Html5 Canvas实现图片标志、缩放、移动和生涯汗青状态成果 (附转换公式)
这个就必要用到我们之前推导出来的公式啦!由于呢,细心想一下,假如我们缩放位移之后,我们鼠标按下的位置,他的坐标也许就相对付画布来说会有变革, 以是我们必要转换一下才气举办鼠标按下的位置与画布的位置逐一对应的结果 轻微总结一下: 传入鼠标按下的坐标 通过公式转换,开始在对应坐标下绘制 鼠标抬起时,打消变乱监听 // 操作公式转换一下坐标 const generateLinePoint = (x: number, y: number) => { const { current: wrap } = wrapRef const { current: translatePointX } = translatePointXRef const { current: translatePointY } = translatePointYRef const wrapWidth: number = wrap?.offsetWidth || 0 const wrapHeight: number = wrap?.offsetHeight || 0 // 缩放位移坐标变革纪律 // (transformOrigin - downX) / scale * (scale-1) + downX - translateX = pointX const pointX: number = ((wrapWidth / 2) - x) / canvasScale * (canvasScale - 1) + x - translatePointX const pointY: number = ((wrapHeight / 2) - y) / canvasScale * (canvasScale - 1) + y - translatePointY return { pointX, pointY } } // 监听鼠标画笔变乱 const handleLineMode = (downX: number, downY: number) => { const { current: canvas } = canvasRef const { current: wrap } = wrapRef const context: CanvasRenderingContext2D | undefined | null = canvas?.getContext('2d') if (!canvas || !wrap || !context) return const offsetLeft: number = canvas.offsetLeft const offsetTop: number = canvas.offsetTop // 减去画布偏移的间隔(以画布为基准举办计较坐标) downX = downX - offsetLeft downY = downY - offsetTop const { pointX, pointY } = generateLinePoint(downX, downY) context.globalCompositeOperation = "source-over" context.beginPath() // 配置画笔出发点 context.moveTo(pointX, pointY) canvas.onmousemove = null canvas.onmousemove = (event: MouseEvent) => { const moveX: number = event.pageX - offsetLeft const moveY: number = event.pageY - offsetTop const { pointX, pointY } = generateLinePoint(moveX, moveY) // 开始绘制画笔线条~ context.lineTo(pointX, pointY) context.stroke() } canvas.onmouseup = () => { context.closePath() canvas.onmousemove = null canvas.onmouseup = null } } 7. 橡皮擦的实现 橡皮擦今朝尚有点题目,此刻的话是通过将 canvas 画布的配景图片 + globalCompositeOperation 这个属性来模仿橡皮擦的实现,不外,这时辰图片天生出来之后,橡皮擦的陈迹会酿成白色,而不是透明 此步调与画笔实现差不多,只有一点点小变换 配置属性 context.globalCompositeOperation = "destination-out" // 今朝橡皮擦尚有点题目,前端表现正常,生涯图片下来,擦除的陈迹会酿成白色 const handleEraserMode = (downX: number, downY: number) => { const { current: canvas } = canvasRef const { current: wrap } = wrapRef const context: CanvasRenderingContext2D | undefined | null = canvas?.getContext('2d') if (!canvas || !wrap || !context) return const offsetLeft: number = canvas.offsetLeft const offsetTop: number = canvas.offsetTop downX = downX - offsetLeft downY = downY - offsetTop const { pointX, pointY } = generateLinePoint(downX, downY) context.beginPath() context.moveTo(pointX, pointY) canvas.onmousemove = null canvas.onmousemove = (event: MouseEvent) => { const moveX: number = event.pageX - offsetLeft const moveY: number = event.pageY - offsetTop const { pointX, pointY } = generateLinePoint(moveX, moveY) context.globalCompositeOperation = "destination-out" context.lineWidth = lineWidth context.lineTo(pointX, pointY) context.stroke() } canvas.onmouseup = () => { context.closePath() canvas.onmousemove = null canvas.onmouseup = null } } 8. 取消与规复的成果实现 这个的话,我们起首必要相识常见的取消与规复的成果的逻辑 分几种环境吧 若当前状态处于第一个位置,则不应承取消 若当前状态处于最后一个位置,则不应承规复 假如当前取消了,然而更新了状态,则取当前状态为最新的状态(也就是说不应承规复了,这个刚更新的状态就是最新的) 画布状态的更新 以是我们必要配置一些变量来存,状态列表,与当前画笔的状态下标 // 界说参数存东东 const canvasHistroyListRef: MutableRefObject<ImageData[]> = useRef([]) const [canvasCurrentHistory, setCanvasCurrentHistory] = useState<number>(0) 我们还必要在初始化canvas的时辰,我们就添插手当前的状态存入列表中,作为最先开始的空画布状态 (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |