diff --git a/.changeset/many-jeans-tan.md b/.changeset/many-jeans-tan.md new file mode 100644 index 000000000..5dac58d1c --- /dev/null +++ b/.changeset/many-jeans-tan.md @@ -0,0 +1,6 @@ +--- +'@antv/g-lite': patch +'@antv/g-plugin-canvas-path-generator': patch +--- + +fix: `markerStartOffset`/`markerEndOffset` of the path in the svg/canvas renderer is drawn abnormally diff --git a/__tests__/demos/bugfix/1760.ts b/__tests__/demos/bugfix/1760.ts new file mode 100644 index 000000000..ea0ba6512 --- /dev/null +++ b/__tests__/demos/bugfix/1760.ts @@ -0,0 +1,61 @@ +import { Canvas, Path, Line } from '@antv/g'; + +/** + * @see https://github.com/antvis/G/issues/1760 + * @see https://github.com/antvis/G/issues/1790 + * @see https://github.com/antvis/G/pull/1808 + */ +export async function issue_1760(context: { canvas: Canvas }) { + const { canvas } = context; + await canvas.ready; + + const arrowMarker = new Path({ + style: { + d: 'M 10,10 L -10,0 L 10,-10 Z', + stroke: '#1890FF', + transformOrigin: 'center', + }, + }); + const arrowMarker1 = new Path({ + style: { + d: 'M 10,10 L -10,0 L 10,-10 Z', + stroke: '#ff90FF', + transformOrigin: 'center', + }, + }); + + const path = new Path({ + style: { + lineWidth: 1, + stroke: '#54BECC', + // d: 'M 0,40 L 100,100', + // d: 'M 10,100 L 100,100', + d: 'M 10,100 Q 100,100 150,150', + // d: 'M 10,100 C 100,100 150,150 180,200', + // d: 'M 10,100 A 30 50 0 0 1 162.55 162.45', + // d: 'M 10,100 A 30 50 0 0 0 162.55 162.45', + markerStart: arrowMarker, + markerStartOffset: 30, + markerEnd: arrowMarker1, + markerEndOffset: 30, + }, + }); + + const line = new Line({ + style: { + x1: 10, + y1: 150, + x2: 100, + y2: 150, + lineWidth: 1, + stroke: '#54BECC', + markerStart: arrowMarker, + markerStartOffset: 30, + markerEnd: arrowMarker, + markerEndOffset: 30, + }, + }); + + canvas.appendChild(path); + canvas.appendChild(line); +} diff --git a/__tests__/demos/bugfix/index.ts b/__tests__/demos/bugfix/index.ts index f48122b8c..96e15b67c 100644 --- a/__tests__/demos/bugfix/index.ts +++ b/__tests__/demos/bugfix/index.ts @@ -7,3 +7,4 @@ export { shadowroot_offset } from './1677'; export { gradient_text } from './1572'; export { zoom } from './1667'; export { test_pick } from './1747'; +export { issue_1760 } from './1760'; diff --git a/babel.config.mjs b/babel.config.mjs index 025ea934b..f22b25d61 100644 --- a/babel.config.mjs +++ b/babel.config.mjs @@ -1,6 +1,11 @@ // See https://babeljs.io/docs/en/configuration export default { + /** + * @see https://babeljs.io/docs/options#targets + * default is es5 + */ + // targets: '', assumptions: { privateFieldsAsProperties: true, setPublicClassFields: true, diff --git a/demo/issues/issue-1760.html b/demo/issues/issue-1760.html deleted file mode 100644 index 4b4a1006f..000000000 --- a/demo/issues/issue-1760.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - issue-1760 - - - - -
- - - - - diff --git a/packages/g-lite/src/utils/path.ts b/packages/g-lite/src/utils/path.ts index ec204cb80..e5df1195d 100644 --- a/packages/g-lite/src/utils/path.ts +++ b/packages/g-lite/src/utils/path.ts @@ -959,41 +959,34 @@ export function translatePathToString( (nextSegment[0] === 'M' || nextSegment[0] === 'Z'))) && endOffsetX !== 0 && endOffsetY !== 0; + const [startOffsetXTemp, startOffsetYTemp] = useStartOffset + ? [startOffsetX, startOffsetY] + : [0, 0]; + const [endOffsetXTemp, endOffsetYTemp] = useEndOffset + ? [endOffsetX, endOffsetY] + : [0, 0]; switch (command) { case 'M': - // Use start marker offset - if (useStartOffset) { - return `M ${params[1] + startOffsetX},${ - params[2] + startOffsetY - } L ${params[1]},${params[2]}`; - } - return `M ${params[1]},${params[2]}`; + return `M ${params[1] + startOffsetXTemp},${params[2] + startOffsetYTemp}`; case 'L': - return `L ${params[1] + (useEndOffset ? endOffsetX : 0)},${ - params[2] + (useEndOffset ? endOffsetY : 0) + return `L ${params[1] + endOffsetXTemp},${ + params[2] + endOffsetYTemp }`; + case 'Q': - return `Q ${params[1]} ${params[2]},${params[3]} ${params[4]}${ - useEndOffset - ? ` L ${params[3] + endOffsetX},${params[4] + endOffsetY}` - : '' - }`; + return `Q ${params[1]} ${params[2]},${params[3] + endOffsetXTemp} ${params[4] + endOffsetYTemp}`; + case 'C': - return `C ${params[1]} ${params[2]},${params[3]} ${params[4]},${params[5]} ${params[6]}${ - useEndOffset - ? ` L ${params[5] + endOffsetX},${params[6] + endOffsetY}` - : '' - }`; + return `C ${params[1]} ${params[2]},${params[3]} ${params[4]},${params[5] + endOffsetXTemp} ${params[6] + endOffsetYTemp}`; + case 'A': - return `A ${params[1]} ${params[2]} ${params[3]} ${params[4]} ${params[5]} ${params[6]} ${params[7]}${ - useEndOffset - ? ` L ${params[6] + endOffsetX},${params[7] + endOffsetY}` - : '' - }`; + return `A ${params[1]} ${params[2]} ${params[3]} ${params[4]} ${params[5]} ${params[6] + endOffsetXTemp} ${params[7] + endOffsetYTemp}`; + case 'Z': return 'Z'; + default: return null; } diff --git a/packages/g-plugin-canvas-path-generator/src/paths/Path.ts b/packages/g-plugin-canvas-path-generator/src/paths/Path.ts index a5800a62c..2c9898d2f 100644 --- a/packages/g-plugin-canvas-path-generator/src/paths/Path.ts +++ b/packages/g-plugin-canvas-path-generator/src/paths/Path.ts @@ -48,28 +48,31 @@ export function generatePath( (nextSegment && (nextSegment[0] === 'M' || nextSegment[0] === 'Z'))) && endOffsetX !== 0 && endOffsetY !== 0; + const [startOffsetXTemp, startOffsetYTemp] = useStartOffset + ? [startOffsetX, startOffsetY] + : [0, 0]; + const [endOffsetXTemp, endOffsetYTemp] = useEndOffset + ? [endOffsetX, endOffsetY] + : [0, 0]; switch (command) { case 'M': // Use start marker offset - if (useStartOffset) { - context.moveTo(params[1] + startOffsetX, params[2] + startOffsetY); - } else { - context.moveTo(params[1], params[2]); - } + context.moveTo( + params[1] + startOffsetXTemp, + params[2] + startOffsetYTemp, + ); break; case 'L': - if (useEndOffset) { - context.lineTo(params[1] + endOffsetX, params[2] + endOffsetY); - } else { - context.lineTo(params[1], params[2]); - } + context.lineTo(params[1] + endOffsetXTemp, params[2] + endOffsetYTemp); break; case 'Q': - context.quadraticCurveTo(params[1], params[2], params[3], params[4]); - if (useEndOffset) { - context.lineTo(params[3] + endOffsetX, params[4] + endOffsetY); - } + context.quadraticCurveTo( + params[1], + params[2], + params[3] + endOffsetXTemp, + params[4] + endOffsetYTemp, + ); break; case 'C': context.bezierCurveTo( @@ -77,14 +80,12 @@ export function generatePath( params[2], params[3], params[4], - params[5], - params[6], + params[5] + endOffsetXTemp, + params[6] + endOffsetYTemp, ); - if (useEndOffset) { - context.lineTo(params[5] + endOffsetX, params[6] + endOffsetY); - } break; case 'A': { + // FIXME startOffset / endOffset const { arcParams } = segments[i]; const { cx, cy, rx, ry, startAngle, endAngle, xRotation, sweepFlag } = arcParams;