Skip to content

Commit

Permalink
Replace SVG shadow renderer
Browse files Browse the repository at this point in the history
Safari doesn't do drop shadows, so the new code renders a circle with a
gradient circle to achieve a similar effect.
  • Loading branch information
anoek committed Aug 26, 2024
1 parent 01e3f25 commit 9a920d3
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 16 deletions.
2 changes: 1 addition & 1 deletion engine/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "goban-engine",
"version": "8.3.29",
"version": "8.3.30",
"description": "",
"main": "build/goban-engine.js",
"types": "build/engine/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "goban",
"version": "8.3.29",
"version": "8.3.30",
"description": "",
"main": "build/goban.js",
"types": "build/src/index.d.ts",
Expand Down
3 changes: 3 additions & 0 deletions src/Goban/SVGRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3231,6 +3231,9 @@ export class SVGRenderer extends Goban implements GobanSVGInterface {
__theme_cache.black[themes.black] = {};
}

this.theme_white.preRenderShadowSVG(this.svg_defs, "black");
this.theme_white.preRenderShadowSVG(this.svg_defs, "white");

for (const radius of [this.theme_stone_radius, MoveTree.stone_radius]) {
__theme_cache.white[themes.white][radius] = this.theme_white.preRenderWhiteSVG(
this.svg_defs,
Expand Down
77 changes: 63 additions & 14 deletions src/Goban/themes/GobanTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,66 @@ export class GobanTheme {
radius,
),
);

return ret;
}

public preRenderShadowSVG(defs: SVGDefsElement, color: string): void {
/* Radial gradient for shadow */
const radial_gradient = document.createElementNS(
"http://www.w3.org/2000/svg",
"radialGradient",
);
radial_gradient.setAttribute("id", "shadow-" + color);
radial_gradient.setAttribute("r", "1.0");

// solid stone color
const stop1 = document.createElementNS("http://www.w3.org/2000/svg", "stop");
stop1.setAttribute("offset", "0");
stop1.setAttribute("stop-color", color);
stop1.setAttribute("stop-opacity", "1.0");
radial_gradient.appendChild(stop1);
const stop2 = document.createElementNS("http://www.w3.org/2000/svg", "stop");
stop2.setAttribute("offset", "30%");
stop2.setAttribute("stop-color", color);
stop2.setAttribute("stop-opacity", "1.0");
radial_gradient.appendChild(stop2);

const shadow_color = "#333333";

{
const shadow_stop = document.createElementNS("http://www.w3.org/2000/svg", "stop");
shadow_stop.setAttribute("offset", "31%");
shadow_stop.setAttribute("stop-color", shadow_color);
shadow_stop.setAttribute("stop-opacity", "0.6");
radial_gradient.appendChild(shadow_stop);
}

{
const shadow_stop = document.createElementNS("http://www.w3.org/2000/svg", "stop");
shadow_stop.setAttribute("offset", "34%");
shadow_stop.setAttribute("stop-color", shadow_color);
shadow_stop.setAttribute("stop-opacity", "0.50");
radial_gradient.appendChild(shadow_stop);
}
{
const shadow_stop = document.createElementNS("http://www.w3.org/2000/svg", "stop");
shadow_stop.setAttribute("offset", "40%");
shadow_stop.setAttribute("stop-color", shadow_color);
shadow_stop.setAttribute("stop-opacity", "0.5");
radial_gradient.appendChild(shadow_stop);
}
{
const shadow_stop = document.createElementNS("http://www.w3.org/2000/svg", "stop");
shadow_stop.setAttribute("offset", "50%");
shadow_stop.setAttribute("stop-color", shadow_color);
shadow_stop.setAttribute("stop-opacity", "0.0");
radial_gradient.appendChild(shadow_stop);
}

defs.appendChild(radial_gradient);
}

/* Places a pre rendered stone onto the canvas, centered at cx, cy */
public placeWhiteStone(
ctx: CanvasRenderingContext2D,
Expand Down Expand Up @@ -196,18 +253,10 @@ export class GobanTheme {
"http://www.w3.org/2000/svg",
"circle",
);
circle_to_cast_shadow.setAttribute("class", "shadow");
circle_to_cast_shadow.setAttribute("fill", color);
circle_to_cast_shadow.setAttribute("cx", cx.toString());
circle_to_cast_shadow.setAttribute("cy", cy.toString());
circle_to_cast_shadow.setAttribute("r", (radius * 0.9).toString());
const sx = radius * 0.15;
const sy = radius * 0.15;
const softness = radius * 0.1;
circle_to_cast_shadow.setAttribute(
"style",
`filter: drop-shadow(${sx}px ${sy}px ${softness}px rgba(0,0,0,0.4)`,
);
circle_to_cast_shadow.setAttribute("fill", `url(#shadow-${color})`);
circle_to_cast_shadow.setAttribute("cx", (cx * 1.2).toString());
circle_to_cast_shadow.setAttribute("cy", (cy * 1.2).toString());
circle_to_cast_shadow.setAttribute("r", (radius * 0.95).toString());
shadow_cell.appendChild(circle_to_cast_shadow);
return circle_to_cast_shadow;
}
Expand Down Expand Up @@ -240,7 +289,7 @@ export class GobanTheme {
cy: number,
radius: number,
): [SVGElement, SVGElement | undefined] {
return this.placeStoneSVG(cell, shadow_cell, stone, cx, cy, radius, "#eeeeee");
return this.placeStoneSVG(cell, shadow_cell, stone, cx, cy, radius, "white");
}

public placeBlackStoneSVG(
Expand All @@ -251,7 +300,7 @@ export class GobanTheme {
cy: number,
radius: number,
): [SVGElement, SVGElement | undefined] {
return this.placeStoneSVG(cell, shadow_cell, stone, cx, cy, radius, "#222222");
return this.placeStoneSVG(cell, shadow_cell, stone, cx, cy, radius, "black");
}

/* Resolve which stone graphic we should use. By default we just pick a
Expand Down

0 comments on commit 9a920d3

Please sign in to comment.