Skip to content

feat: support outerBorder / innerBorder for polygon graphic - #2103

Merged
xuefei1313 merged 2 commits into
VisActor:developfrom
g1f9:feat/polygon-outer-border
Jul 29, 2026
Merged

feat: support outerBorder / innerBorder for polygon graphic#2103
xuefei1313 merged 2 commits into
VisActor:developfrom
g1f9:feat/polygon-outer-border

Conversation

@g1f9

@g1f9 g1f9 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Closes #2102

What

outerBorder / innerBorder are implemented per graphic type in the render contributions. rect / arc / circle / symbol have them; polygon-contribution-render.ts only re-exports texture and background, so configuring outerBorder on a polygon silently renders nothing.

This adds the polygon implementation.

How

  • common/polygon.tsoffsetPolygonPoints(points, distance)
    Offsets every edge along its normal and intersects adjacent offset lines to get an equidistant outline. The polygon's signed area decides the normal direction, so a positive distance always expands outwards regardless of vertex winding; innerBorder passes a negative distance. Degenerate (zero-length) and collinear edges fall back to the original vertex, so no NaN coordinate can reach the path.

  • polygon-contribution-render.tsDefaultPolygonRenderContribution
    Mirrors the rect contribution: afterFillStroke, honours keepStrokeScale / getScaledStroke, supports strokeCb. Corner radius is shifted by the same distance (max(0, cornerRadius ± d)) so the border stays equidistant from the outline instead of drifting at the corners. Registered in DefaultCanvasPolygonRender.builtinContributions.

    It also reproduces rect's opacity inject/restore around setStrokeStyle — the theme defaults for outerBorder carry strokeOpacity but no opacity, and without the injection setStrokeStyle bails out silently and the border is stroked with leftover canvas state. See the issue for details.

  • graphic/polygon.ts
    updatePolygonAABBBoundsImprecise now calls updateBoundsOfCommonOuterBorder, same as rect — otherwise the border sits outside the AABB and the dirty rect clips it on incremental repaints.

Verification

Verified against the equivalent change backported into 1.1.5 and running in our product (funnel charts in VChart, both the funnel body and the conversion bands are polygons):

  • outerBorder renders as a closed ring equidistant from the trapezoid, following the rounded corners;
  • innerBorder renders on the inside;
  • the graphic's own stroke is untouched (which was the whole point — writing stroke directly would overwrite it);
  • no repaint artefacts once the AABB includes the border.

No behaviour change for polygons that don't configure a border: the contribution returns immediately when neither outerBorder nor innerBorder is set.

@g1f9
g1f9 changed the base branch from main to develop July 26, 2026 11:19
@g1f9
g1f9 force-pushed the feat/polygon-outer-border branch from 39d02f3 to e31507c Compare July 27, 2026 06:54

@xuefei1313 xuefei1313 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

发现 3 个需要修正的边界条件,均已附在对应行:缩放下 AABB 与实际边框坐标不一致、凹角圆角偏移方向错误,以及重复顶点在圆角分支中仍会产生 NaN。

strokeBoundsBuffer = defaultOuterBorder.strokeBoundsBuffer
} = outerBorder;

offsetPolygonPoints(points, distance as number, closePath).forEach(point => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 这里的 AABB 没有和实际绘制使用同一坐标空间。keepStrokeScale 默认为 false 时,渲染端会用 getScaledStrokedistance 转为局部坐标;例如 scaleX = scaleY = 0.5distance = 10 时,绘制的局部偏移是 20(屏幕上仍是 10),但这里仅偏移 10,随后再被矩阵缩小为屏幕上的 5。增量重绘会因此漏清/裁掉外边框。请在这里使用等价的局部缩放距离(或在变换后的坐标中合并边界),并覆盖缩小变换的回归测试。

if (noCorner) {
drawPolygon(context.camera ? context : context.nativeContext, nextPoints, x, y);
} else {
drawRoundedPolygon(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] offsetPolygonPoints 虽然让重复顶点的结果保持有限值,但圆角分支仍会把重复点传给 drawRoundedPolygon。现有 duplicate-edge 测试的输入只要再设置 cornerRadius: 2,该函数就在该顶点得到 length2 = 0,随后 getProportionPoint 发生 0 / 0 并将 NaN 写入 lineTo/arcTo。Polygon 目前接受重复顶点,请在圆角绘制前收敛退化边,或让 drawRoundedPolygon 跳过零长度边,并补充实际 border-render 回归测试。

@g1f9
g1f9 force-pushed the feat/polygon-outer-border branch from e31507c to c543c0f Compare July 28, 2026 09:10

@xuefei1313 xuefei1313 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上轮提出的凹角圆角、重复顶点和图元自身缩放场景均已处理;但非缩放边框在父级缩放下的 AABB 仍会漏算,需修正后再合入。

Comment thread packages/vrender-core/src/graphic/graphic-service/polygon-outer-border-bounds.ts Outdated
Add equidistant polygon border outlines and register the polygon render
contribution.

Handle transformed bounds, open paths, convex and concave rounded corners,
and degenerate or duplicate edges without emitting non-finite coordinates.
Add focused geometry, bounds, and render regression coverage.
@g1f9
g1f9 force-pushed the feat/polygon-outer-border branch from c543c0f to 7fb3d28 Compare July 29, 2026 07:43

@xuefei1313 xuefei1313 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

发现两处需要在合并前修复的问题:动态修改 outerBorder 后的边界失效,以及 keepStrokeScale 未传递给边框线宽。详情见行内评论。

Comment thread packages/vrender-core/src/graphic/polygon.ts

@xuefei1313 xuefei1313 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已复核修复:state patch 触发 Polygon 外边框 bounds 失效,且边框绘制与 bounds 均遵循 keepStrokeScale。已补充回归用例,并通过全包测试。

@xuefei1313
xuefei1313 merged commit 18e6b59 into VisActor:develop Jul 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] polygon does not render outerBorder / innerBorder

2 participants