Skip to content

Commit

Permalink
refactor: use native browser SVG scaling for drawing tools
Browse files Browse the repository at this point in the history
- remove manual scaling code from `strokeWidth` for all the SVG drawing marks. To be honest, it has never worked very well.
- add `vector-effect="non-scaling-stroke"` to all the SVG drawing marks. This will make the displayed stroke width independent of the scaling of the SVG element, at all zoom levels.
- style marks with `:focus-visible` so that the focus ring is only shown for keyboard interactions.
  • Loading branch information
eatyourgreens committed May 8, 2024
1 parent 045a642 commit eb85430
Show file tree
Hide file tree
Showing 12 changed files with 45 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const ConsensusLine = styled('g')`
cursor: pointer;
filter: drop-shadow(1px 1px 4px #5c5c5c);
&:focus {
&:focus-visible {
${props => css`outline: solid 4px ${props.focusColor};`}
}
Expand Down Expand Up @@ -69,9 +69,7 @@ function TranscribedLines({
/** Show/hide previously transcribed lines. */
visible,
} = useTranscriptionReductions()
const {
theme = defaultTheme
} = useTheme()
const theme = useTheme()
const [ bounds, setBounds ] = useState({})
const [ line, setLine ] = useState(defaultLine)
const [ show, setShow ] = useState(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ function Circle({ active, mark, onFinish, scale }) {
y2={handleY}
strokeWidth={guideWidth}
strokeDasharray={GUIDE_DASH}
vectorEffect={'non-scaling-stroke'}
/>
<DragHandle
scale={scale}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ const DragHandle = forwardRef(function DragHandle(

return (
<g ref={ref} transform={transform} data-testid={testid} {...props} >
<StyledCircle r={radius} {...styleProps} />
<StyledCircle r={2 * radius} fill='transparent' stroke='transparent' />
<StyledCircle r={radius} {...styleProps} vectorEffect={'non-scaling-stroke'} />
<StyledCircle r={2 * radius} fill='transparent' stroke='transparent' vectorEffect={'non-scaling-stroke'} />
</g>
)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function Ellipse({ active, mark, onFinish, scale }) {

return (
<g onPointerUp={active ? onFinish : undefined}>
<ellipse rx={rx} ry={ry} />
<ellipse rx={rx} ry={ry} vectorEffect={'non-scaling-stroke'} />

{active && (
<g>
Expand All @@ -34,6 +34,7 @@ function Ellipse({ active, mark, onFinish, scale }) {
y2='0'
strokeWidth={guideWidth}
strokeDasharray={GUIDE_DASH}
vectorEffect={'non-scaling-stroke'}
/>
<line
x1='0'
Expand All @@ -42,6 +43,7 @@ function Ellipse({ active, mark, onFinish, scale }) {
y2={-1 * ry}
strokeWidth={guideWidth}
strokeDasharray={GUIDE_DASH}
vectorEffect={'non-scaling-stroke'}
/>
<DragHandle dragMove={onXHandleDrag} x={rx} y={0} scale={scale} />
<DragHandle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ function Line({ active, mark, onFinish, scale }) {

return (
<g onPointerUp={active ? onFinish : undefined}>
<line x1={x1} y1={y1} x2={x2} y2={y2} />
<line x1={x1} y1={y1} x2={x2} y2={y2} vectorEffect={'non-scaling-stroke'} />
<line
x1={x1}
y1={y1}
x2={x2}
y2={y2}
strokeWidth={GRAB_STROKE_WIDTH / scale}
strokeWidth={GRAB_STROKE_WIDTH}
strokeOpacity='0'
vectorEffect={'non-scaling-stroke'}
/>
{active && (
<DragHandle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const STROKE_WIDTH = 2
const SELECTED_STROKE_WIDTH = 4

const StyledGroup = styled('g')`
&:focus {
&:focus-visible {
${(props) =>
css`
outline: solid 4px ${props.focusColor};
Expand Down Expand Up @@ -164,7 +164,7 @@ const Mark = forwardRef(function Mark(
ref={markRoot}
role='button'
strokeWidth={
isActive ? SELECTED_STROKE_WIDTH / scale : STROKE_WIDTH / scale
isActive ? SELECTED_STROKE_WIDTH : STROKE_WIDTH
}
tabIndex={disabled ? -1 : 0}
transform={transform}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const CROSSHAIR_WIDTH = 1
function Point({ active, children, mark, onFinish, scale }) {
const { size } = mark.tool
const crosshairSpace = CROSSHAIR_SPACE / scale
const crosshairWidth = CROSSHAIR_WIDTH / scale
const crosshairWidth = CROSSHAIR_WIDTH
const selectedRadius = SELECTED_RADIUS[size] / scale
const radius = RADIUS[size] / scale

Expand All @@ -29,30 +29,33 @@ function Point({ active, children, mark, onFinish, scale }) {
x2='0'
y2={-1 * selectedRadius}
strokeWidth={crosshairWidth}
vectorEffect={'non-scaling-stroke'}
/>
<line
x1={-1 * crosshairSpace * selectedRadius}
y1='0'
x2={-1 * selectedRadius}
y2='0'
strokeWidth={crosshairWidth}
vectorEffect={'non-scaling-stroke'}
/>
<line
x1='0'
y1={crosshairSpace * selectedRadius}
x2='0'
y2={selectedRadius}
strokeWidth={crosshairWidth}
vectorEffect={'non-scaling-stroke'}
/>
<line
x1={crosshairSpace * selectedRadius}
y1='0'
x2={selectedRadius}
y2='0'
strokeWidth={crosshairWidth}
vectorEffect={'non-scaling-stroke'}
/>
<circle r={active ? selectedRadius : radius} />
{children}
<circle r={active ? selectedRadius : radius} vectorEffect={'non-scaling-stroke'} />
</g>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ const GuideLine = styled.line`
`

const RADIUS = 3
const STROKE_WIDTH = 3
const GUIDELINE_STROKE_WIDTH = 2
const GUIDELINE_STROKE_WIDTH = 1
const GRAB_STROKE_WIDTH = 6

function Polygon({ active, mark, scale, onFinish }) {
Expand All @@ -25,9 +24,8 @@ function Polygon({ active, mark, scale, onFinish }) {
} = mark

const radius = RADIUS / scale
const strokeWidth = STROKE_WIDTH / scale
const guideLineStrokeWidth = GUIDELINE_STROKE_WIDTH / scale
const grabStrokeWidth = GRAB_STROKE_WIDTH / scale
const guideLineStrokeWidth = GUIDELINE_STROKE_WIDTH
const grabStrokeWidth = GRAB_STROKE_WIDTH

function onUndoDrawing() {
mark.shortenPath()
Expand All @@ -53,14 +51,15 @@ function Polygon({ active, mark, scale, onFinish }) {
)}

/* Visible lines */
<polyline points={path} strokeWidth={strokeWidth} fill='none' />
<polyline points={path} fill='none' vectorEffect={'non-scaling-stroke'} />

/* So users can easily select the polygon */
<polyline
points={path}
strokeWidth={grabStrokeWidth}
strokeOpacity='0'
fill={fill}
vectorEffect={'non-scaling-stroke'}
/>

/* To visibly show a closed polygon */
Expand All @@ -69,10 +68,9 @@ function Polygon({ active, mark, scale, onFinish }) {
y1={lastPoint.y}
x2={initialPoint.x}
y2={initialPoint.y}
strokeWidth={strokeWidth}
strokeDasharray={strokeDasharray}
vectorEffect={'non-scaling-stroke'}
/>
)}

{active &&
points.map((point, i) => (
Expand Down Expand Up @@ -101,6 +99,7 @@ function Polygon({ active, mark, scale, onFinish }) {
y2={guideLineY}
strokeWidth={guideLineStrokeWidth}
strokeDasharray='2 2'
vectorEffect={'non-scaling-stroke'}
/>
)}
</g>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ function Rectangle({ active, mark, onFinish, scale }) {
y={y_top}
width={width}
height={height}
strokeWidth={GRAB_STROKE_WIDTH / scale}
strokeWidth={GRAB_STROKE_WIDTH}
strokeOpacity='0'
vectorEffect={'non-scaling-stroke'}
/>
{active && (
<DragHandle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function RotateRectangle({
scale = 1
}) {
const { angle, height, width, x_center, y_center } = mark
const guideWidth = GUIDE_WIDTH / scale
const guideWidth = GUIDE_WIDTH

const x_left = x_center - width / 2
const x_right = x_center + width / 2
Expand All @@ -41,14 +41,15 @@ function RotateRectangle({

return (
<g onPointerUp={active ? onFinish : undefined}>
<rect x={x_left} y={y_top} width={width} height={height} />
<rect x={x_left} y={y_top} width={width} height={height} vectorEffect={'non-scaling-stroke'} />
<rect
x={x_left}
y={y_top}
width={width}
height={height}
strokeWidth={GRAB_STROKE_WIDTH / scale}
strokeWidth={GRAB_STROKE_WIDTH}
strokeOpacity='0'
vectorEffect={'non-scaling-stroke'}
/>
{/* Rotate Handle */}
{active && (
Expand All @@ -60,6 +61,7 @@ function RotateRectangle({
y2={y_center}
strokeWidth={guideWidth}
strokeDasharray={GUIDE_DASH}
vectorEffect={'non-scaling-stroke'}
/>
<RotateHandle
dragMove={onRotateDrag}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function FreehandLine({ active, mark, onFinish, scale }) {
mark.setScale(scale)

// Stroke width varies as a function of the zoom level. Ranges 1-5.75
const STROKE_WIDTH = (scale < 3) ? (4 - scale) : 1
const STROKE_WIDTH = 1

function onDoubleClick(event) {
if (active) {
Expand Down Expand Up @@ -123,8 +123,9 @@ function FreehandLine({ active, mark, onFinish, scale }) {
strokeLinejoin: 'round',
strokeLinecap: 'round',
fill: 'none',
strokeOpacity: 1,
strokeOpacity: 1
}}
vectorEffect={'non-scaling-stroke'}
/>
<title>{getHoverText()}</title>
<path // Main Path that's clickable. Not visible as its thick for click purposes
Expand All @@ -136,6 +137,7 @@ function FreehandLine({ active, mark, onFinish, scale }) {
strokeWidth: GRAB_STROKE_WIDTH / scale
}}
fill='none'
vectorEffect={'non-scaling-stroke'}
/>
</Fragment>
})}
Expand All @@ -145,6 +147,7 @@ function FreehandLine({ active, mark, onFinish, scale }) {
strokeDasharray='2 2'
strokeWidth={STROKE_WIDTH}
opacity=".4"
vectorEffect={'non-scaling-stroke'}
/>

{active && mark.closePoint &&
Expand All @@ -153,6 +156,7 @@ function FreehandLine({ active, mark, onFinish, scale }) {
r={FINISHER_RADIUS / scale}
cx={mark.closePoint.x}
cy={mark.closePoint.y}
vectorEffect={'non-scaling-stroke'}
/>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,9 @@ const TranscriptionLineMark = forwardRef((props, ref) => {
fill={color}
ref={ref}
stroke={color}
strokeWidth={2}
>
<line x1={x1 + offsetX} y1={y1 + offsetY} x2={x2} y2={y2} />
<line x1={x1} y1={y1} x2={x2} y2={y2} strokeWidth={GRAB_STROKE_WIDTH / scale} strokeOpacity='0' />
<line x1={x1 + offsetX} y1={y1 + offsetY} x2={x2} y2={y2} vectorEffect={'non-scaling-stroke'} />
<line x1={x1} y1={y1} x2={x2} y2={y2} strokeWidth={GRAB_STROKE_WIDTH} strokeOpacity='0' vectorEffect={'non-scaling-stroke'} />

{active ?
<DragHandle
Expand All @@ -58,6 +57,7 @@ const TranscriptionLineMark = forwardRef((props, ref) => {
fill='transparent'
r={handleRadius}
stroke='currentColor'
vectorEffect={'non-scaling-stroke'}
/>
}
{active ?
Expand All @@ -74,6 +74,7 @@ const TranscriptionLineMark = forwardRef((props, ref) => {
fill='currentColor'
r={handleRadius}
stroke='currentColor'
vectorEffect={'non-scaling-stroke'}
/>
}

Expand All @@ -86,13 +87,15 @@ const TranscriptionLineMark = forwardRef((props, ref) => {
fill="transparent"
onPointerDown={handlePointerDown}
onPointerUp={handleFinishClick}
vectorEffect={'non-scaling-stroke'}
/>
<circle
r={handleRadius}
cx={x2}
cy={y2}
onPointerDown={handlePointerDown}
onPointerUp={handleFinishClick}
vectorEffect={'non-scaling-stroke'}
/>
</g>
}
Expand Down

0 comments on commit eb85430

Please sign in to comment.