js实现白版
实现白板的基本思路
使用HTML5的Canvas元素结合JavaScript可以轻松实现一个简单的白板功能。Canvas提供了丰富的绘图API,能够满足基本的绘图需求。
基础代码结构
HTML部分需要包含一个Canvas元素:
<canvas id="whiteboard" width="800" height="600"></canvas>
JavaScript部分需要获取Canvas元素并设置绘图上下文:
const canvas = document.getElementById('whiteboard');
const ctx = canvas.getContext('2d');
实现绘图功能
监听鼠标事件来实现绘图功能。需要处理mousedown、mousemove和mouseup事件:
let isDrawing = false;
let lastX = 0;
let lastY = 0;
canvas.addEventListener('mousedown', (e) => {
isDrawing = true;
[lastX, lastY] = [e.offsetX, e.offsetY];
});
canvas.addEventListener('mousemove', (e) => {
if (!isDrawing) return;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
[lastX, lastY] = [e.offsetX, e.offsetY];
});
canvas.addEventListener('mouseup', () => isDrawing = false);
canvas.addEventListener('mouseout', () => isDrawing = false);
添加绘图工具
可以扩展功能,添加不同的绘图工具如画笔、橡皮擦等:
let currentTool = 'pen';
function setTool(tool) {
currentTool = tool;
}
canvas.addEventListener('mousemove', (e) => {
if (!isDrawing) return;
if (currentTool === 'pen') {
ctx.strokeStyle = '#000000';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
} else if (currentTool === 'eraser') {
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 10;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
}
[lastX, lastY] = [e.offsetX, e.offsetY];
});
实现颜色选择
添加颜色选择功能可以让用户自定义画笔颜色:
let currentColor = '#000000';
function setColor(color) {
currentColor = color;
ctx.strokeStyle = currentColor;
}
// 在绘图逻辑中使用currentColor
ctx.strokeStyle = currentColor;
实现线条粗细调整
允许用户调整线条的粗细:
let lineWidth = 2;
function setLineWidth(width) {
lineWidth = width;
ctx.lineWidth = lineWidth;
}
// 在绘图逻辑中使用lineWidth
ctx.lineWidth = lineWidth;
实现清除画布功能
添加一个清除画布的按钮:
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
实现保存功能
可以将画布内容保存为图片:
function saveCanvas() {
const link = document.createElement('a');
link.download = 'drawing.png';
link.href = canvas.toDataURL('image/png');
link.click();
}
完整示例代码
将上述功能整合在一起的完整示例:
<!DOCTYPE html>
<html>
<head>
<title>Whiteboard</title>
<style>
#whiteboard {
border: 1px solid #000;
}
.tools {
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="tools">
<button onclick="setTool('pen')">Pen</button>
<button onclick="setTool('eraser')">Eraser</button>
<input type="color" onchange="setColor(this.value)">
<input type="range" min="1" max="20" value="2" onchange="setLineWidth(this.value)">
<button onclick="clearCanvas()">Clear</button>
<button onclick="saveCanvas()">Save</button>
</div>
<canvas id="whiteboard" width="800" height="600"></canvas>
<script>
const canvas = document.getElementById('whiteboard');
const ctx = canvas.getContext('2d');
let isDrawing = false;
let lastX = 0;
let lastY = 0;
let currentTool = 'pen';
let currentColor = '#000000';
let lineWidth = 2;
function setTool(tool) {
currentTool = tool;
}
function setColor(color) {
currentColor = color;
}
function setLineWidth(width) {
lineWidth = width;
}
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function saveCanvas() {
const link = document.createElement('a');
link.download = 'drawing.png';
link.href = canvas.toDataURL('image/png');
link.click();
}
canvas.addEventListener('mousedown', (e) => {
isDrawing = true;
[lastX, lastY] = [e.offsetX, e.offsetY];
});
canvas.addEventListener('mousemove', (e) => {
if (!isDrawing) return;
if (currentTool === 'pen') {
ctx.strokeStyle = currentColor;
ctx.lineWidth = lineWidth;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
} else if (currentTool === 'eraser') {
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = lineWidth * 2;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
}
[lastX, lastY] = [e.offsetX, e.offsetY];
});
canvas.addEventListener('mouseup', () => isDrawing = false);
canvas.addEventListener('mouseout', () => isDrawing = false);
</script>
</body>
</html>
进阶功能建议
对于更复杂的白板应用,可以考虑添加以下功能:
- 撤销/重做功能
- 多用户协作
- 图形绘制(矩形、圆形等)
- 文字输入
- 画布缩放和平移
这些功能需要更复杂的实现,但基于上述基础代码可以逐步扩展。







