<-- Home |--javascript

003 Canvas Drawing一个小小的白板

5px

原因

这几天我需要给别人发一个签名的图片,自己在画图里挣了半天,不好看……

突然记起(不记得什么时候)看到有人发了一个他的白板小工具,做得非常不错,非常好用。

那就不纠结,趁着死线还有若干小时,抽出半小时,自己写一个。

使用指南

就只提供了几个简单的功能:

  • 清屏
  • 颜色
  • 画刷尺寸
  • 导出

这几个功能完全满足了我签个名字,导出一个图片,发给别人的需求。

代码

三个文件下载:

文件内容如下所示。

draw.html

 1<link rel="stylesheet" href="/javascript/canvas-drawing/style.css">
 2
 3<canvas id="drawingCanvas" width="800" height="600"></canvas>
 4<div class="controls">
 5    <button id="clear">Clear Canvas</button>
 6    <input type="color" id="colorPicker" value="#000000">
 7    <input type="range" id="brushSize" min="1" max="50" value="5">
 8    <span id="brushSizeValue">5px</span>
 9    <button id="export">Export (300 DPI)</button>
10</div>
11
12<script src="/javascript/canvas-drawing/draw.js"></script>

style.css

 1body {
 2    display: flex;
 3    flex-direction: column;
 4    align-items: center;
 5    background-color: #f0f0f0;
 6    font-family: Arial, sans-serif;
 7}
 8
 9canvas {
10    border: 2px solid #333;
11    background-color: white;
12    margin: 20px;
13    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
14}
15
16.controls {
17    margin-bottom: 20px;
18    display: flex;
19    align-items: center;
20    justify-content: center;
21}
22
23button {
24    padding: 8px 16px;
25    margin: 0 5px;
26    background-color: #4CAF50;
27    color: white;
28    border: none;
29    border-radius: 4px;
30    cursor: pointer;
31}
32
33button:hover {
34    background-color: #45a049;
35}
36
37input[type="color"] {
38    margin: 0 10px;
39}
40
41.brush-preview {
42    background-color: black;
43    border-radius: 50%;
44}
45
46.size-label {
47    font-size: 12px;
48    color: #666;
49    text-align: center;
50    margin-top: 4px;
51}

draw.js

 1const canvas = document.getElementById('drawingCanvas');
 2const ctx = canvas.getContext('2d');
 3const clearButton = document.getElementById('clear');
 4const colorPicker = document.getElementById('colorPicker');
 5const brushSize = document.getElementById('brushSize');
 6const brushSizeValue = document.getElementById('brushSizeValue');
 7const exportButton = document.getElementById('export');
 8const EXPORT_DPI = 300;
 9const INCH_TO_PIXEL = 96; // Standard screen DPI
10
11let isDrawing = false;
12let lastX = 0;
13let lastY = 0;
14
15// Initialize canvas
16ctx.lineCap = 'round';
17ctx.lineJoin = 'round';
18ctx.strokeStyle = colorPicker.value;
19ctx.lineWidth = brushSize.value;
20
21// Drawing functions
22function startDrawing(e) {
23    isDrawing = true;
24    [lastX, lastY] = [e.offsetX, e.offsetY];
25}
26
27function draw(e) {
28    if (!isDrawing) return;
29
30    ctx.beginPath();
31    ctx.moveTo(lastX, lastY);
32    ctx.lineTo(e.offsetX, e.offsetY);
33    ctx.stroke();
34
35    [lastX, lastY] = [e.offsetX, e.offsetY];
36}
37
38function stopDrawing() {
39    isDrawing = false;
40}
41
42function exportHighResImage() {
43    // Create timestamp for filename
44    const now = new Date();
45    const year = now.getFullYear();
46    const month = String(now.getMonth() + 1).padStart(2, '0');
47    const day = String(now.getDate()).padStart(2, '0');
48    const time = String(now.getHours()).padStart(2, '0') +
49        String(now.getMinutes()).padStart(2, '0') +
50        String(now.getSeconds()).padStart(2, '0');
51    const filename = `canvas-${year}-${month}${day}-${time}.png`;
52
53    // Create a temporary canvas for high-res export
54    const tempCanvas = document.createElement('canvas');
55    const tempCtx = tempCanvas.getContext('2d');
56
57    // Calculate size for 300 DPI
58    const scale = EXPORT_DPI / INCH_TO_PIXEL;
59    tempCanvas.width = canvas.width * scale;
60    tempCanvas.height = canvas.height * scale;
61
62    // Scale the context and draw the original canvas
63    tempCtx.scale(scale, scale);
64    tempCtx.drawImage(canvas, 0, 0);
65
66    // Create download link
67    const link = document.createElement('a');
68    link.download = filename;
69    link.href = tempCanvas.toDataURL('image/png');
70    link.click();
71}
72
73// Event listeners
74canvas.addEventListener('mousedown', startDrawing);
75canvas.addEventListener('mousemove', draw);
76canvas.addEventListener('mouseup', stopDrawing);
77canvas.addEventListener('mouseout', stopDrawing);
78
79clearButton.addEventListener('click', () => {
80    ctx.clearRect(0, 0, canvas.width, canvas.height);
81});
82
83colorPicker.addEventListener('input', (e) => {
84    ctx.strokeStyle = e.target.value;
85});
86
87brushSize.addEventListener('input', (e) => {
88    ctx.lineWidth = e.target.value;
89    brushSizeValue.textContent = e.target.value + 'px';
90});
91
92exportButton.addEventListener('click', exportHighResImage);

文章标签

|-->javascript |-->canvas |-->drawing |-->whiteboard


GitHub