react-hooks實現簡單的繪圖、簽名功能
阿新 • • 發佈:2021-06-11
使用creat-react-app簡單搭建一個react-hooks專案
return(<Fragment> <canvas ref={canvasRef} width={window.innerWidth} height={window.innerHeight} /> <div className='SSS' onClick={clearCanvas}>清除</div> </Fragment>)
建立一個canvas繪圖區域
import React, { Fragment } from 'react' const HOOK_SVG = 'm129.03125 63.3125c0-34.914062-28.941406-63.3125-64.519531-63.3125-35.574219 0-64.511719 28.398438-64.511719 63.3125 0 29.488281 20.671875 54.246094 48.511719 61.261719v162.898437c0 53.222656 44.222656 96.527344 98.585937 96.527344h10.316406c54.363282 0 98.585938-43.304688 98.585938-96.527344v-95.640625c0-7.070312-4.640625-13.304687-11.414062-15.328125-6.769532-2.015625-14.082032.625-17.960938 6.535156l-42.328125 64.425782c-4.847656 7.390625-2.800781 17.3125 4.582031 22.167968 7.386719 4.832032 17.304688 2.792969 22.160156-4.585937l12.960938-19.71875v42.144531c0 35.582032-29.863281 64.527344-66.585938 64.527344h-10.316406c-36.714844 0-66.585937-28.945312-66.585937-64.527344v-162.898437c27.847656-7.015625 48.519531-31.773438 48.519531-61.261719zm-97.03125 0c0-17.265625 14.585938-31.3125 32.511719-31.3125 17.929687 0 32.511719 14.046875 32.511719 31.3125 0 17.261719-14.582032 31.3125-32.511719 31.3125-17.925781 0-32.511719-14.050781-32.511719-31.3125zm0 0' const HOOK_PATH = new Path2D(HOOK_SVG) const SCALE = 0.3 const OFFSET = 80 function draw( ctx: { fillStyle: string; shadowColor: string; shadowBlur: number; save: () => void; scale: (arg0: number, arg1: number) => void; translate: (arg0: number, arg1: number) => void; fill: (arg0: Path2D) => void; restore: () => void }, location: { x: any; y: any }) { ctx.fillStyle = 'deepskyblue' ctx.shadowColor = 'dodgerblue' ctx.shadowBlur = 20; ctx.save() ctx.scale(SCALE, SCALE) ctx.translate(location.x / SCALE - OFFSET, location.y / SCALE - OFFSET) ctx.fill(HOOK_PATH) ctx.restore() } function App() { const canvasRef = React.useRef<any>(null); let [Flag, setFlat] = React.useState(false) React.useEffect(() => { const canvas = canvasRef.current const ctx = canvas.getContext('2d') ctx.fillStyle = 'white'; ctx.fillRect(10, 10, window.innerWidth, window.innerHeight); // 畫圖 ctx.beginPath(); ctx.moveTo(75, 50); ctx.lineTo(100, 75); ctx.lineTo(100, 25); ctx.lineWidth = '1'; ctx.fillStyle = 'pink'; ctx.fill(); }) const writing = ( beginX: number, beginY: number, stopX: number, stopY: number, ctx: { beginPath: () => void; globalAlpha: number; lineWidth: number; strokeStyle: string; moveTo: (arg0: any, arg1: any) => void; lineTo: (arg0: any, arg1: any) => void; closePath: () => void; stroke: () => void }, ) => { ctx.beginPath() // 開啟一條新路徑 ctx.globalAlpha = 1 // 設定圖片的透明度 ctx.lineWidth = 3 // 設定線寬 ctx.strokeStyle = 'pink' // 設定路徑顏色 ctx.moveTo(beginX, beginY) // 從(beginX, beginY)這個座標點開始畫圖 ctx.lineTo(stopX, stopY) // 定義從(beginX, beginY)到(stopX, stopY)的線條(該方法不會建立線條) ctx.closePath() // 建立該條路徑 ctx.stroke() // 實際地繪製出通過 moveTo() 和 lineTo() 方法定義的路徑。預設顏色是黑色。 } React.useEffect(() => { let beginX: number; let beginY: number const canvas = canvasRef.current const ctx = canvas.getContext('2d') ctx.fillStyle = '#fff' ctx.fillRect(0, 0, canvas.width, canvas.height) console.log(ctx, 'canvas'); // pc端 和 移動端事件 canvas.addEventListener('click', function (event: { preventDefault: () => void; clientX: number; clientY: number }) { event.preventDefault() // 阻止在canvas畫布上簽名的時候頁面跟著滾動 beginX = event.clientX beginY = event.clientY setFlat(true) ctx.fillStyle = 'deepskyblue' ctx.shadowColor = 'dodgerblue' ctx.shadowBlur = 20; ctx.save() ctx.scale(SCALE, SCALE) ctx.translate(event.clientX / SCALE - OFFSET, event.clientY / SCALE - OFFSET) ctx.fill(HOOK_PATH) ctx.restore() }) canvas.addEventListener('mousemove', (event: { preventDefault: () => void; clientX: number; clientY: number }) => { event.preventDefault() // 阻止在canvas畫布上簽名的時候頁面跟著滾動 if (Flag === false) { return } const stopX = event.clientX - canvas.offsetLeft const stopY = event.clientY - canvas.offsetTop writing(beginX, beginY, stopX, stopY, ctx) beginX = stopX // 這一步很關鍵,需要不斷更新起點,否則畫出來的是射線簇 beginY = stopY }) canvas.addEventListener('mouseleave', function (event: { preventDefault: () => void; }) { event.preventDefault() // 阻止在canvas畫布上簽名的時候頁面跟著滾動 }) canvas.addEventListener('touchstart', function (event: { preventDefault: () => void; touches: { clientX: number; pageY: any }[] }) { event.preventDefault() // 阻止在canvas畫布上簽名的時候頁面跟著滾動 beginX = event.touches[0].clientX beginY = event.touches[0].pageY }) canvas.addEventListener('touchmove', (event: { preventDefault: () => void; touches: any[]; clientX: number; pageY: number }) => { event.preventDefault() // 阻止在canvas畫布上簽名的時候頁面跟著滾動 event = event.touches[0] const stopX = event.clientX - canvas.offsetLeft const stopY = event.pageY - canvas.offsetTop writing(beginX, beginY, stopX, stopY, ctx) beginX = stopX // 這一步很關鍵,需要不斷更新起點,否則畫出來的是射線簇 beginY = stopY }) }) function clearCanvas() { // 清除畫圖 ,重新畫布 ,或者設定白色背景色 const canvas = canvasRef.current const ctx = canvas.getContext('2d') ctx.clearRect(0, 0, window.innerWidth, window.innerHeight); }