Skip to content

[Bug] polygon does not render outerBorder / innerBorder #2102

Description

@g1f9

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions