Skip to content

Instantly share code, notes, and snippets.

@sslotsky
Created February 20, 2023 00:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sslotsky/03a290263e038987b2ca968c19f65abc to your computer and use it in GitHub Desktop.
Save sslotsky/03a290263e038987b2ca968c19f65abc to your computer and use it in GitHub Desktop.
A qwik component to track the change in movement for both mouse and single-touch dragging. Accepts all div attributes as well as children.
import {
component$,
HTMLAttributes,
QRL,
Slot,
useSignal,
useTask$,
} from "@builder.io/qwik";
interface Movement {
changeX: number;
changeY: number;
}
interface Props extends HTMLAttributes<HTMLDivElement> {
tracking: boolean;
callback$: QRL<(movement: Movement) => void>;
}
export default component$((props: Props) => {
const { tracking, callback$, ...divProps } = props;
const lastTouch = useSignal<[number, number]>();
useTask$(({ track }) => {
track(() => tracking);
if (!tracking) {
lastTouch.value = undefined;
}
});
return (
<div
{...divProps}
onTouchMove$={(e) => {
if (tracking) {
const [touch] = e.changedTouches;
if (lastTouch.value) {
const [lastX, lastY] = lastTouch.value;
const changeX = touch.clientX - lastX;
const changeY = touch.clientY - lastY;
callback$({ changeX, changeY });
}
lastTouch.value = [touch.clientX, touch.clientY];
}
}}
onPointerMove$={(e) => {
if (tracking) {
callback$({
changeX: e.movementX,
changeY: e.movementY,
});
}
}}
>
<Slot />
</div>
);
});
@sslotsky
Copy link
Author

Example usage

  return (
    <DragTracker
      class="wrapper"
      tracking={cropper.moving}
      callback$={(movement) => {
        props.store.cropperLeft = Math.max(
          0,
          Math.min(
            props.store.cropperLeft + movement.changeX,
            (props.imageRef.value?.clientWidth || 0) - props.store.cropperWidth
          )
        );
        props.store.cropperTop = Math.max(
          0,
          Math.min(
            props.store.cropperTop + movement.changeY,
            (props.imageRef.value?.clientHeight || 0) -
              props.store.cropperHeight
          )
        );
      }}
    >

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment