Skip to content

Commit

Permalink
Support for touch events
Browse files Browse the repository at this point in the history
  • Loading branch information
joshthompson committed May 2, 2024
1 parent 1b9d019 commit ae87bf4
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 13 deletions.
54 changes: 41 additions & 13 deletions src/components/svg-flow/SvgFlowCanvas.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type Component, createSignal, onMount, onCleanup } from 'solid-js';
import { type Component, createSignal, onMount, onCleanup, Show } from 'solid-js';

import SvgFlowCanvasDefs from './SvgFlowCanvasDefs';
import { useSvgFlowContext } from '../../context/SvgFlowContext';
Expand All @@ -20,7 +20,9 @@ const SvgFlowCanvas: Component<{
if (props.data) setSvgFlow('data', props.data);
if (props.config) setSvgFlow('config', prev => ({ ...prev, ...props.config }));

let svgRef: SVGSVGElement | undefined;
let containerRef: HTMLDivElement | undefined;

const containerResizeObserver = new ResizeObserver(() => setSvgSize());
const setSvgSize = () => {
if (containerRef) {
Expand All @@ -39,11 +41,10 @@ const SvgFlowCanvas: Component<{
if (svgFlow.config.resizeOnInit && svgFlow.data.nodes.length > 1) {
zoomToFit();
}
svgRef?.addEventListener('touchmove', onTouchMove, { passive: false });
});
onCleanup(() => document.documentElement.style.overscrollBehavior = initialOverscroll());



const viewBox = () => {
const { x, y } = svgFlow.canvas;
const width = svgFlow.state.width / svgFlow.canvas.zoom;
Expand Down Expand Up @@ -121,38 +122,65 @@ const SvgFlowCanvas: Component<{
}
};

let lastTouches: TouchList | undefined = undefined;
let prevTouches: TouchList | undefined = undefined;
const touchCenter = (touches: Touch[]) => {
if (svgRef) {
const svgRect = svgRef.getBoundingClientRect();
const sumX = touches.map(touch => touch.pageX).reduce((a, b) => a + b, 0);
const sumY = touches.map(touch => touch.pageY).reduce((a, b) => a + b, 0);
return {
x: (sumX / touches.length - svgRect.x) / svgRect.width,
y: (sumY / touches.length - svgRect.y) / svgRect.height,
};
}
return { x: 0.5, y: 0.5 };
}
const onTouchEnd = () => prevTouches = undefined;
const onTouchMove = (event: TouchEvent) => {
if (lastTouches) {
event.preventDefault();
if (prevTouches?.length === event.touches.length) {
if (event.touches.length === 1) {
const deltaX = event.touches[0].pageX - lastTouches[0].pageX;
const deltaY = event.touches[0].pageY - lastTouches[0].pageY;
setSvgFlow('canvas', 'x', prev => prev + deltaX / svgFlow.canvas.zoom);
setSvgFlow('canvas', 'y', prev => prev + deltaY / svgFlow.canvas.zoom);
const deltaX = event.touches[0].pageX - prevTouches[0].pageX;
const deltaY = event.touches[0].pageY - prevTouches[0].pageY;
setSvgFlow('canvas', 'x', prev => prev - deltaX / svgFlow.canvas.zoom);
setSvgFlow('canvas', 'y', prev => prev - deltaY / svgFlow.canvas.zoom);
}
if (event.touches.length === 2) {
const prevDist = Math.sqrt(
(prevTouches[0].pageX - prevTouches[1].pageX) ** 2 +
(prevTouches[0].pageY - prevTouches[1].pageY) ** 2
);
const dist = Math.sqrt(
(event.touches[0].pageX - event.touches[1].pageX) ** 2 +
(event.touches[0].pageY - event.touches[1].pageY) ** 2
);
const center = touchCenter([...event.touches]);
zoom(dist / prevDist, center.x, center.y);
}
}
lastTouches = event.touches;
prevTouches = event.touches;
}
const onTouchEnd = () => lastTouches = undefined;

return (
<div ref={containerRef} style={containerStyle()}>
<SvgFlowCanvasControls />
<svg
ref={svgRef}
xmlns='http://www.w3.org/2000/svg'
viewBox={viewBox()}
style={svgStyle()}
onMouseDown={onMouseDown}
onWheel={onScroll}
onTouchMove={onTouchMove}
onTouchEnd={onTouchEnd}
>
<SvgFlowCanvasBackground />
<SvgFlowCanvasDefs />
<SvgFlowCanvasConnections />
<SvgFlowCanvasNodes nodeComponent={props.nodeComponent} />
</svg>
{ false && <SvgFlowDebug /> }
<Show when={svgFlow.config.showDebug}>
<SvgFlowDebug />
</Show>
</div>
);
};
Expand Down
1 change: 1 addition & 0 deletions src/context/SvgFlowContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const DefaultSvgFlowConfig: SvgFlow['config'] = {
autoNodeHeight: true,
resizeOnInit: true,
showControls: true,
showDebug: false,
width: '800px',
height: '500px',
};
Expand Down
1 change: 1 addition & 0 deletions src/models/canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export interface SvgFlowConfig {
stroke?: string;
strokeWidth?: number;
showControls?: boolean;
showDebug?: boolean;
width?: string;
height?: string;
}
Expand Down

0 comments on commit ae87bf4

Please sign in to comment.