js实现画笔功能
实现基础画布与画笔功能
使用HTML5的Canvas API创建画布,并通过JavaScript监听鼠标事件实现画笔功能。以下代码展示如何初始化画布和基本绘图:
<canvas id="drawCanvas" width="800" height="600"></canvas>
const canvas = document.getElementById('drawCanvas');
const ctx = canvas.getContext('2d');
let isDrawing = false;
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
canvas.addEventListener('mouseout', stopDrawing);
function startDrawing(e) {
isDrawing = true;
ctx.beginPath();
ctx.moveTo(e.offsetX, e.offsetY);
}
function draw(e) {
if (!isDrawing) return;
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
}
function stopDrawing() {
isDrawing = false;
}
自定义画笔样式
扩展基础功能以支持自定义画笔属性,包括颜色、粗细和线条样式:
// 设置默认样式
ctx.strokeStyle = '#000000';
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
// 动态修改样式示例
function setBrushColor(color) {
ctx.strokeStyle = color;
}
function setBrushSize(size) {
ctx.lineWidth = size;
}
实现触摸屏支持
为移动设备添加触摸事件处理,需注意坐标获取方式的差异:
canvas.addEventListener('touchstart', handleTouchStart);
canvas.addEventListener('touchmove', handleTouchMove);
canvas.addEventListener('touchend', handleTouchEnd);
function handleTouchStart(e) {
e.preventDefault();
const touch = e.touches[0];
const mouseEvent = {
offsetX: touch.clientX - canvas.offsetLeft,
offsetY: touch.clientY - canvas.offsetTop
};
startDrawing(mouseEvent);
}
function handleTouchMove(e) {
e.preventDefault();
const touch = e.touches[0];
const mouseEvent = {
offsetX: touch.clientX - canvas.offsetLeft,
offsetY: touch.clientY - canvas.offsetTop
};
draw(mouseEvent);
}
function handleTouchEnd() {
stopDrawing();
}
添加撤销与重做功能
通过保存绘图状态实现历史记录功能:
const drawingHistory = [];
let historyIndex = -1;
function saveState() {
historyIndex++;
if (historyIndex < drawingHistory.length) {
drawingHistory.length = historyIndex;
}
drawingHistory.push(canvas.toDataURL());
}
function undo() {
if (historyIndex <= 0) return;
historyIndex--;
restoreState();
}
function redo() {
if (historyIndex >= drawingHistory.length - 1) return;
historyIndex++;
restoreState();
}
function restoreState() {
const img = new Image();
img.onload = function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
};
img.src = drawingHistory[historyIndex];
}
// 在每次绘制结束时调用saveState()
function stopDrawing() {
isDrawing = false;
saveState();
}
实现压力敏感绘图(适用于支持压感的设备)
通过PointerEvent获取压力值,增强绘图体验:
canvas.addEventListener('pointerdown', startDrawing);
canvas.addEventListener('pointermove', draw);
canvas.addEventListener('pointerup', stopDrawing);
function draw(e) {
if (!isDrawing) return;
// 获取压力值(0-1),不支持时默认为1
const pressure = e.pressure || 1;
ctx.lineWidth = baseWidth * pressure;
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
}
清除画布与导出图像
添加实用功能完善画笔应用:
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
saveState();
}
function exportAsPNG() {
const link = document.createElement('a');
link.download = 'drawing.png';
link.href = canvas.toDataURL('image/png');
link.click();
}
性能优化建议
对于复杂绘图场景,考虑以下优化措施:
// 使用requestAnimationFrame节流绘制操作
let lastX = 0;
let lastY = 0;
function draw(e) {
if (!isDrawing) return;
requestAnimationFrame(() => {
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
lastX = e.offsetX;
lastY = e.offsetY;
});
}
以上实现方案可根据具体需求进行组合或扩展,例如添加多种画笔类型(毛笔、铅笔等)、实现图层功能或集成到现有Web应用中。







