UNPKG

use-konva-snapping

Version:

A lightweight React hook for adding snapping functionality to Konva.js elements. It allows objects to snap to stage borders, center, and other shapes, with customizable guidelines and snapping sensitivity.

225 lines (182 loc) 6.47 kB
# use-konva-snapping A lightweight React hook for adding snapping functionality to Konva.js elements. It enables elements to snap to stage borders, the center of the stage, and other shapes, with customizable guidelines and snapping sensitivity. --- # <a href="https://codesandbox.io/p/sandbox/ysz9q6" target="_blank">DEMO</a> ## Features - **Snap to Stage Center**: Snap elements to the center of the Konva stage. - **Snap to Stage Borders**: Snap elements to the edges of the stage. - **Snap to Shapes**: Snap elements to other shapes within the Konva stage. - **Guidelines**: Display visual guidelines when snapping, customizable in terms of color, thickness, and dash style. - **Customizable Snap Range**: Define how close elements need to be to another object for snapping to occur. - **Supports Dragging & Resizing**: Works with both dragging and resizing of Konva shapes. - **Fully Configurable**: Customize snapping behavior, guidelines, and more with simple options. --- ## Installation To install `use-konva-snapping`, you can use npm or yarn: ### Using npm: ```bash npm install use-konva-snapping ``` ### Using yarn: ```bash yarn add use-konva-snapping ``` --- ## Usage Once installed, you can use the `useKonvaSnapping` hook to enable snapping for Konva elements in your React app. Here's how to set it up: ### Step 1: Import the Hook Import the `useKonvaSnapping` hook into your React component. ```javascript import { useKonvaSnapping } from "use-konva-snapping"; ``` ### Step 2: Use the Hook Use the hook to get the snapping functionality and attach it to your Konva elements. Below is an example of a basic implementation where you can add draggable shapes and make them snap to the stage and other shapes. ```javascript "use client"; import React, { useRef, useState } from "react"; import { Stage, Layer, Rect, Circle, RegularPolygon, Transformer, } from "react-konva"; import { useKonvaSnapping } from "use-konva-snapping"; const App = () => { const transformerRef = useRef(null); // Initialize transformerRef const [shapes, setShapes] = useState([ { type: "rect", x: 60, y: 160, width: 100, height: 50, fill: "red", draggable: true, }, { type: "rect", x: 260, y: 260, width: 100, height: 50, fill: "red", draggable: true, }, { type: "circle", x: 200, y: 100, radius: 40, fill: "green", draggable: true, }, { type: "triangle", x: 300, y: 150, radius: 50, sides: 3, fill: "blue", draggable: true, }, ]); const { handleDragging, handleDragEnd, handleResizing, handleResizeEnd } = useKonvaSnapping({ guidelineColor: "blue", guidelineDash: true, snapToStageCenter: true, snapRange: 5, guidelineThickness: 1, showGuidelines: true, snapToShapes: true, snapToStageBorders: true, }); const handleSelect = (e) => { transformerRef.current.nodes([e.target]); }; return ( <Stage width={window.innerWidth} height={window.innerHeight}> <Layer> {shapes.map((shape, index) => { if (shape.type === "rect") { return ( <Rect key={index} x={shape.x} y={shape.y} width={shape.width} height={shape.height} fill={shape.fill} draggable={shape.draggable} onDragMove={handleDragging} onDragEnd={handleDragEnd} onClick={handleSelect} /> ); } if (shape.type === "circle") { return ( <Circle key={index} x={shape.x} y={shape.y} radius={shape.radius} fill={shape.fill} draggable={shape.draggable} onClick={handleSelect} onDragMove={handleDragging} onDragEnd={handleDragEnd} /> ); } if (shape.type === "triangle") { return ( <RegularPolygon key={index} x={shape.x} y={shape.y} radius={shape.radius} sides={shape.sides} fill={shape.fill} draggable={shape.draggable} onClick={handleSelect} onDragMove={handleDragging} onDragEnd={handleDragEnd} /> ); } return null; })} <Transformer ref={transformerRef} onTransform={handleResizing} onTransformEnd={handleResizeEnd} keepRatio={false} /> </Layer> </Stage> ); }; export default App; ``` ### Step 3: Customize Options (Optional) ### `useKonvaSnapping(params)` #### Parameters: - `snapRange`: (default: `3`) Distance in pixels for snapping sensitivity. - `guidelineColor`: (default: `"rgb(0, 161, 255)"`) Color of the snapping guidelines. - `guidelineDash`: (default: `true`) Whether the guidelines should be dashed. - `showGuidelines`: (default: `true`) Whether the guidelines should be displayed. - `guidelineThickness`: (default: `1`) Thickness of the guidelines. - `snapToStageCenter`: (default: `true`) Whether to snap to the center of the stage. - `snapToStageBorders`: (default: `true`) Whether to snap to the edges of the stage. - `snapToShapes`: (default: `true`) Whether to snap to other shapes on the stage. #### Methods Returned: - `handleDragging`: Attach this method to `onDragMove` of Konva elements. - `handleResizing`: Attach this method to `onResize` of Konva Transformer. - `handleDragEnd`: Attach this method to `onDragEnd` of Konva elements. - `handleResizeEnd`: Attach this method to `onResizeEnd` of Konva Transformer. Author: <a href="https://www.linkedin.com/in/farid-methia/" target="_blank">Farid Methia</a> GitHub: <a href="https://github.com/faridmth" target="_blank">faridmth</a> Email: <a href="mailto:methia.farid2001@gmail.com" target="_blank">methia.farid2001@gmail.com</a>