Version
@visactor/vrender-core@1.1.5, also reproduces on main (dfae0a4).
Describe the bug
Setting outerBorder (or innerBorder) on a polygon graphic renders nothing — no error, no border. The same configuration works on rect / arc / circle / symbol.
We hit this building a "selected" state for funnel charts in VChart (both the funnel body and the conversion bands are polygons). Falling back to writing stroke directly is not equivalent: it overwrites the border the graphic itself is configured with, whereas outerBorder is supposed to be a separate ring outside it.
Root cause
outerBorder / innerBorder are implemented per graphic type in the render contributions:
| graphic |
contribution |
border |
| rect |
rect-contribution-render.ts |
✅ |
| arc |
arc-contribution-render.ts |
✅ |
| circle |
circle-contribution-render.ts |
✅ |
| symbol |
symbol-contribution-render.ts |
✅ |
| polygon |
polygon-contribution-render.ts |
❌ only re-exports texture / background |
packages/vrender-core/src/graphic/polygon.ts also never calls updateBoundsOfCommonOuterBorder, so even once the border is drawn its AABB would be too small and the dirty rect would clip it.
Reproduce
const polygon = createPolygon({
points: [{ x: 0, y: 0 }, { x: 120, y: 0 }, { x: 90, y: 60 }, { x: 30, y: 60 }],
fill: '#4e83fd',
outerBorder: { stroke: '#ff0000', lineWidth: 1, distance: 3 }
});
Expected: a red ring 3px outside the trapezoid. Actual: nothing is drawn.
Expected behavior
polygon behaves like rect / arc / circle / symbol: outerBorder / innerBorder are rendered, and the AABB accounts for the border.
Note for whoever implements it
There is a trap worth knowing about. context.setStrokeStyle(graphic, borderStyle, x, y, defaultParams) destructures opacity from defaultParams, and the theme defaults for outerBorder only carry strokeOpacity, not opacity. With opacity === undefined the undefined > 1e-12 guard fails and the whole style block is silently skipped, so the border gets stroked with whatever canvas state the previous graphic left behind. rect works around this by temporarily injecting the graphic's own opacity into the theme border object and restoring it afterwards; any new implementation needs the same dance. (We lost a while on this — a runtime probe showed strokeStyle / lineWidth completely unchanged across the border draw.)
PR to follow.
Version
@visactor/vrender-core@1.1.5, also reproduces onmain(dfae0a4).Describe the bug
Setting
outerBorder(orinnerBorder) on apolygongraphic renders nothing — no error, no border. The same configuration works onrect/arc/circle/symbol.We hit this building a "selected" state for funnel charts in VChart (both the funnel body and the conversion bands are polygons). Falling back to writing
strokedirectly is not equivalent: it overwrites the border the graphic itself is configured with, whereasouterBorderis supposed to be a separate ring outside it.Root cause
outerBorder/innerBorderare implemented per graphic type in the render contributions:rect-contribution-render.tsarc-contribution-render.tscircle-contribution-render.tssymbol-contribution-render.tspolygon-contribution-render.tspackages/vrender-core/src/graphic/polygon.tsalso never callsupdateBoundsOfCommonOuterBorder, so even once the border is drawn its AABB would be too small and the dirty rect would clip it.Reproduce
Expected: a red ring 3px outside the trapezoid. Actual: nothing is drawn.
Expected behavior
polygonbehaves likerect/arc/circle/symbol:outerBorder/innerBorderare rendered, and the AABB accounts for the border.Note for whoever implements it
There is a trap worth knowing about.
context.setStrokeStyle(graphic, borderStyle, x, y, defaultParams)destructuresopacityfromdefaultParams, and the theme defaults forouterBorderonly carrystrokeOpacity, notopacity. Withopacity === undefinedtheundefined > 1e-12guard fails and the whole style block is silently skipped, so the border gets stroked with whatever canvas state the previous graphic left behind.rectworks around this by temporarily injecting the graphic's ownopacityinto the theme border object and restoring it afterwards; any new implementation needs the same dance. (We lost a while on this — a runtime probe showedstrokeStyle/lineWidthcompletely unchanged across the border draw.)PR to follow.