steveruizok / perfect-freehand

Draw perfect pressure-sensitive freehand lines.
https://perfectfreehand.com
MIT License
4.52k stars 159 forks source link

syncing pointer to SVG #25

Closed Heydon closed 3 years ago

Heydon commented 3 years ago

Really love this tool; draws beautifully!

Something I'm having trouble with is keeping the pointer events / coords synced to the SVG.

It appears I can only get an accurate pointer location—directly under the cursor—if the SVG's viewBox matches its width and height in px. This can be addressed by dynamically updating the viewBox, as in this example: https://codesandbox.io/s/objective-violet-e9ck1?file=/src/App.vue.

As you can see, I do this viewBox translation on mounting the component with the setDimensions function. The remaining issue regards responsive design. If the browser is resized or I zoom out—and the SVG changes size as a result—this goes out of sync again. I have tried using a resizeObserver to address this (commented out) but it means the drawing/path nolonger scales with the SVG.

Is there something about the tool that I don't understand or have missed that would make this easier? Or would I have to do something like add a viewBox-to-path-coords translation layer 😣?

Thanks!

colbyn commented 3 years ago

@Heydon I presume you're asking about scaling the drawing to always fit within the browser viewport. This is pretty easy, just define your dimensions in the SVG viewbox, and the browser will automatically scale your drawing.

For example, this isn't using the perfect freehand JS lib, but my solution is essentially what I've been using over here.

steveruizok commented 3 years ago

Heya, this isn't a perfect-freehand specific issue so I'm moving to discussions.

👉 But here's the fix: just remove the viewBox property!

Your example with just that line removed.

You never have to provide a viewBox to an <svg> element; and in most cases, I would suggest you don't provide one. If you styling an <svg> element with CSS and leave the viewBox off, then the browser will solve the coordinate space automatically—solving problems like the one you have here.

If you need to crop, zoom, etc, then I'd suggest transforming a <g> element rather than using the viewBox. (I've tried things both ways and the <g> approach is better.)