一、理解Canvas
Canvas是一个HTML5元素,用于在Web页面上绘制2D或3D图形。它允许使用JavaScript在网页上创建和操作图形。Canvas的主要功能是绘图,但也可以用来实现其他功能,如动画和交互式游戏。
使用Canvas,可以创建各种形状、路径、文本和图像。可以使用JavaScript绘制直线、矩形、圆形、弧形等基本形状。通过使用path API,可以创建复杂的形状和路径。同时,还可以在Canvas上添加图像,通过缩放、旋转、移动等操作进行处理。
Canvas还可以用于创建动画效果。可以使用JavaScript逐帧地修改和更新Canvas元素,从而创建动画效果。可以使用setTimeout()或requestAnimationFrame()函数来控制动画的帧速率和时间。
除了绘图和动画,Canvas还可以用来实现交互式游戏。可以使用Canvas元素检测鼠标、键盘等用户输入,根据用户的输入进行相应操作,从而实现游戏的交互性。
总之,Canvas是一个强大的HTML5工具,可以用于创建各种图形和动画效果,并实现交互式网页应用程序。
二、项目介绍
本文项目 vue3 + ts
三、Canvas的使用方法
Canvas是HTML5新增的一个标签,用于绘制图形,动画等。这里简单介绍一下Canvas的使用方法。
3.1、创建Canvas元素
在HTML中使用<canvas>标签创建Canvas元素,需要指定Canvas的宽度和高度,例如:
<canvas id="myCanvas" width="400" height="400"></canvas>
3.2、获取Canvas上下文
在JavaScript中,需要使用Canvas元素的getContext()方法获取Canvas的上下文对象,通过上下文对象可以对Canvas进行绘制,例如:
import { onMounted } from "vue";
// 获取Canvas上下文
onMounted(()=>{
let canvas: any = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");
})
四、绘制基本图形
4.1、绘制一条直线
<template>
<div class="contmian">
<canvas id="myCanvas" width="400" height="400"></canvas>
</div>
</template>
<script setup lang="ts">
import { onMounted } from "vue";
// 获取Canvas上下文
onMounted(()=>{
let canvas: any = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");
// 绘制一条直线
ctx.beginPath();
ctx.moveTo(0, 0); //起点
ctx.lineTo(200, 200); //终点
ctx.stroke(); //绘制线条
})
</script>
<style scoped lang="less">
</style>
4.2、绘制一个矩形
<template>
<div class="contmian">
<canvas id="myCanvas" width="400" height="400"></canvas>
</div>
</template>
<script setup lang="ts">
import { onMounted } from "vue";
// 获取Canvas上下文
onMounted(()=>{
let canvas: any = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");
// 绘制一个矩形
ctx.beginPath();
ctx.rect(50, 50, 100, 100); //x轴坐标,y轴坐标,宽度,高度
ctx.fill(); //填充矩形
})
</script>
<style scoped lang="less">
</style>
4.3、绘制一个圆形
<template>
<div class="contmian">
<canvas id="myCanvas" width="400" height="400"></canvas>
</div>
</template>
<script setup lang="ts">
import { onMounted } from "vue";
// 获取Canvas上下文
onMounted(()=>{
let canvas: any = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");
// 绘制一个圆形
ctx.beginPath();
ctx.arc(200, 200, 100, 0, 2*Math.PI); //中心点x轴坐标,中心点y轴坐标,半径,起始角度,终止角度
ctx.stroke(); //绘制圆形
})
</script>
<style scoped lang="less">
</style>
4.4、绘制图像
通过Canvas的上下文对象,还可以绘制图像,例如:
<template>
<div class="contmian">
<canvas id="myCanvas" width="400" height="400"></canvas>
</div>
</template>
<script setup lang="ts">
import { onMounted } from "vue";
// 获取Canvas上下文
onMounted(()=>{
let canvas: any = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");
// 绘制图像
var img = new Image();
img.src = "../../../public/docker.png";
img.onload = function() {
ctx.drawImage(img, 50, 50, 200, 200); //绘制图像,x轴坐标,y轴坐标,宽度,高度
}
})
</script>
<style scoped lang="less">
</style>
4.5、绘制动画
通过setInterval()方法可以实现Canvas上的动画效果,例如:
<template>
<div class="contmian">
<canvas id="myCanvas" width="400" height="400"></canvas>
</div>
</template>
<script setup lang="ts">
import { onMounted } from "vue";
// 获取Canvas上下文
onMounted(()=>{
let canvas: any = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");
// 绘制动画
var x = 0;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height); //清除画布
ctx.beginPath();
ctx.rect(x, 50, 50, 50); //绘制矩形
ctx.fill();
x++;
console.log(x)
if(x > 400){
clearInterval(timer)
}
}
const timer = setInterval(draw, 10); //每10毫秒调用一次draw()函数
})
</script>
<style scoped lang="less">
</style>
以上是Canvas的基本使用方法,还有很多其他功能可以通过Canvas实现,需要进一步学习和掌握。
五、canvas Demo
5.1、canvas实现流星雨
<template>
<div class="contmian">
<canvas id="myCanvas" width="400" height="400"></canvas>
</div>
</template>
<script setup lang="ts">
import { onMounted } from "vue";
// 获取Canvas上下文
onMounted(()=>{
let canvas: any = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");
// 设置canvas宽度和高度
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// 定义流星雨粒子对象
function Particle (x, y, vx, vy, size, color) {
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.size = size;
this.color = color;
}
// 定义流星雨数组
let particles = [];
// 创建流星雨粒子函数
const createParticle = () => {
let x = Math.random() * canvas.width; // 随机横坐标
let y = Math.random() * canvas.height; // 随机纵坐标
let vx = -(Math.random() * 2 + 3); // x方向速度
let vy = Math.random() * 2 + 2; // y方向速度
let size = Math.random() * 3 + 1; // 大小
let color = "#ff0000"; // 颜色
particles.push(new Particle(x, y, vx, vy, size, color));
}
// 绘制流星雨
const draw = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height); // 清空canvas
for (let i = 0; i < particles.length; i++) {
let p = particles[i];
ctx.beginPath();
ctx.fillStyle = p.color;
ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2, false);
ctx.fill();
p.x += p.vx;
p.y += p.vy;
if (p.x < -p.size || p.y > canvas.height + p.size) {
// 如果粒子出了画布则删除
particles.splice(i, 1);
i--;
}
}
requestAnimationFrame(draw);
}
// 创建流星雨粒子
setInterval(createParticle, 50);
// 开始绘制流星雨
draw();
})
</script>
<style scoped lang="less">
</style>
通过以上代码可以实现一个简单的canvas流星雨。如果需要更加复杂的效果可以调整粒子的属性值或添加其他动画效果。
5.2、canvas实现修改图片色调、饱和度、亮度
<template>
<div class="contmian">
<h1>Canvas修改图片色调、饱和度、亮度</h1>
<p>请选择图片文件:</p>
<input type="file" accept="image/*" @change="loadImage">
<h2>修改颜色</h2>
<p>
<label for="hue">色调:</label>
<input type="range" id="hue" min="0" max="360" value="0" @change="updateColor()">
</p>
<p>
<label for="saturation">饱和度:</label>
<input type="range" id="saturation" min="0" max="2" step="0.01" value="1" @change="updateColor()">
</p>
<p>
<label for="lightness">亮度:</label>
<input type="range" id="lightness" min="0" max="2" step="0.01" value="1" @change="updateColor()">
</p>
<canvas id="canvas"></canvas>
</div>
</template>
<script setup lang="ts">
import { onMounted } from "vue";
// 获取Canvas上下文
let ctx:any = {}
let canvas:any = {}
onMounted(()=>{
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
})
let img:any;
const loadImage = (e: any) => {
console.log('35', e)
let reader = new FileReader();
reader.onload = function(event: any) {
img = new Image();
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
};
img.src = event.target.result;
};
reader.readAsDataURL(e.target.files[0]);
}
const updateColor = () => {
let hue = document.getElementById('hue').value;
let saturation = document.getElementById('saturation').value;
let lightness = document.getElementById('lightness').value;
let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
let data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
let hsl = rgbToHsl(data[i], data[i+1], data[i+2]);
hsl[0] = (hsl[0] + hue) % 360;
hsl[1] = hsl[1] * saturation;
hsl[2] = hsl[2] * lightness;
let rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
data[i] = rgb[0];
data[i+1] = rgb[1];
data[i+2] = rgb[2];
}
ctx.putImageData(imageData, 0, 0);
}
// RGB转HSL
const rgbToHsl = (r: any, g: any, b: any) => {
r /= 255, g /= 255, b /= 255;
let max = Math.max(r, g, b), min = Math.min(r, g, b);
let h: any, s: any, l = (max + min) / 2;
if(max == min){
h = s = 0;
}else{
let d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch(max){
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [h * 360, s, l];
}
// HSL转RGB
const hslToRgb = (h:any, s:any, l: any) => {
let r:any, g:any, b:any;
if(s == 0){
r = g = b = l;
}else{
function hue2rgb(p:any, q:any, t:any){
if(t < 0) t += 1;
if(t > 1) t -= 1;
if(t < 1/6) return p + (q - p) * 6 * t;
if(t < 1/2) return q;
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
}
let q = l < 0.5 ? l * (1 + s) : l + s - l * s;
let p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return [r * 255, g * 255, b * 255];
}
</script>
<style scoped lang="less">
</style>
在这个示例中,使用<input>元素选择图像文件,并在加载图像时绘制在canvas上。使用三个<input>元素来控制色调、饱和度和亮度。在更新颜色值时,使用getImageData()方法获取图像的像素数据。遍历像素数据并将每个像素的RGB颜色值转换为HSL值,并根据选择的色调、饱和度和亮度值进行修改。然后将修改后的像素数据使用putImageData()方法重新绘制到canvas上。 请注意,这个示例的性能可能受到图像大小和计算复杂度的影响。如果需要处理大型图像或者进行更复杂的颜色修改,请考虑使用WebGL或其他高性能图形库。
5.3、canvas实现通过点击事件修改图片中点中区域元素内容颜色为指定颜色
以下是一个使用HTML canvas实现通过点击事件修改图片中点中区域元素内容颜色为指定颜色的示例代码。
<template>
<div class="contmian">
<h1>Canvas通过点击事件修改图片中点中区域元素内容颜色</h1>
<p>请选择图片文件:</p>
<input type="file" accept="image/*" @change="loadImage">
<h2>修改颜色</h2>
<p>
<label for="color">颜色:</label>
<input type="color" id="color" value="#ff0000">
</p>
<canvas id="canvas"></canvas>
</div>
</template>
<script setup lang="ts">
import { onMounted } from "vue";
// 获取Canvas上下文
let ctx:any = {}
let canvas:any = {}
let color:any = {}
onMounted(()=>{
canvas = document.getElementById("canvas");
canvas.addEventListener('click', updateColor);
ctx = canvas.getContext("2d");
color = document.getElementById('color').value;
})
let img:any;
const loadImage = (e: any) => {
var reader = new FileReader();
reader.onload = function(event) {
img = new Image();
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
};
img.src = event.target.result;
};
reader.readAsDataURL(e.target.files[0]);
}
const updateColor = (e) => {
var x = e.offsetX;
var y = e.offsetY;
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
var index = (x + y * imageData.width) * 4;
data[index] = parseInt(color.substr(1, 2), 16);
data[index + 1] = parseInt(color.substr(3, 2), 16);
data[index + 2] = parseInt(color.substr(5, 2), 16);
ctx.putImageData(imageData, 0, 0);
}
</script>
<style scoped lang="less">
canvas {
border: 1px solid black;
}
</style>
在这个示例中,使用<input>元素选择图像文件,并在加载图像时绘制在canvas上。使用<input>元素选择要更改元素的颜色。 使用addEventListener()方法在canvas上添加点击事件监听器。在事件处理程序中,获取鼠标点击位置的x和y坐标,并使用getImageData()方法获取图像的像素数据。计算要更改的像素的索引,并将其颜色更改为所选颜色。使用putImageData()方法重新绘制修改后的图像数据。 请注意,此示例仅在单击canvas上的图像时更改指定像素的颜色。您可以根据需要修改更改颜色的逻辑和条件。
5.4、canvas实现刮刮乐
以下是一个使用HTML canvas实现刮刮乐效果的示例代码。
<template>
<div class="contmian">
<h1>Canvas实现刮刮乐效果</h1>
<p>刮奖面板:</p>
<canvas id="canvas"></canvas>
</div>
</template>
<script setup lang="ts">
import { onMounted } from "vue";
// 获取Canvas上下文
let ctx:any = {}
let canvas:any = {}
let isDrawing = false;
let img:any;
onMounted(()=>{
canvas = document.getElementById("canvas");
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
canvas.addEventListener('mouseleave', stopDrawing);
ctx = canvas.getContext("2d");
init();
})
const init = () => {
canvas.width = 400;
canvas.height = 200;
ctx.fillStyle = '#ddd';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.font = 'bold 30px Arial';
ctx.fillStyle = '#f00';
ctx.fillText('刮一刮', 120, 100);
img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
};
img.src = 'image.jpg';
}
const startDrawing = () => {
isDrawing = true;
}
const stopDrawing = () => {
isDrawing = false;
}
const draw = (e) => {
if (!isDrawing) return;
var x = e.offsetX;
var y = e.offsetY;
ctx.globalCompositeOperation = 'destination-out';
ctx.beginPath();
ctx.arc(x, y, 20, 0, Math.PI * 2, false);
ctx.fill();
}
</script>
<style scoped lang="less">
canvas {
border: 1px solid black;
}
</style>
在这个示例中,使用<canvas>
元素创建刮刮乐面板并绘制了一个图像。当鼠标在canvas上按下时,设置isDrawing
变量为true
。当鼠标移动时,如果isDrawing
为true
,则使用globalCompositeOperation
属性将画笔设置为destination-out
模式,这样每次涂抹时都会将像素颜色变成透明颜色。在鼠标弹起或离开canvas时,设置isDrawing
为false
,停止绘制涂层。
此示例中,使用了一个灰色矩形覆盖图像,但是您可以使用任何其他的遮罩层,或者在涂抹时使用自己的颜色。
5.5、canvas玩转图片
用canvas玩转图片【渡一教育】_哔哩哔哩_bilibili
六、html 转 canvas
HTML如何转化为canvas教程_htmltocanvas-CSDN博客
七、过程记录
7.1、Caught error TypeError: Cannot read properties of null (reading 'getContext')
注意获取Canvas上下文的生命周期,在onMounted里边即可
import { onMounted } from "vue";
7.2、html 转 canvas
HTML转Canvas的原理如下
1. 首先,将HTML中的DOM元素(如div、p、img等)转换为Canvas上的元素。
2. 然后,将CSS样式应用到Canvas上的元素。这意味着,需要将HTML中的样式计算出来,并将其应用到Canvas上。
3. 接下来,需要将HTML中的所有内容都绘制到Canvas上。这可以通过在Canvas上使用绘图API(如绘制文本、图像、路径等)来完成。
4. 最后,需要将Canvas上的内容转换为图像或数据,以便将其保存或上传至服务器等操作。
总体来说,HTML转Canvas的过程可以分为三个主要阶段:解析HTML和CSS、将内容绘制到Canvas上、将Canvas内容转换为图像或数据。
demo待完成
八、欢迎交流指正
九、参考链接
Canvas详解-CSDN博客
Canvas 基础使用_canvas 字体_19岁的墨先生的博客-CSDN博客
HTML 画布 | 菜鸟教程
学习 HTML5 Canvas 这一篇文章就够了 | 菜鸟教程
HTML5 Canvas | 菜鸟教程
Canvas 教程 - Web API 接口参考 | MDN
canvas基础简单易懂教程(完结,多图)_canvas教程-CSDN博客
canvas详细入门教程(1W字 吐血分享)_canvas教程-CSDN博客
解决canvas清晰度的问题【渡一教育】_哔哩哔哩_bilibili
canvas动画【渡一教育】_哔哩哔哩_bilibili
文字也能很酷炫【渡一教育】_哔哩哔哩_bilibili
用canvas玩转图片【渡一教育】_哔哩哔哩_bilibili