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 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import cuid from 'cuid'
import PropTypes from 'prop-types'
import { useRef, useState } from 'react';
import { useContext, useRef, useState } from 'react';
import styled, { css } from 'styled-components'

import SVGContext from '@plugins/drawingTools/shared/SVGContext'
import { convertEvent } from '@plugins/drawingTools/components/draggable/draggable'
import DrawingToolMarks from './components/DrawingToolMarks'
import TranscribedLines from './components/TranscribedLines'
import SubTaskPopup from './components/SubTaskPopup'
Expand Down Expand Up @@ -43,7 +46,9 @@ function InteractionLayer({
duration
}) {
const [creating, setCreating] = useState(false)
const canvas = useRef()
const svgContext = useContext(SVGContext)
const canvasRef = useRef()
svgContext.canvas = canvasRef.current
Comment on lines +49 to +51
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.)


if (creating && !activeMark) {
setCreating(false)
Expand All @@ -54,42 +59,6 @@ function InteractionLayer({
setActiveMark(undefined)
}

function convertEvent(event) {
const type = event.type

const svgEventOffset = getEventOffset(event)

const svgCoordinateEvent = {
pointerId: event.pointerId,
type,
x: svgEventOffset.x,
y: svgEventOffset.y
}

return svgCoordinateEvent
}

function createPoint(event) {
const { clientX, clientY } = event
// SVG 2 uses DOMPoint
if (window.DOMPointReadOnly) {
return new DOMPointReadOnly(clientX, clientY)
}
// jsdom doesn't support SVG
return {
x: clientX,
y: clientY
}
}

function getEventOffset(event) {
const svgPoint = createPoint(event)
const svgEventOffset = svgPoint.matrixTransform
? svgPoint.matrixTransform(canvas.current?.getScreenCTM().inverse())
: svgPoint
return svgEventOffset
}

function createMark(event) {
const timeStamp = getFixedNumber(played, 5)
const mark = activeTool.createMark({
Expand All @@ -99,7 +68,7 @@ function InteractionLayer({
toolIndex: activeToolIndex
})

mark.initialPosition(convertEvent(event))
mark.initialPosition(convertEvent(event, canvasRef.current))
setActiveMark(mark)
setCreating(true)
mark.setSubTaskVisibility(false)
Expand All @@ -124,7 +93,7 @@ function InteractionLayer({
}

if (creating) {
activeTool?.handlePointerDown?.(convertEvent(event), activeMark)
activeTool?.handlePointerDown?.(convertEvent(event, canvasRef.current), activeMark)
if (activeMark.finished) onFinish(event)
return true
}
Expand All @@ -136,7 +105,7 @@ function InteractionLayer({
function onPointerMove(event) {
cancelEvent(event)
if (creating) {
activeTool?.handlePointerMove?.(convertEvent(event), activeMark)
activeTool?.handlePointerMove?.(convertEvent(event, canvasRef.current), activeMark)
}
}

Expand All @@ -149,7 +118,7 @@ function InteractionLayer({
function onPointerUp(event) {
cancelEvent(event)
if (creating) {
activeTool?.handlePointerUp?.(convertEvent(event), activeMark)
activeTool?.handlePointerUp?.(convertEvent(event, canvasRef.current), activeMark)
if (activeMark.finished) onFinish(event)
}
}
Expand All @@ -165,7 +134,7 @@ function InteractionLayer({
return (
<>
<DrawingCanvas
ref={canvas}
ref={canvasRef}
disabled={disabled || move}
pointerEvents={move ? 'none' : 'all'}
width={width}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,10 @@ function SingleImageViewer({
zoomControlFn = null,
zooming = false
}) {
const canvasLayer = useRef()
const canvas = canvasLayer.current
const transform = `rotate(${rotate} ${width / 2} ${height / 2})`

return (
<SVGContext.Provider value={{ canvas, viewBox, rotate, width, height }}>
<SVGContext.Provider value={{ viewBox, rotate, width, height }}>
{zoomControlFn && (
<ZoomControlButton
onClick={zoomControlFn}
Expand Down Expand Up @@ -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.

viewBox={viewBox}
>
{children}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function getEventOffset(event, canvas) {
return svgEventOffset
}

function convertEvent(event, canvas) {
export function convertEvent(event, canvas) {
const svgEventOffset = getEventOffset(event, canvas)
const svgCoordinateEvent = {
type: event.type,
Expand Down