背景
Canvas 的使用场景非常广泛,主要用于实现各种图形、动画、游戏、图像处理和交互效果,接下来主要从水印效果、柱状图、个人签名、球在屏幕上弹跳的效果四种场景来总结
一. 水印效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let watermark = {};
let setWatermark = str => {
let id = "1.23452384164.123412415";
if (document.getElementById(id) !== null) {
document.body.removeChild(document.getElementById(id));
}
let can = document.createElement("canvas");
can.width = 200;
can.height = 100;
let cans = can.getContext("2d");
cans.rotate((-20 * Math.PI) / 180);
cans.font = "15px Vedana";
cans.fillStyle = "rgba(0, 0, 0, 0.30)";
cans.textAlign = "left";
cans.textBaseline = "Middle";
cans.fillText(str, can.width / 20, can.height);
let div = document.createElement("div");
div.id = id;
div.style.pointerEvents = "none";
div.style.top = "3px";
div.style.left = "0px";
div.style.position = "fixed";
div.style.zIndex = "100000";
div.style.width = document.documentElement.clientWidth + "px";
div.style.height = document.documentElement.clientHeight + "px";
div.style.background =
"url(" + can.toDataURL("image/png") + ") left top repeat";
document.body.appendChild(div);
return id;
};
// 该方法只允许调用一次
watermark.set = str => {
let id = setWatermark(str);
setInterval(() => {
if (document.getElementById(id) === null) {
id = setWatermark(str);
}
}, 2000);
window.onresize = () => {
setWatermark(str);
};
};
setWatermark('测试数据')
</script>
</body>
</html>
二. 柱状图
<!DOCTYPE html>
<html>
<head>
<title>Canvas 柱状图示例</title>
</head>
<body>
<canvas id="myChart" width="500" height="300"></canvas>
<img id="chartImage">
<script>
// 获取 canvas 元素和绘图上下文
const canvas = document.getElementById('myChart');
const ctx = canvas.getContext('2d');
// 定义数据
const data = [5, 10, 15, 20, 25];
const barWidth = 40;
const gap = 10;
const xOffset = (canvas.width - (barWidth + gap) * data.length) / 2;
const yScale = (canvas.height - 20) / Math.max(...data);
// 绘制柱状图
data.forEach((value, index) => {
const x = xOffset + (barWidth + gap) * index;
const y = canvas.height - value * yScale;
const height = value * yScale;
// 绘制矩形
ctx.fillStyle = 'blue'; // 设置填充颜色
ctx.fillRect(x, y, barWidth, height); // 绘制矩形
// 绘制数值标签
ctx.fillStyle = 'black'; // 设置字体颜色
ctx.fillText(value, x + barWidth / 2, y - 5); // 绘制文本
});
function convertToImage () {
// 使用 toDataURL 方法将 canvas 内容转换为图片数据的 URL
const imageUrl = canvas.toDataURL('image/png');
// 获取 img 元素并设置其 src 属性为图片数据的 URL
const imgElement = document.getElementById('chartImage');
imgElement.src = imageUrl;
}
convertToImage()
</script>
</body>
</html>
三. 个人签名
<!DOCTYPE html>
<html>
<head>
<title>实时签名板</title>
<style>
#signatureCanvas {
border: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="signatureCanvas" width="400" height="200"></canvas>
<button onclick="clearCanvas()">清除</button>
<button onclick="saveSignature()">保存签名</button>
<img id="1233">
<script>
const canvas = document.getElementById('signatureCanvas');
const ctx = canvas.getContext('2d');
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.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.lineCap = 'round';
ctx.stroke();
[lastX, lastY] = [e.offsetX, e.offsetY];
});
// 监听鼠标松开事件
canvas.addEventListener('mouseup', () => {
if (!isDrawing) return;
isDrawing = false;
ctx.beginPath();
});
// 监听鼠标离开canvas事件
canvas.addEventListener('mouseout', () => {
isDrawing = false;
// ctx.beginPath();
});
// 清除画布
function clearCanvas () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
// 保存签名
function saveSignature () {
const imageData = canvas.toDataURL('image/png');
const imgId = document.getElementById('1233');
imgId.src = imageData;
}
</script>
</body>
</html>
四. 球在屏幕上弹跳的效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas Bouncing Ball Game</title>
<style>
canvas {
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="480" height="320"></canvas>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
let ball = {
x: canvas.width / 2,
y: canvas.height - 30,
dx: 2,
dy: -2,
radius: 10
};
function drawBall () {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function draw () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
// Ball bounce logic
if (ball.x + ball.dx > canvas.width - ball.radius || ball.x + ball.dx < ball.radius) {
ball.dx = -ball.dx;
}
if (ball.y + ball.dy < ball.radius) {
ball.dy = -ball.dy;
} else if (ball.y + ball.dy > canvas.height - ball.radius) {
ball.dy = -ball.dy;
}
// Update ball position
ball.x += ball.dx;
ball.y += ball.dy;
// Request next frame
requestAnimationFrame(draw);
}
// Start drawing
draw();
</script>
</body>
</html>
为了方便理解,弹球逻辑也可以改成这样
// Ball bounce logic
if (ball.x === canvas.width - ball.radius || ball.x === ball.radius) {
ball.dx = -ball.dx;
}
if (ball.y === ball.radius) {
ball.dy = -ball.dy;
} else if (ball.y === canvas.height - ball.radius) {
ball.dy = -ball.dy;
}