UNPKG

@grandlinex/react-components

Version:
201 lines (200 loc) 8.46 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const react_1 = __importStar(require("react")); const react_icons_1 = require("@grandlinex/react-icons"); const Grid_1 = require("../Grid/Grid"); const IconButton_1 = require("../button/IconButton"); const Draw = ({ width = window.innerWidth, height = window.innerHeight, onChange, }) => { const canvasRef = (0, react_1.useRef)(null); const [color, setColor] = (0, react_1.useState)('blue'); const [lineWidth, setLineWidth] = (0, react_1.useState)(5); const [data, setData] = (0, react_1.useState)([]); const [isPainting, setIsPainting] = (0, react_1.useState)(false); const [mousePosition, setMousePosition] = (0, react_1.useState)(undefined); const getCoordinates = (event) => { if (!canvasRef.current) { return undefined; } const canvas = canvasRef.current; const { left, top } = canvas.getBoundingClientRect(); const leftR = Math.round(left); const topR = Math.round(top); if (window.TouchEvent && event instanceof TouchEvent) { return { x: event.changedTouches[0].pageX - leftR, y: event.changedTouches[0].pageY - topR, }; } if (event instanceof MouseEvent) { return { x: event.pageX - leftR, y: event.pageY - topR, }; } return { x: 0, y: 0, }; }; const startPaint = (0, react_1.useCallback)((event) => { const coordinates = getCoordinates(event); if (coordinates) { setMousePosition(coordinates); setIsPainting(true); } }, []); (0, react_1.useEffect)(() => { if (!canvasRef.current) { return undefined; } const canvas = canvasRef.current; canvas.addEventListener('mousedown', startPaint); canvas.addEventListener('touchstart', startPaint); return () => { canvas.removeEventListener('mousedown', startPaint); canvas.removeEventListener('touchstart', startPaint); }; }, [startPaint]); const drawLine = (originalMousePosition, newMousePosition) => { if (!canvasRef.current) { return; } const canvas = canvasRef.current; const context = canvas.getContext('2d'); if (context) { context.strokeStyle = color; context.lineJoin = 'round'; context.lineWidth = lineWidth; context.beginPath(); context.moveTo(originalMousePosition.x, originalMousePosition.y); context.lineTo(newMousePosition.x, newMousePosition.y); context.closePath(); context.stroke(); } }; const paint = (0, react_1.useCallback)((event) => { if (isPainting) { const newMousePosition = getCoordinates(event); if (mousePosition && newMousePosition) { drawLine(mousePosition, newMousePosition); setMousePosition(newMousePosition); } } }, [isPainting, mousePosition]); const exitPaint = (0, react_1.useCallback)(() => { setIsPainting(false); setMousePosition(undefined); }, []); (0, react_1.useEffect)(() => { if (!isPainting && canvasRef.current) { const dat = canvasRef.current.toDataURL(); setData(data.concat(dat)); onChange?.(dat); } }, [isPainting]); (0, react_1.useEffect)(() => { if (!canvasRef.current) { return undefined; } const canvas = canvasRef.current; canvas.addEventListener('mousemove', paint); canvas.addEventListener('touchmove', paint); return () => { canvas.removeEventListener('mousemove', paint); canvas.removeEventListener('touchmove', paint); }; }, [paint]); (0, react_1.useEffect)(() => { if (!canvasRef.current) { return undefined; } const canvas = canvasRef.current; canvas.addEventListener('mouseup', exitPaint); canvas.addEventListener('mouseleave', exitPaint); canvas.addEventListener('touchend', exitPaint); return () => { canvas.removeEventListener('mouseup', exitPaint); canvas.removeEventListener('mouseleave', exitPaint); canvas.removeEventListener('touchend', exitPaint); }; }, [exitPaint]); return (react_1.default.createElement(Grid_1.Grid, { className: "glx-draw" }, react_1.default.createElement(Grid_1.Grid, { className: "glx-draw--header glx-flex-wrap", flex: true, flexR: true, gap: 8, vCenter: true, style: { width, } }, react_1.default.createElement(IconButton_1.IconButton, { disabled: data.length < 2, onClick: () => { const canvas = canvasRef.current; if (canvas) { const context = canvas.getContext('2d'); if (context) { const img = new Image(); img.onload = () => { context.clearRect(0, 0, canvas.width, canvas.height); context.drawImage(img, 0, 0); }; const x = data.slice(0, data.length - 1); img.src = x[x.length - 1]; onChange?.(x[x.length - 1]); setData(x); } } } }, react_1.default.createElement(react_icons_1.IOArrowUndoCircle, null)), [ 'blue', 'red', 'green', 'yellow', 'orange', 'cyan', 'pink', 'purple', 'black', ].map((x) => (react_1.default.createElement(IconButton_1.IconButton, { key: `color_${x}`, color: x, onClick: () => { setColor(x); } }, react_1.default.createElement(react_icons_1.IOColorFill, null)))), react_1.default.createElement(IconButton_1.IconButton, { onClick: () => { setColor('white'); } }, react_1.default.createElement(react_icons_1.IOColorFill, null)), react_1.default.createElement("div", null, "Current color:"), react_1.default.createElement("div", { style: { width: '50px', height: '25px', backgroundColor: color, } }), react_1.default.createElement("div", null, "Line width:"), react_1.default.createElement("div", null, react_1.default.createElement("input", { type: "range", min: 1, step: 1, max: 40, value: lineWidth, onChange: (e) => { setLineWidth(parseInt(e.target.value, 10)); } })), react_1.default.createElement("div", null, lineWidth, "px")), react_1.default.createElement("canvas", { style: { border: '1px solid white' }, ref: canvasRef, height: height, width: width }))); }; exports.default = Draw;