Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(lib-classifier): canvas context for SVG drawing tools #6491

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

eatyourgreens
Copy link
Contributor

@eatyourgreens eatyourgreens commented Nov 23, 2024

Make sure that SVGContext.canvas is a reference to the SVG rect element that's used as a drawing canvas, so that creating new drawing marks and editing existing marks both use the same screen CTM when calculating the pointer position in SVG space.

This fixes a bug in Firefox where the draggable decorator doesn't correctly track the active pointer, in the context of a zoomed SVG image.

Please request review from @zooniverse/frontend team or an individual member of that team.

Package

  • lib-classifier

Linked Issue and/or Talk Post

How to Review

On I Fancy Cats, you should be able to draw while zoomed in, without seeing any of the mismatched positioning described in #6490. You can try it out by drawing an ellipse while zoomed in, or by placing a point then dragging the point to a new position.

Try it out in Firefox and Chrome, while zoomed in and also after rotating the image. Pointer interactions should be correctly mapped to the SVG image now, regardless of any external transformation.

While drawing, in any browser, you should be able to pan and zoom with the keyboard too.

The stroke width of drawn marks should also stay the same as you zoom in. Lines shouldn’t be thicker at increased magnification.

Checklist

PR Creator - Please cater the checklist to fit the review needed for your code changes.
PR Reviewer - Use the checklist during your review. Each point should be checkmarked or discussed before PR approval.

General

  • Tests are passing locally and on Github
  • Documentation is up to date and changelog has been updated if appropriate
  • You can yarn panic && yarn bootstrap or docker-compose up --build and FEM works as expected
  • FEM works in all major desktop browsers: Firefox, Chrome, Edge, Safari (Use Browserstack account as needed)
  • FEM works in a mobile browser

General UX

Example Staging Project: i-fancy-cats

  • All pages of a FEM project load: Home Page, Classify Page, and About Pages
  • Can submit a classification
  • Can sign-in and sign-out
  • The component is accessible

Bug Fix

  • The PR creator has listed user actions to use when testing if bug is fixed
  • The bug is fixed
  • Unit tests are added or updated

Comment on lines +80 to +51
const svgContext = useContext(SVGContext)
const canvasRef = useRef()
svgContext.canvas = canvasRef.current
Copy link
Contributor Author

@eatyourgreens eatyourgreens Nov 23, 2024

Choose a reason for hiding this comment

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

I'm not 100% sure if this is the best way to update a reference within a context object, but it works in Chrome, Safari, and Firefox.

SVGContext.canvas is a reference to the element that the draggable decorator (and drawing tools in general) will use to calculate the screen CTM for pointer interactions (ie. to get SVG coordinates from pointer coordinates.)

@coveralls
Copy link

coveralls commented Nov 23, 2024

Coverage Status

coverage: 77.364% (+0.01%) from 77.354%
when pulling 5219203 on eatyourgreens:fix-svg-canvas-context
into 3e8f2ee on zooniverse:master.

@@ -68,7 +66,6 @@ function SingleImageViewer({
transform={transform}
>
<SVGImageCanvas
ref={canvasLayer}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This ref was originally used for dragging interactions, which caused the Firefox bug.

@mcbouslog mcbouslog self-requested a review November 25, 2024 16:07
@mcbouslog mcbouslog self-assigned this Nov 26, 2024
@eatyourgreens eatyourgreens force-pushed the fix-svg-canvas-context branch 2 times, most recently from 22f3fae to 79fea74 Compare December 3, 2024 00:31
@mcbouslog
Copy link
Contributor

mcbouslog commented Dec 5, 2024

I think this has broken dragging/pan with the mouse (across browsers). In pan/zoom mode, when clicking then dragging the subject image, I get the following console error:

Uncaught TypeError: Cannot read properties of undefined (reading 'getScreenCTM')
    at getEventOffset (draggable.js:38:83)

However, if I remove the changes to SingleImageViewer I think mouse dragging/panning works and Firefox zoomed in drawn marks dragging works as expected. I need to wrap my head around why, but posting an update.

@eatyourgreens
Copy link
Contributor Author

eatyourgreens commented Dec 5, 2024

Oh, I think that might be because the draggable image is dragged in a different context to draggable drawing marks. Marks should get the CTM from the rect that defines the drawing canvas, but the image is rendered separately.

The fix here was for the drawn marks, so it probably would break the draggable image.

@eatyourgreens
Copy link
Contributor Author

eatyourgreens commented Dec 6, 2024

However, if I remove the changes to SingleImageViewer I think mouse dragging/panning works and Firefox zoomed in drawn marks dragging works as expected.

I tried this quickly, but it breaks the drawing tools. Dragging the image also doesn't work as expected with the CTM that's used by the drawing tools. I'm not sure why the image and drawing tools are using different CTMs.

I find that clicking and dragging a zoomed-in image, after drawing some marks, causes the image to jump around unexpectedly. I think you mentioned this bug, or a similar bug, on #6390. The transformation matrix for clicks on the image is generating the wrong x,y coordinates in SVG space.

@eatyourgreens
Copy link
Contributor Author

I'll push my changes up, since they're easy to revert and this branch is already broken anyway.

@eatyourgreens eatyourgreens force-pushed the fix-svg-canvas-context branch 3 times, most recently from 0e7a945 to 960252c Compare December 6, 2024 20:54
@eatyourgreens
Copy link
Contributor Author

Since pushing my latest commit, I'm not seeing those problems any more in Firefox, so maybe I've fixed the problem? It's still bothering me a bit that the image and drawn marks are using different transformation matrixes. It seems like both should have the same transformations applied to them.

@eatyourgreens
Copy link
Contributor Author

eatyourgreens commented Dec 11, 2024

Thinking about this some more, currentTarget might be a more robust way to get the DOM node that is currently handling pointer events. It would simplify the interfaces for draggable behaviour too.

EDIT: I tried this. It breaks the coordinate transformations for drag handles, which are rendered relative to the parent mark.

const transform = `translate(${x}, ${y}) scale(${1 / scale})`

Make sure that `SVGContext.canvas` is a reference to the SVG `rect` element that's used as a drawing canvas, so that creating new drawing marks and editing existing marks both use the same screen CTM when calculating the pointer position.

This fixes a bug in Firefox where the `draggable` decorator doesn't correctly track the active pointer, in the context of a zoomed SVG image.
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.

Drawing is broken for zoomed-in images in Firefox
3 participants