Skip to content

Comments

feat(extensions): add StrokeStyleExtension for dashed strokes on SDF layers#9976

Open
chrisgervang wants to merge 6 commits intomasterfrom
claude/implement-feature-9864-rWt7o
Open

feat(extensions): add StrokeStyleExtension for dashed strokes on SDF layers#9976
chrisgervang wants to merge 6 commits intomasterfrom
claude/implement-feature-9864-rWt7o

Conversation

@chrisgervang
Copy link
Collaborator

@chrisgervang chrisgervang commented Feb 1, 2026

Summary

Implements feature request #9864 - adds StrokeStyleExtension to enable dashed strokes on SDF-based layers.

Supported Layers

  • ScatterplotLayer: Dashed circle strokes using angle-based calculation around the circumference
  • TextBackgroundLayer: Dashed rectangle strokes using perimeter-based calculation (including rounded corners)

New Props (via extension)

  • getDashArray: [dashSize, gapSize] relative to stroke width
  • dashGapPickable: Whether gaps are pickable (default: false)

Usage

import {ScatterplotLayer} from '@deck.gl/layers';
import {StrokeStyleExtension} from '@deck.gl/extensions';

new ScatterplotLayer({
  stroked: true,
  getDashArray: [3, 2],
  extensions: [new StrokeStyleExtension({dash: true})]
});

https://claude.ai/code/session_01KsGs1v7AGFNXyvMUhjaiFm


Note

Medium Risk
Introduces new shader injections and layer type detection that affect rendering/picking behavior for supported layers; risk is contained to opt-in usage via the new extension.

Overview
Adds a new StrokeStyleExtension that enables dashed stroke rendering for SDF-based layers by injecting layer-specific shader code and wiring a new instanced instanceDashArrays attribute plus a dashGapPickable uniform.

Updates the public extensions surface (modules/extensions/src/index.ts) and docs navigation to include the new extension, and adds a runnable Vite example.

Extends test coverage with new unit tests for attribute/uniform updates and adds new render golden test cases for dashed ScatterplotLayer variants (plus a minor formatting-only change in the scatterplot fragment shader).

Written by Cursor Bugbot for commit 71c76f9. This will update automatically on new commits. Configure here.

@chrisgervang chrisgervang changed the title feat(extensions): add StrokeStyleExtension for dashed circle strokes feat(extensions): add StrokeStyleExtension for dashed strokes on SDF layers Feb 1, 2026
pos = arcBottomLeft + leftEdge + arcTopLeft + topEdge + angle / (PI * 0.5) * arcTopRight;
}
// Right edge
else if (pixelPos.x >= max(pixelPos.y, height - pixelPos.y) && pixelPos.y >= rBottomRight && pixelPos.y <= height - rTopRight) {
Copy link

Choose a reason for hiding this comment

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

Incorrect edge detection for non-square rounded rectangles

Medium Severity

The strokeStyle_getPerimeterPosition function uses diagonal-based region detection instead of distance-based detection for determining which edge a pixel belongs to. Conditions like pixelPos.y >= max(pixelPos.x, width - pixelPos.x) for the top edge and pixelPos.x >= max(pixelPos.y, height - pixelPos.y) for the right edge fail for non-square rectangles. For a 200x100 rectangle, a pixel at (100, 99) is 1 pixel from the top but gets classified as "right edge" because 99 >= 100 is false. The non-rounded version strokeStyle_getRectPerimeterPosition correctly uses actual distance calculations.

Fix in Cursor Fix in Web

@chrisgervang chrisgervang added this to the v9.3 milestone Feb 2, 2026
claude and others added 5 commits February 6, 2026 08:26
Add a new StrokeStyleExtension that enables rendering dashed strokes on
ScatterplotLayer circle outlines. This implements feature request #9864.

The extension uses shader injection to calculate dash patterns based on
the angle around the circle's circumference. It supports:
- getDashArray accessor: [solidLength, gapLength] relative to stroke width
- dashGapPickable prop: controls whether gaps are pickable

When a circle is both stroked and filled, the fill color shows through
the gaps. When only stroked (no fill), fragments in gaps are discarded.

https://claude.ai/code/session_01KsGs1v7AGFNXyvMUhjaiFm
…ndLayer

Add support for dashed strokes on TextBackgroundLayer rectangles in addition
to ScatterplotLayer circles. The extension now auto-detects the layer type
and uses the appropriate shader injection:

- ScatterplotLayer: angle-based dash calculation around circle circumference
- TextBackgroundLayer: perimeter-based dash calculation around rectangle edges

No performance impact on ScatterplotLayer since each layer type gets only
its specific shader code at compile time.

https://claude.ai/code/session_01KsGs1v7AGFNXyvMUhjaiFm
…calculation

The perimeter position calculation now properly accounts for rounded
corners in TextBackgroundLayer. When borderRadius is set:
- Corner arcs are included in the perimeter length calculation
- Position along corner arcs uses angle-based interpolation
- Each corner can have a different radius (vec4 borderRadius)

This ensures dash patterns flow smoothly around rounded corners
without discontinuities.

https://claude.ai/code/session_01KsGs1v7AGFNXyvMUhjaiFm
Add comprehensive documentation for the new StrokeStyleExtension including:
- Usage examples for ScatterplotLayer and TextBackgroundLayer
- API reference for getDashArray and dashGapPickable props
- Explanation of how dash calculation works for circles vs rectangles
- Comparison table with PathStyleExtension
- Details on rounded corner support for TextBackgroundLayer

https://claude.ai/code/session_01KsGs1v7AGFNXyvMUhjaiFm
- Add examples/stroke-style-test for interactive testing
- Apply linter formatting to test file

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chrisgervang chrisgervang force-pushed the claude/implement-feature-9864-rWt7o branch from 105108f to 4fb089b Compare February 6, 2026 16:26
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

vec2 cornerCenter = vec2(rBottomLeft, rBottomLeft);
vec2 toPixel = pixelPos - cornerCenter;
float angle = atan(toPixel.x, -toPixel.y); // 0 at bottom, PI/2 at left
pos = (PI * 0.5 - angle) / (PI * 0.5) * arcBottomLeft;
Copy link

Choose a reason for hiding this comment

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

Corner angle formulas produce wrong perimeter positions

High Severity

The bottom-left and top-left corner arc angle calculations in strokeStyle_getPerimeterPosition are incorrect. In both corners, the atan arguments produce results in the range (-PI/2, 0), but the formulas assume the range (0, PI/2). For the bottom-left corner, atan(toPixel.x, -toPixel.y) yields (-PI/2, 0) since toPixel.x < 0 and -toPixel.y > 0, causing positions to be offset by +arcBottomLeft. For the top-left corner, the same issue causes positions to decrease through the arc instead of increasing, creating a direction reversal. Both produce visible dash pattern discontinuities at these corners.

Additional Locations (1)

Fix in Cursor Fix in Web

…sion docs

TextBackgroundLayer is an internal layer without its own documentation page.
Link to TextLayer instead since TextBackgroundLayer is used internally by it.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants