UNPKG

@nutui/nutui-react

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

127 lines (126 loc) 5.22 kB
import { _ as __rest } from "./tslib.es6.js"; import React__default, { useRef, useState, useEffect, useImperativeHandle } from "react"; import { useConfig } from "./ConfigProvider.js"; import { C as ComponentDefaults } from "./typings.js"; import { c as canUseDom } from "./can-use-dom.js"; const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { type: "png", lineWidth: 2, strokeStyle: "#1a1a1a", unsupported: "" }); const InternalSignature = (props, ref) => { const { locale } = useConfig(); const _a = Object.assign(Object.assign({}, defaultProps), props), { type, lineWidth, strokeStyle, unsupported, className, style, onConfirm, onClear } = _a, rest = __rest(_a, ["type", "lineWidth", "strokeStyle", "unsupported", "className", "style", "onConfirm", "onClear"]); const classPrefix = `nut-signature`; const canvasRef = useRef(null); const wrapRef = useRef(null); const [canvasHeight, setCanvasHeight] = useState(0); const [canvasWidth, setCanvasWidth] = useState(0); const ctx = useRef(null); const checkCanvas = () => { const elem = document.createElement("canvas"); return !!(elem.getContext && elem.getContext("2d")); }; const [isCanvasSupported, setIsCanvasSupported] = useState(false); const isSignedRef = useRef(false); const isSupportTouch = canUseDom ? "ontouchstart" in window : false; const events = isSupportTouch ? ["touchstart", "touchmove", "touchend", "touchleave"] : ["mousedown", "mousemove", "mouseup", "mouseleave"]; useEffect(() => { setIsCanvasSupported(checkCanvas); }, []); useEffect(() => { if (isCanvasSupported && canvasRef.current && wrapRef.current) { ctx.current = canvasRef.current.getContext("2d"); setCanvasWidth(wrapRef.current.offsetWidth); setCanvasHeight(wrapRef.current.offsetHeight); addEvent(); } }, [isCanvasSupported]); const startEventHandler = (event) => { event.preventDefault(); isSignedRef.current = true; if (ctx.current && canvasRef.current) { ctx.current.beginPath(); ctx.current.lineWidth = lineWidth; ctx.current.strokeStyle = strokeStyle; canvasRef.current.addEventListener(events[1], moveEventHandler, false); canvasRef.current.addEventListener(events[2], endEventHandler, false); canvasRef.current.addEventListener(events[3], leaveEventHandler, false); } }; const addEvent = () => { if (canvasRef.current) { canvasRef.current.addEventListener(events[0], startEventHandler, false); } }; const moveEventHandler = (event) => { event.preventDefault(); const evt = isSupportTouch ? event.touches[0] : event; if (canvasRef.current && ctx.current) { const coverPos = canvasRef.current.getBoundingClientRect(); const mouseX = evt.clientX - coverPos.left; const mouseY = evt.clientY - coverPos.top; ctx.current.lineTo(mouseX, mouseY); ctx.current.stroke(); } }; const endEventHandler = (event) => { event.preventDefault(); if (canvasRef.current) { canvasRef.current.removeEventListener(events[1], moveEventHandler, false); canvasRef.current.removeEventListener(events[2], endEventHandler, false); } }; const leaveEventHandler = (event) => { event.preventDefault(); if (canvasRef.current) { canvasRef.current.removeEventListener(events[1], moveEventHandler, false); canvasRef.current.removeEventListener(events[2], endEventHandler, false); } }; const handleClearBtn = () => { isSignedRef.current = false; if (canvasRef.current && ctx.current) { canvasRef.current.addEventListener(events[2], endEventHandler, false); ctx.current.clearRect(0, 0, canvasWidth, canvasHeight); ctx.current.closePath(); } onClear && onClear(); }; const onSave = (canvas) => { let dataurl = ""; if (!isSignedRef.current) { onConfirm && onConfirm(canvas, dataurl, isSignedRef.current); return; } switch (type) { case "png": dataurl = canvas.toDataURL("image/png"); break; case "jpg": dataurl = canvas.toDataURL("image/jpeg", 0.8); break; default: dataurl = canvas.toDataURL("image/png"); } onConfirm && onConfirm(canvas, dataurl, isSignedRef.current); }; useImperativeHandle(ref, () => ({ confirm: () => { onSave(canvasRef.current); }, clear: () => { handleClearBtn(); } })); return React__default.createElement( "div", Object.assign({ className: `${classPrefix} ${className}`, style }, rest), React__default.createElement( "div", { className: `${classPrefix}-inner`, ref: wrapRef }, React__default.createElement(React__default.Fragment, null, isCanvasSupported ? React__default.createElement("canvas", { ref: canvasRef, height: canvasHeight, width: canvasWidth }) : unsupported ? React__default.createElement(React__default.Fragment, null, unsupported) : React__default.createElement("p", { className: `${classPrefix}-unsupport` }, locale.signature.unsupported)) ) ); }; const Signature = React__default.forwardRef(InternalSignature); Signature.displayName = "NutSignature"; export { Signature as default };