svgdotjs / svg.js

The lightweight library for manipulating and animating SVG
https://svgjs.dev
Other
10.95k stars 1.07k forks source link

How can I draw a Polyline from a svg => g => svg => rect (responsive) to an Dom Element on the right side? #1314

Closed ChimingPhang closed 2 weeks ago

ChimingPhang commented 4 months ago

i have below layout:

<container>
<left>
<svg style="width: 100%; height: 100%" viewBox="0 0 1391 1" >
   <g>
       <svg x="100" y="100" width="1191" height="1685" viewBox="0 0 1191 1685">
        <image />
        <rect />
       </svg>
   </g>
</svg>
</left>
<right>
   <item id="item-1" />
   <item id="item-2" />
</right>
</container>

Want to click rect and draw a polyline to item-1. Stuck in the position of item-1's top.

Anyone can give me a tips? I would be very grateful.

enter image description here

Have tried bbox, getBoundingClientRect, all are not correct.

elliottmejia commented 3 months ago

Yep! Those methods are methods. You can't call those on as they are not within the SVG class.

So this won't work:

const foo = SVG('#foo')
let posX = foo.getBoundingClientRect().x

Why? Because #foo's DOM position is not provided to the SVG class during instantiation.

However, this will work, because the HTMLElement has an instantiated {x,y} position within its node.

// ... draw() instantiation
// ...
const getHTMLElementPositionById = (selector) => {
    const { x , y } = document.getElementById(selector).getBoundingClientRect()
    // or spread whatever else you need
    return { x , y }
}
const { fooX, fooY } = getHTMLElementPositionById('foo')
const { barX , barY } = getHTMLElementPositionById('bar)
draw.line(fooX, fooY, barX, barY)

Any positional data should be collected upon instantiation if heavy positional manipulation is required- this can be done by putting svgs into other elements in the DOM tree and using them as references in the case that things move.

SVG.js elements have getters and setters for position, but these are abstracted from the DOM position of these elements. Unless provided in the constructor and/or manipulated later, you're not going to be able to get positional information from referencing your SVG object.

I would try again by instantiating the SVG class with native attributes.

If an element is already instantiated and THEN provided to the SVG class, its position will be {0,0}:{ x , y}. This is not a valid way to get the position of these elements unless they are instantiated with x and y values, in which case the getter can provide this information. Otherwise, these values were not set in the constructor of the instance and will return their relative value to their initial position when a positional getter is called.