Skip to content

Commit 2c8b56c

Browse files
committed
feat: add background-color and text-color parameters
- Add background-color (default: transparent) and text-color (default: black) inputs - Render background rect in SVG output - Apply text color to collision text paths - Web app reads colors from trajectory response - Update README (EN & ZH) with new parameters - Add tests for custom colors
1 parent 95be4d3 commit 2c8b56c

11 files changed

Lines changed: 78 additions & 8 deletions

File tree

‎README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ Inspired by [Orta Therox](https://github.com/Orta). Thanks Orta for your outstan
3737
| `sample-rate` | ❌ | `4` | Trajectory sample rate (higher = smaller SVG, less smooth animation) |
3838
| `shape` | ❌ | `circle` | Shape of contribution blocks: `circle` or `square` |
3939
| `text-top` | ❌ | `50` | Distance from the top of the world to the text |
40+
| `background-color` | ❌ | `transparent` | Background color of the SVG (CSS color value) |
41+
| `text-color` | ❌ | `black` | Color of the collision text (CSS color value) |
4042

4143
### Outputs
4244

‎README_zh.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
| `sample-rate` | ❌ | `4` | 轨迹采样率(越大文件越小,动画越不流畅) |
3838
| `shape` | ❌ | `circle` | 贡献方块的形状(`circle` 或 `square`) |
3939
| `text-top` | ❌ | `50` | 文字距离世界顶部的距离,控制文字垂直位置 |
40+
| `background-color` | ❌ | `transparent` | SVG 背景颜色(CSS 颜色值) |
41+
| `text-color` | ❌ | `black` | 碰撞文字颜色(CSS 颜色值) |
4042

4143
### 输出
4244

‎__tests__/integration.test.ts‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ describe('full pipeline integration', () => {
5555
expect(svg).toContain('<circle')
5656
expect(svg).toContain('animateTransform')
5757
expect(svg).toContain('<path d="')
58+
// Default background is transparent
59+
expect(svg).toContain('fill="transparent"')
60+
// Default text color is black
61+
expect(svg).toContain('fill="black"')
5862
})
5963

6064
it('generates square-shaped contributions when shape is square', async () => {
@@ -113,4 +117,26 @@ describe('full pipeline integration', () => {
113117

114118
expect(svg1).toBe(svg2)
115119
})
120+
121+
it('uses custom background color', async () => {
122+
const svg = await gensvg({
123+
username: 'testuser',
124+
text: 'Hi',
125+
fontSize: 40,
126+
backgroundColor: '#1a1a2e'
127+
})
128+
129+
expect(svg).toContain('fill="#1a1a2e"')
130+
})
131+
132+
it('uses custom text color', async () => {
133+
const svg = await gensvg({
134+
username: 'testuser',
135+
text: 'Hi',
136+
fontSize: 40,
137+
textColor: '#ff0000'
138+
})
139+
140+
expect(svg).toContain('fill="#ff0000"')
141+
})
116142
})

‎action.yml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ inputs:
3333
description: Distance from the top of the world to the text (controls vertical text position)
3434
required: false
3535
default: '50'
36+
background-color:
37+
description: Background color of the SVG (CSS color value)
38+
required: false
39+
default: transparent
40+
text-color:
41+
description: Color of the collision text (CSS color value)
42+
required: false
43+
default: black
3644

3745
outputs:
3846
svg-path:

‎src/app.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ Bun.serve({
1616
await startSimulation({
1717
username: GITHUB_ID,
1818
text: TEXT,
19-
sampleRate: 8
19+
sampleRate: 8,
20+
backgroundColor: '#fff',
21+
textColor: '#eb510a'
2022
})
2123
)
2224
},

‎src/gensvg.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { HEIGHT, SCALE, SIZE, WIDTH } from './utils'
1010
* @returns 完整的 SVG 字符串
1111
*/
1212
export async function gensvg(options: SimulationOptions): Promise<string> {
13+
const backgroundColor = options.backgroundColor || 'transparent'
14+
const textColor = options.textColor || 'black'
1315
const result: SimulationResult = await startSimulation(options)
1416

1517
const svgWidth = WIDTH * SCALE
@@ -57,7 +59,7 @@ export async function gensvg(options: SimulationOptions): Promise<string> {
5759
// 用 path 渲染文字路径,与物理碰撞体坐标对齐
5860
// opentype 坐标 → SVG 坐标: svgX = (opentypeX + offsetX) * SCALE, svgY = (HEIGHT - centerY + opentypeY) * SCALE
5961
const textPathsSvg = result.textPaths
60-
.map(({ pathData }) => ` <path d="${pathData}" fill="black" />`)
62+
.map(({ pathData }) => ` <path d="${pathData}" fill="${textColor}" />`)
6163
.join('\n')
6264

6365
const textGroupSvg = `
@@ -71,6 +73,7 @@ ${textPathsSvg}
7173
height="${svgHeight}"
7274
viewBox="0 0 ${svgWidth} ${svgHeight}"
7375
>
76+
<rect width="${svgWidth}" height="${svgHeight}" fill="${backgroundColor}" />
7477
${contributionsSvg}
7578
${textGroupSvg}
7679
</svg>`

‎src/main.ts‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@ export async function run(): Promise<void> {
2424
const sampleRate: number = parseInt(core.getInput('sample-rate') || '4', 10)
2525
const shape: string = core.getInput('shape') || 'circle'
2626
const textTop: number = parseInt(core.getInput('text-top') || '50', 10)
27+
const backgroundColor: string =
28+
core.getInput('background-color') || 'transparent'
29+
const textColor: string = core.getInput('text-color') || 'black'
2730

2831
core.info(`Generating gravity SVG for user: ${username}`)
2932
core.info(
30-
`Text: "${text}", Font size: ${fontSize}, Sample rate: ${sampleRate}, Shape: ${shape}, Text top: ${textTop}`
33+
`Text: "${text}", Font size: ${fontSize}, Sample rate: ${sampleRate}, Shape: ${shape}, Text top: ${textTop}, Background: ${backgroundColor}, Text color: ${textColor}`
3134
)
3235

3336
const svg = await gensvg({
@@ -36,7 +39,9 @@ export async function run(): Promise<void> {
3639
fontSize,
3740
sampleRate,
3841
shape,
39-
textTop
42+
textTop,
43+
backgroundColor,
44+
textColor
4045
})
4146

4247
writeFileSync(outputPath, svg, 'utf-8')

‎src/physics.ts‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ export interface SimulationOptions {
113113
sampleRate?: number
114114
/** 贡献方块的形状:circle(圆形)或 square(方形)。圆形物理模拟更丝滑,不容易穿模。 */
115115
shape?: string
116+
/** 背景颜色,默认透明 */
117+
backgroundColor?: string
118+
/** 文字颜色,默认黑色 */
119+
textColor?: string
116120
}
117121

118122
export async function startSimulation({
@@ -122,7 +126,9 @@ export async function startSimulation({
122126
fontSize = 80,
123127
stepTime = 8,
124128
sampleRate = 4,
125-
shape = 'circle'
129+
shape = 'circle',
130+
backgroundColor = 'transparent',
131+
textColor = 'black'
126132
}: SimulationOptions): Promise<SimulationResult> {
127133
const world = await createWord()
128134
const contributionsSet = new Set<Contribution>()
@@ -270,6 +276,8 @@ export async function startSimulation({
270276
textTriangles,
271277
offsetX,
272278
centerY,
273-
stepTime
279+
stepTime,
280+
backgroundColor,
281+
textColor
274282
}
275283
}

‎src/utils/index.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,8 @@ export interface SimulationResult {
4444
centerY: number
4545
/** 一步的时间(ms) */
4646
stepTime: number
47+
/** 背景颜色 */
48+
backgroundColor: string
49+
/** 文字颜色 */
50+
textColor: string
4751
}

‎src/web/index.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
<body
2525
style="display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #ddd;margin:0;">
26-
<div style="background-color: white;font-size: 0;">
26+
<div style="font-size: 0;">
2727
<svg id="canvas"></svg>
2828
</div>
2929
<script type="module" src="./index.ts"></script>

0 commit comments

Comments
 (0)