Skip to main content

useGesture

The following example moves a target by dragging.

When dragging, the states of x and y are changed.

When dragging starts, holding state becomes true, and when dragging ends, holding changes to false.

Reactive Adapter

const REACTIVE_ADAPTER = ({ setEvents, emit, onInit, onDestroy, getProps }) => {
setEvents(["dragStart", "drag", "dragEnd"]);
const obj = reactive({
x: 0,
y: 0,
holding: false,
});
const ref = getProps().ref;

let startClientX = 0;
let startClientY = 0;
let startX = 0;
let startY = 0;

const onDragStart = (e) => {
obj.holding = true;
startClientX = e.clientX;
startClientY = e.clientY;
startX = obj.x;
startY = obj.y;
emit("dragStart", e);
};
const onDrag = e => {
if (!obj.holding) {
return;
}
obj.x = startX + e.clientX - startClientX;
obj.y = startY + e.clientY - startClientY;
emit("drag", e);
};
const onDragEnd = e => {
if (!obj.holding) {
return;
}
emit("dragEnd", e);
obj.holding = false;
};
onInit(() => {
const element = ref.value || ref.current;
element?.addEventListener("mousedown", onDragStart);
window.addEventListener("mousemove", onDrag);
window.addEventListener("mouseup", onDragEnd);
});

onDestroy(() => {
const element = ref.value || ref.current;
element?.removeEventListener("mousedown", onDragStart);
window.removeEventListener("mousemove", onDrag);
window.removeEventListener("mouseup", onDragEnd);
});
return obj;
};

Frameworks

You can create a Reactive Component by importing the @cfcs/react module and using the useReactive function.

import React from "react";
import { useReactive } from "@cfcs/react";

function useGesture() {
const ref = React.useRef(null);

return Object.assign(useReactive(ADAPTER, () => ({ ref })), {
ref,
});
}
export function App() {
const {
ref,
x, y, holding,
onDragStart,
onDrag,
onDragEnd,
} = useGesture();

onDragStart(() => {
console.log("drag start");
}, []);
onDrag(() => {
console.log("drag");
}, []);
onDragEnd(() => {
console.log("drag end");
}, []);

return <div
ref={ref}
style={{
...
background: holding ? "#8C532E" : "#F5C721",
transform: `translate(${x}px, ${y}px`,
}}
></div>;
}