From baa240c52542aaeb7eca683606ac01c283656588 Mon Sep 17 00:00:00 2001 From: Adnane Belmadiaf Date: Thu, 26 Dec 2024 20:06:05 +0100 Subject: [PATCH] fix(ArrowAnnotate): use svg marker to draw the arrow fix #1671 --- packages/tools/src/drawingSvg/drawArrow.ts | 50 +------------------ packages/tools/src/drawingSvg/drawLine.ts | 49 ++++++++++++------ packages/tools/src/drawingSvg/drawPolyline.ts | 6 +++ packages/tools/src/store/addEnabledElement.ts | 15 ++++++ 4 files changed, 58 insertions(+), 62 deletions(-) diff --git a/packages/tools/src/drawingSvg/drawArrow.ts b/packages/tools/src/drawingSvg/drawArrow.ts index b4283b81be..83b3ddaed1 100644 --- a/packages/tools/src/drawingSvg/drawArrow.ts +++ b/packages/tools/src/drawingSvg/drawArrow.ts @@ -18,7 +18,7 @@ export default function drawArrow( const { color, width, lineWidth, lineDash } = Object.assign( { color: 'rgb(0, 255, 0)', - width: '2', + width: 2, lineWidth: undefined, lineDash: undefined, }, @@ -31,52 +31,6 @@ export default function drawArrow( width, lineWidth, lineDash, + markerEndId: 'arrow', }); - - // Drawing the head arrow with two lines - // Variables to be used when creating the arrow - const headLength = 10; - const angle = Math.atan2(end[1] - start[1], end[0] - start[0]); - - const firstLine = { - start: [ - end[0] - headLength * Math.cos(angle - Math.PI / 7), - end[1] - headLength * Math.sin(angle - Math.PI / 7), - ] as Types.Point2, - end: end, - }; - - const secondLine = { - start: [ - end[0] - headLength * Math.cos(angle + Math.PI / 7), - end[1] - headLength * Math.sin(angle + Math.PI / 7), - ] as Types.Point2, - end: end, - }; - - drawLine( - svgDrawingHelper, - annotationUID, - '2', - firstLine.start, - firstLine.end, - { - color, - width, - lineWidth, - } - ); - - drawLine( - svgDrawingHelper, - annotationUID, - '3', - secondLine.start, - secondLine.end, - { - color, - width, - lineWidth, - } - ); } diff --git a/packages/tools/src/drawingSvg/drawLine.ts b/packages/tools/src/drawingSvg/drawLine.ts index 63910135c0..7b7d26146d 100644 --- a/packages/tools/src/drawingSvg/drawLine.ts +++ b/packages/tools/src/drawingSvg/drawLine.ts @@ -11,7 +11,16 @@ export default function drawLine( lineUID: string, start: Types.Point2, end: Types.Point2, - options = {}, + options: { + color?: string; + width?: number; + lineWidth?: number; + lineDash?: string; + markerStartId?: string; + markerMidId?: string; + markerEndId?: string; + shadow?: boolean; + }, dataId = '' ): void { // if length is NaN return @@ -19,16 +28,15 @@ export default function drawLine( return; } - const { color, width, lineWidth, lineDash, shadow } = Object.assign( - { - color: 'rgb(0, 255, 0)', - width: '2', - lineWidth: undefined, - lineDash: undefined, - shadow: undefined, - }, - options - ); + const { + color = 'rgb(0, 255, 0)', + width = 10, + lineWidth, + lineDash, + markerStartId = null, + markerEndId = null, + shadow = false, + } = options; // for supporting both lineWidth and width options const strokeWidth = lineWidth || width; @@ -36,9 +44,20 @@ export default function drawLine( const svgns = 'http://www.w3.org/2000/svg'; const svgNodeHash = _getHash(annotationUID, 'line', lineUID); const existingLine = svgDrawingHelper.getSvgNode(svgNodeHash); - const dropShadowStyle = shadow - ? `filter:url(#shadow-${svgDrawingHelper.svgLayerElement.id});` - : ''; + const layerId = svgDrawingHelper.svgLayerElement.id; + const dropShadowStyle = shadow ? `filter:url(#shadow-${layerId});` : ''; + const arrow = svgDrawingHelper.svgLayerElement.querySelector( + `#${markerEndId}-${layerId}` + ); + + console.log('arrow', arrow); + + if (arrow) { + arrow.setAttribute('fill', color); + const newstrokeWidth = strokeWidth >= 4 ? 3 : 6; + arrow.setAttribute('markerWidth', `${newstrokeWidth}`); + arrow.setAttribute('markerHeight', `${newstrokeWidth}`); + } const attributes = { x1: `${start[0]}`, @@ -49,6 +68,8 @@ export default function drawLine( style: dropShadowStyle, 'stroke-width': strokeWidth, 'stroke-dasharray': lineDash, + 'marker-start': markerStartId ? `url(#${markerStartId}-${layerId})` : '', + 'marker-end': markerEndId ? `url(#${markerEndId}-${layerId})` : '', }; if (existingLine) { diff --git a/packages/tools/src/drawingSvg/drawPolyline.ts b/packages/tools/src/drawingSvg/drawPolyline.ts index 5bd2dca851..cdc7d965a0 100644 --- a/packages/tools/src/drawingSvg/drawPolyline.ts +++ b/packages/tools/src/drawingSvg/drawPolyline.ts @@ -23,6 +23,8 @@ export default function drawPolyline( lineWidth?: number; lineDash?: string; closePath?: boolean; + markerStartId?: string; + markerEndId?: string; } ): void { if (points.length < 2) { @@ -37,6 +39,8 @@ export default function drawPolyline( lineWidth, lineDash, closePath = false, + markerStartId = null, + markerEndId = null, } = options; // for supporting both lineWidth and width options @@ -65,6 +69,8 @@ export default function drawPolyline( 'fill-opacity': fillOpacity, 'stroke-width': strokeWidth, 'stroke-dasharray': lineDash, + 'marker-start': markerStartId ? `url(#${markerStartId})` : '', + 'marker-end': markerEndId ? `url(#${markerEndId})` : '', }; if (existingPolyLine) { diff --git a/packages/tools/src/store/addEnabledElement.ts b/packages/tools/src/store/addEnabledElement.ts index 1398ea12c0..fa4b0f797c 100644 --- a/packages/tools/src/store/addEnabledElement.ts +++ b/packages/tools/src/store/addEnabledElement.ts @@ -108,10 +108,25 @@ function _createSvgAnnotationLayer(viewportId: string): SVGElement { feBlend.setAttribute('in2', 'matrixOut'); feBlend.setAttribute('mode', 'normal'); + // arrow marker + const arrowMarker = document.createElementNS(svgns, 'marker'); + arrowMarker.setAttribute('id', `arrow-${svgLayerId}`); + arrowMarker.setAttribute('viewBox', '0 0 10 10'); + arrowMarker.setAttribute('refX', '8'); + arrowMarker.setAttribute('refY', '5'); + arrowMarker.setAttribute('markerWidth', '5'); + arrowMarker.setAttribute('markerHeight', '5'); + arrowMarker.setAttribute('orient', 'auto'); + arrowMarker.setAttribute('stroke', 'none'); + const arrowPath = document.createElementNS(svgns, 'path'); + arrowPath.setAttribute('d', 'M 0 0 L 10 5 L 0 10 z'); + arrowMarker.appendChild(arrowPath); + filter.appendChild(feOffset); filter.appendChild(feColorMatrix); filter.appendChild(feBlend); defs.appendChild(filter); + defs.appendChild(arrowMarker); svgLayer.appendChild(defs); return svgLayer;