diff --git a/engine/package.json b/engine/package.json index 4bc9b75a..04e06dd5 100644 --- a/engine/package.json +++ b/engine/package.json @@ -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", diff --git a/package.json b/package.json index 7a1fdff9..110222e7 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/Goban/SVGRenderer.ts b/src/Goban/SVGRenderer.ts index 62b7d9a6..ac2b83b1 100644 --- a/src/Goban/SVGRenderer.ts +++ b/src/Goban/SVGRenderer.ts @@ -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, diff --git a/src/Goban/themes/GobanTheme.ts b/src/Goban/themes/GobanTheme.ts index 55218979..b097af6b 100644 --- a/src/Goban/themes/GobanTheme.ts +++ b/src/Goban/themes/GobanTheme.ts @@ -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, @@ -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; } @@ -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( @@ -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