Canvas学习笔记 Canvas的基础知识点(下)
三、绘制图片
核心:必须要onload
之后才能够绘制图片。
//实例化image属性
const img = new Image();
img.src = "./images/test.png";
// 必须要在onload挂载之后绘制图片
img.onload = function () {
ctx.drawImage(img, 0, 0); //后两个参数为绘画的路径位置
}
上面是三个参数的,若是有五个参数,多出来的参数能够设置宽、高:
ctx.drawImage(img, 0, 0, 600, 400);
若是有9个参数,除开第一个前面四个指的是原图进行的切片,后面四个指的是切片放置的位置:
- 含义:从原图上的(408,81)位置切下来宽147、高182的切片图放置到canvas中(200,200)位置的宽147、高182。
切片结果:
目的:就是截取原图上指定区域并且最终绘制到我们的指定canvas画布上!
实操
我们实操一下:
//实例化image属性
const img = new Image();
img.src = "./images/test.png";
// 必须要在onload挂载之后绘制图片
img.onload = function () {
ctx.drawImage(img, 369, 435, 1181, 360, 0, 0, 1181, 360);
}
达到目标:
四、资源管理器(手动创建类进行管理)
设立资源管理员的原因是在开发例如游戏的时候,会有一些静态资源需要请求回来的,若是直接开始,某些静态资源没有获取到页面上就会显示空或者直接报错,举例子如游戏背景图界面等,所以我们要手动创建一个资源管理器来进行管理我们的整个进程。
示例:一旦我们的资源加载完毕了,就可以开始使用资源了如下图的绘制多张图片操作!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用桃心形方程绘制爱心</title>
</head>
<body>
<canvas id="mycanvas" width="1500" height="400"></canvas>
<script>
/** @type {HTMLCanvasElement} */
var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');
//创建资源管理器
function Game() {
this.dom = document.getElementById('mycanvas');
this.ctx = this.dom.getContext("2d");
this.R = {
"1": "./images/1.png",
"2": "./images/2.jpg",
"3": "./images/3.jpg",
"4": "./images/4.png",
}
// 加载资源
const counts = Object.keys(this.R).length;
let count = 0;
let height = 50;
for (let key in this.R) {
const src = this.R[key];
this.R[key] = new Image();
this.R[key].src = src;
const self = this;
// 异步方法:游戏开始方法函数只能够写在其内部中进行!!!
this.R[key].onload = () => {
count++;
this.ctx.clearRect(10, 10, 200, 50);
self.ctx.font = "12px serif";
self.ctx.fillText("资源" + count + "已加载完毕!", 10, 30);
console.log(height);
// self.ctx.drawImage(self.R[key], 10, height, 200, 150);
height += 150;
if (count == counts) {
this.start();//等待资源加载完毕之后可以开始游戏!
}
}
}
}
// 等待资源结束之后开始执行......
Game.prototype.start = function () {
let width = 10;
//业务逻辑
for (let item in this.R) {
this.ctx.drawImage(this.R[item], width, 50, 200, 150)
width += 220;
}
}
console.log(new Game());;
</script>
</body>
</html>
五、变形
5.1、transloate(移动画布)
核心API:
//变形
ctx.transloate(50,50); //将canvas画布进行x轴、y轴平移,平移之后绘制图时就需要按照平移后的坐标进行
//保存当前状态
ctx.save();//举个例子吧你是用translate进行画布平移前使用保存,之后恢复状态再
//回复到以前的状态(包含画布原本位置,线、填充样式等等),已经绘画好的不会消失
ctx.restore();
通常进行变形的画布会不可控,所以我们需要配合save与restore来进行保存与恢复状态,从而可控。
示例:
<body>
<canvas id="mycanvas" width="1500" height="400"></canvas>
<script>
/** @type {HTMLCanvasElement} */
var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');
// 保存画布状态
ctx.save();
ctx.fillStyle = "red";
// 移动画布位置
ctx.translate(100, 40);
// ctx.rotate(0.5);
ctx.arc(0, 0, 40, 0, Math.PI * 2, false);
ctx.fill();
// 恢复画布之前状态
ctx.restore();
ctx.fillRect(0, 100, 50, 50);
</script>
</body>
5.2、rotate(画布旋转)
效果:将整个画布来进行来进行指定角度的旋转,左上角为中心点。
核心API:
ctx.rotate(0.5); //表示整个画布顺时针旋转5°
注意点:对于restore之前的绘制的图片好像木有影响!
示例:
<body>
<canvas id="mycanvas" width="1500" height="400"></canvas>
<script>
/** @type {HTMLCanvasElement} */
var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');
ctx.save();
ctx.fillStyle = "red";
ctx.translate(100, 40);
// ctx.rotate(0.5);
ctx.arc(0, 0, 40, 0, Math.PI * 2, false);
ctx.fill();
ctx.restore();
// 进行旋转,需要在绘制前进行旋转才有效果
ctx.rotate(5 * Math.PI / 180);
ctx.fillRect(0, 100, 50, 50);
</script>
</body>
5.3、scale(缩小绘制目标)
包含两个参数:分别表示宽、高缩小的比例。
核心API:
ctx.scale(0.8, 0.8);//缩小80%,注意不能够进行放大!
示例:
<body>
<canvas id="mycanvas" width="1500" height="400"></canvas>
<script>
/** @type {HTMLCanvasElement} */
var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = "black";
ctx.scale(1.0, 1.0);//初始状态
ctx.fillRect(0, 0, 100, 100);
ctx.scale(0.8, 0.8);//缩小80%
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, 100, 100);
ctx.scale(.5, .5)// 缩小50%
ctx.fillStyle = "red";
ctx.fillRect(0, 0, 100, 100);
</script>
</body>
transform(三个元素统一写)
核心API:可以对指定待绘制的元素进行移动、倾斜(旋转)、缩放的设置,就正好对应了前面的三个属性
ctx.setTransform(a, b, c, d, e, f);
a (m11)
水平缩放。
b (m12)
垂直倾斜。
c (m21)
水平倾斜。
d (m22)
垂直缩放。
e (dx)
水平移动。
f (dy)
垂直移动。
示例:
<body>
<canvas id="mycanvas" width="1500" height="400"></canvas>
<script>
/** @type {HTMLCanvasElement} */
var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');
//水平缩放:1 垂直倾斜:1 水平倾斜:0 1-3 垂直倾斜指的是垂直向下倾斜;反之平行向右
//垂直缩放:1 水平移动:0 垂直移动:0 4-6
ctx.setTransform(1, 0, 1, 1, 0, 0);
ctx.fillRect(0, 0, 100, 100);
</script>
</body>
六、合成(globalCompositeOperation)
核心API:
# 在绘制的两个图案之间设置属性,不仅可以在已有图形后面再画新图形,还可以用来遮盖指定区域,清除画布中的某些部分
ctx.globalCompositeOperation = "destination-out"; # 该属性就是后面绘制的图案会压盖掉原本的图案
示例:
<body>
<canvas id="mycanvas" width="400px" height="400px">
</canvas>
<div class="mbody"></div>
<script>
/** @type {HTMLCanvasElement} */
const mcanvas = document.getElementById("mycanvas");
const ctx = mcanvas.getContext("2d");
//绘制的第一个图案
ctx.fillRect(50, 50, 100, 100);
//设置合成属性 ctx=globalCompositeOperation = "destination-out";
// 绘制的第二个图案
ctx.beginPath();
ctx.fillStyle = "red";
ctx.arc(150, 150, 50, 0, 7, false);
ctx.fill();
</script>
</body>
当在canvas板上绘制多个图案时,如下图后绘制的会有压盖效果:
若是我们想要对压盖的内容做一些处理,如压盖部分清除、只留下压盖部分等等等等,都可以在中间设置指定的合成样式就会有对应的效果啦!
对应案例如下:
还有…
实战
1、车轮滚动(核心使用rotate)
提前知识预备
需要用到属性:rotate、translate、drawImg…
核心是rotate
属性进行轮子旋转转动:我们知道rotate属性是针对于canvas画布左上角作为中心点进行顺时针移动的,我们要想让某个图片实现自转效果,需要将该图片圆心位置置于右上角,之后配合rotate属性实现滚动效果!!!
例如:图书属性为400*400,我们要想让图片中心位于画布左上角,则需要指定绘制位置
const img = new Image();
img.src = "./images/wheel.png";
img.onload = () => {
ctx.drawImage(img, -400 / 2, -400 / 2); //通常这里来进行指定绘画位置
}
- 注意:若是图片过大,请直接在外部设置图片的长宽,不要使用scale属性缩小,之后在进行旋转时会出现问题!
接着我们设置一个定时器即可让其进行转动起来!
OK了之后我们配合translate属性将其移至到我们屏幕中央,这就又需要配合save与restore属性了,直接见案例!
实际示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用桃心形方程绘制爱心</title>
<style>
canvas {
border: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="mycanvas" width="1500" height="400"></canvas>
<script>
/** @type {HTMLCanvasElement} */
var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');
const img = new Image();
img.src = "./images/wheel.png";//895*895
let deg = 0.1;//旋转角度
let movePos = 200;//初始移动位置
let moveR = 5;//向右移动位置
img.onload = () => {
// ctx.scale(0.2, 0.2); //禁止使用scale来进行图片缩放对于滚动效果,会有问题!
setInterval(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height)
deg += 0.5;
movePos += moveR;
if (movePos == 1500 || movePos == 0) {
moveR = -moveR;
}
//由于使用到了translate就一定要使用save与restore!
ctx.save();
ctx.translate(movePos, 400 / 2);
ctx.rotate(deg)
ctx.drawImage(img, -400 / 2, -400 / 2);
ctx.restore();
}, 30);
}
</script>
</body>
</html>
2、开刮刮乐(核心使用合成)
通过利用合成属性来实现的开刮刮乐效果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用桃心形方程绘制爱心</title>
<style>
div {
width: 150px;
height: 60px;
font-size: 20px;
line-height: 60px;
/* border: 1px solid #000; */
text-align: center;
position: relative;
/* 设置文字不能被选中,也就是不能选中拖动查看文字! */
user-select: none;
}
canvas {
position: absolute;
left: 0;
top: 0;
right: 0;
}
</style>
</head>
<body>
<div>
超级特等奖
<canvas width="150px" height="60px"></canvas>
</div>
<script>
/** @type {HTMLCanvasElement} */
var canvas = document.querySelector("canvas");
var ctx = canvas.getContext('2d');
// 将div元素进行覆盖
ctx.fillStyle = "gray";
ctx.fillRect(0, 0, 150, 60);
// 使用合成效果(当有新的绘制内容压盖上来时就会清除掉原本的内容)
ctx.globalCompositeOperation = "destination-out";
// 实现鼠标按下移动才能够进行刮刮乐
//监控鼠标是否按下,只有按下了移动才会有擦除功能!
let isDown = false;
canvas.onmousedown = function () {
isDown = true;
}
canvas.onmouseup = function () {
isDown = false;
}
canvas.onmousemove = function (e) {
if (isDown) {
console.log(e.offsetX, e.offsetY);
ctx.beginPath();
ctx.arc(e.offsetX, e.offsetY, 8, 0, 7, false);
ctx.fill();
}
}
</script>
</body>
</html>
示例
用 canvas 做个好玩的网站背景:网站背景粒子效果。
参考文章
[1]. 廖雪峰canvas
</head> <body> // 将div元素进行覆盖
ctx.fillStyle = "gray";
ctx.fillRect(0, 0, 150, 60);
// 使用合成效果(当有新的绘制内容压盖上来时就会清除掉原本的内容)
ctx.globalCompositeOperation = "destination-out";
// 实现鼠标按下移动才能够进行刮刮乐
//监控鼠标是否按下,只有按下了移动才会有擦除功能!
let isDown = false;
canvas.onmousedown = function () {
isDown = true;
}
canvas.onmouseup = function () {
isDown = false;
}
canvas.onmousemove = function (e) {
if (isDown) {
console.log(e.offsetX, e.offsetY);
ctx.beginPath();
ctx.arc(e.offsetX, e.offsetY, 8, 0, 7, false);
ctx.fill();
}
}
</script>
</body> </html> ```
[外链图片转存中…(img-WInbZUfD-1652052808606)]
示例
用 canvas 做个好玩的网站背景:网站背景粒子效果。
参考文章
[1]. 廖雪峰canvas
- 点赞
- 收藏
- 关注作者
评论(0)