index.html 文件:
DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>画直线title>
<link href="css/main.css" rel="stylesheet">
head>
<body>
<canvas id="canvas">canvas>
<script src="js/main.js">script>
body>
html>
main.css 文件:
#ccs {
box-shadow: 0px 0px 2px 1px rgba(0, 0, 0, 0.4);
}
main.js 文件:
window.onload = (event) => {
// console.log(event);
main();
}
function main() {
const canvas = document.getElementById("canvas");
// 设置画布的宽高
canvas.width = 400;
canvas.height = 400;
const ctx = canvas.getContext("2d");
// 画直线
ctx.beginPath();
ctx.moveTo(0, 0); // 画笔的起点
ctx.lineTo(100, 100); // 画笔的终点,第一个参数表示向左移动 100 像素,,第二个参数表示向下移动 100 像素
ctx.stroke();
}
index.html 文件:
DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>使用鼠标画线title>
<link href="css/main.css" rel="stylesheet">
head>
<body>
<canvas id="canvas">canvas>
<script src="js/main.js">script>
body>
html>
main.js 文件:
window.onload = (event) => {
// console.log(event);
main();
}
function main() {
const canvas = document.getElementById("canvas");
// 设置画布的宽高
canvas.width = 400;
canvas.height = 400;
const ctx = canvas.getContext("2d");
if (!ctx) return;
const MOUSE_LEFT_BUTTON = 0; // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
let isDrawing = false;
let x = 0;
let y = 0;
canvas.addEventListener("mousedown", (event) => {
// console.log(event);
if (event.button !== MOUSE_LEFT_BUTTON) {
return;
}
x = event.layerX;
y = event.layerY;
isDrawing = true;
});
canvas.addEventListener("mousemove", (event) => {
// console.log(event);
// console.log(event.layerX, event.layerY);
if (event.button !== MOUSE_LEFT_BUTTON) {
return;
}
if (isDrawing) {
drawLine(ctx, "black", 1, x, y, event.layerX, event.layerY);
x = event.layerX;
y = event.layerY;
}
});
canvas.addEventListener("mouseup", (event) => {
// console.log(event);
if (event.button !== MOUSE_LEFT_BUTTON) {
return;
}
if (isDrawing) {
drawLine(ctx, "black", 1, x, y, event.layerX, event.layerY);
x = 0;
y = 0;
isDrawing = false;
}
});
}
function drawLine(context, strokeStyle, lineWidth, x0, y0, x1, y1) {
context.beginPath();
context.strokeStyle = strokeStyle;
context.lineWidth = lineWidth;
context.moveTo(x0, y0);
context.lineTo(x1, y1);
context.stroke();
}
index.html 文件:
DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>使用鼠标画线,带撤销与重做功能title>
<link href="css/main.css" rel="stylesheet">
head>
<body>
<canvas id="canvas">canvas>
<input type="button" id="undo" value="undo" />
<input type="button" id="redo" value="redo" />
<script src="js/pako.js">script> // 压缩与解压:http://nodeca.github.io/pako/
<script src="js/main.js">script>
body>
html>
main.js 文件:
window.onload = (event) => {
// console.log(event);
main();
}
function main() {
const canvas = document.getElementById("canvas");
const undo = document.querySelector("#undo");
const redo = document.querySelector("#redo");
// 设置画布的宽高
canvas.width = 400;
canvas.height = 400;
// 禁用撤销与重做按钮
undo.disabled = true;
redo.disabled = true;
const ctx = canvas.getContext("2d");
if (!ctx) return;
const undoHistory = [];
const redoHistory = [];
const MOUSE_LEFT_BUTTON = 0; // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
let isDrawing = false;
let x = 0;
let y = 0;
// 鼠标按下事件
canvas.addEventListener("mousedown", (event) => {
// console.log(event);
if (event.button !== MOUSE_LEFT_BUTTON) {
return;
}
{
// 保存画布的像素数据
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const compressed = pako.deflate(new Uint8Array(imageData.data)); // 压缩,减小存储开销
undoHistory.push(compressed);
redoHistory.splice(0, redoHistory.length); // 删除所有内容
undo.disabled = false;
redo.disabled = true;
}
{
// 保存鼠标在画布中的坐标
x = event.layerX;
y = event.layerY;
isDrawing = true;
}
});
// 鼠标移动事件
canvas.addEventListener("mousemove", (event) => {
// console.log(event);
// console.log(event.layerX, event.layerY);
if (event.button !== MOUSE_LEFT_BUTTON) {
return;
}
if (isDrawing) {
drawLine(ctx, "black", 1, x, y, event.layerX, event.layerY);
x = event.layerX;
y = event.layerY;
}
});
// 鼠标松开事件
canvas.addEventListener("mouseup", (event) => {
console.log(event);
if (event.button !== MOUSE_LEFT_BUTTON) {
return;
}
if (isDrawing) {
drawLine(ctx, x, y, event.layerX, event.layerY);
x = 0;
y = 0;
isDrawing = false;
}
});
undo.onclick = (event) => {
// console.log(event);
// 在撤销之前,保存当前画布的像素数据
{
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const compressed = pako.deflate(new Uint8Array(imageData.data));
redoHistory.push(compressed);
redo.disabled = false;
}
// 撤销
{
const compressed = undoHistory.pop();
try {
const decompressed = pako.inflate(compressed); // 解压
const uint8ClampedArray = new Uint8ClampedArray(decompressed);
const imageData = new ImageData(uint8ClampedArray, canvas.width, canvas.height);
ctx.putImageData(imageData, 0, 0);
} catch (error) {
console.error(error);
}
if (undoHistory.length === 0) {
undo.disabled = true;
}
}
}
redo.onclick = (event) => {
// console.log(event);
// 在重做之前,保存当前画布的像素数据
{
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const compressed = pako.deflate(new Uint8Array(imageData.data));
undoHistory.push(compressed);
undo.disabled = false;
}
// 重做
{
const compressed = redoHistory.pop();
try {
const decompressed = pako.inflate(compressed);
const uint8ClampedArray = new Uint8ClampedArray(decompressed);
const imageData = new ImageData(uint8ClampedArray, canvas.width, canvas.height);
ctx.putImageData(imageData, 0, 0);
} catch (error) {
console.log(error);
}
if (redoHistory.length === 0) {
redo.disabled = true;
}
}
}
}
function drawLine(context, strokeStyle, lineWidth, x0, y0, x1, y1) {
context.beginPath();
context.strokeStyle = strokeStyle;
context.lineWidth = lineWidth;
context.moveTo(x0, y0);
context.lineTo(x1, y1);
context.stroke();
}