在上一篇章我们学会提取点击时的位置,本篇章也会用到相同的 function,我们先将他移出。
const getClientOffset = (event: any) => {
let rect = canvasRef.current.getBoundingClientRect();
const point = {
x: event.clientX - rect.left,
y: event.clientY - rect.top,
};
return point;
};
再来操作点击line时纪录位置
/**
* 滑鼠点下画布
*/
const handleMouseDown = (event: any) => {
setIsDrawing(true);
switch (tool) {
...
case "line": // 画直线
const point = getClientOffset(event);
lastPoint = { x: point?.x, y: point?.y };
break;
default:
break;
}
};
再来在滑鼠移动时显示直线的显示位置
const handleDrawCanvas = (point: { x: number; y: number }) => {
const ctx = canvasRef.current.getContext("2d");
switch (tool) {
....
case "line": // 直线
ctx.strokeStyle = activeColor;
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(lastPoint?.x, lastPoint?.y); // 下笔位置
ctx.lineTo(point?.x, point?.y);
ctx.stroke();
break;
default:
break;
}
};
天R!这根本不是我们要的效果!观察看看,的确是有画上直线,但他在每个轨迹上都画上了直线,所以我们需要在画的过程中去清除轨迹。
在刚才画线时,我们要操作清除多余的线,让画面保持当前绘制的单一线
const handleDrawCanvas = (point: { x: number; y: number }) => {
const ctx = canvasRef.current.getContext("2d");
switch (tool) {
....
case "line": // 直线
....
ctx.beginPath();
ctx.moveTo(lastPoint?.x, lastPoint?.y);
clearCanvas(); // 补上这行!!
ctx.lineTo(point?.x, point?.y);
ctx.stroke();
break;
default:
break;
}
};
/** 清空画布 **/
const clearCanvas = () => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
};
看看效果
YA!!! 成功了~! 但会发现,因为每次的清空画布,导致我们画布上永远只出现看到的那条线,结果本末倒置 XD...,但距离完成更近了,可以很直觉的想到:只需要储存目前阶段的画布,再画完线後,进行还原,是不是就可以解决这个问题呢?
带上程序码
const [savedData, setSavedData] = useState<HTMLImageElement>(new Image());
/** 储存画布 */
const saveCanvas = () => {
const canvas = canvasRef.current;
const saved = new Image();
saved.src = canvas.toDataURL("image/png");
setSavedData(saved);
};
/** 还原画布 */
const restore = () => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
ctx.drawImage(savedData, 0, 0);
};
看到 canvas 新的用法
toDataURL 可以将目前的 canvas 画面转为图片,还可以指定图片素质,甚至支援 webp格式
drawImage 则与toDataURL为相反,将图片绘制上canvas,并且可指定大小及绘制位置。
有了上方两个方法就可以有了上方两个方法就可以在下笔时,进行储存,在每次移动画笔时,保持前一张画布状态,并清空多余的轨迹线条。
/**
* 滑鼠点下画布
*/
const handleMouseDown = (event: any) => {
setIsDrawing(true);
switch (tool) {
case "line":
const point = getClientOffset(event);
initialPoint = { x: point?.x, y: point?.y };
saveCanvas(); // 加上储存当前的画布!!
break;
default:
break;
}
};
/** 滑鼠移动 **/
const handleDrawCanvas = (point: { x: number; y: number }) => {
...
case "line": // 直线
clearCanvas(); //清空画布
restore(); //还原点击时所储存的画布
// draw the current line
ctx.beginPath();
ctx.moveTo(initialPoint?.x, initialPoint?.y);
ctx.lineTo(point?.x, point?.y);
ctx.stroke();
break;
...
}
};
来看看效果吧
太棒了!顺利完成!
<<: 07 | WordPress 空白间隔区块 Spacer Block
前一篇文章建立了Azure DevOps Agent的Windows Container Image...
昨天我们介绍了 key 的基本使用方式,今天我们就一起来了解为什麽需要 key 吧! 为什麽需要 k...
Home -> 资源群组(Resource Groups) -> 储存体帐户(Stor...
身为一个程序撰写员 所见到的都是数位内容 如果要处理类比的内容,就需要将其转换为数位的,才能使用 像...
1.NPM版本 无须更新到最新,怕错误 2.制作专案package.json npm init np...