canvas可以变形,单变形的不是元素,二十ctx,ctx是整个画布的渲染区域,整个画布在变形。所以需要在画布变形前,进行保存和恢复
save()保存画布的所有状态
restore()恢复画布的状态
save 和 restore 方法是用来保存和恢复 canvas 状态的,都没有参数。Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。
可能保存的状态有:
当前应用的变形(即移动,旋转和缩放,见下)
以及下面这些属性:strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, lineDashOffset, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font, textAlign, textBaseline, direction, imageSmoothingEnabled
1、translate
translate和CSS3的translate属性一样也是发挥着空间平移作用
ctx.translate(50, 50);
ctx.fillRect(0, 0, 120, 120);
// 渲染位置是没有存档之前的位置
ctx.fillRect(120, 220, 120, 120)
此时发现上图的第二次的渲染位置和预期不一致,上图的第二次渲染预期x的位置是120,但是由于第一次进行了变形操作,整体画布移动了50,所以位置变成170
我们知道了变形实际上都是将整个画布进行的变形,所以如果一旦我们的变形操作多了,画布将变得不可控
所以如果我们使用到变形,一定记住下面的规律:变形之前要先备份,将世界和平的状态进行备份,然后再变形,变形完毕后一定要恢复到世界和平的样子,不要影响下一次的操作
下面的代码是正确的操作
// 保存
ctx.save();
ctx.translate(50, 50);
ctx.fillRect(0, 0, 120, 120);
// 恢复
ctx.restore();
// 渲染位置是没有存档之前的位置
ctx.fillRect(0, 220, 120, 120)
2、rotate
ctx.save();
ctx.translate(150, 150);
ctx.rotate(deg)
ctx.fillRect(0, 0, 120, 120);
// 恢复
ctx.restore();
原地打转:关于旋转圆心的问题 希望大佬帮助解释解释,有点迷糊
<script>
var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
var deg = 0;
setInterval(function(){
ctx.clearRect(0,0,1200,800);
//保存
ctx.save()
deg +=0.1;
ctx.translate(150,150);
ctx.fillStyle = "green";
ctx.rotate(deg);
ctx.fillRect(75,75,-150,-150)
//恢复
ctx.restore()
ctx.fillStyle = "skyblue";
ctx.fillRect(75,75,150,150);
},20)
</script>
3、scale
和CSS3中的scale不同的是,canvas的scale是两个参数,分别代表了x,y。都必须是正数。1.0为正常比例,大于1代表放大,小于1代表缩小
// 保存
ctx.save();
ctx.translate(150, 150);
ctx.scale(0.5, 0.5)
ctx.fillRect(0, 0, 120, 120);
// 恢复
ctx.restore();
// 渲染位置是没有存档之前的位置
ctx.fillRect(0, 120, 120, 120)
使用transform进行属性的translate、rotate、scale的综合写法
transform(a, b, c, d, e, f)
- a (m11)水平方向的缩放
- b(m12)竖直方向的倾斜偏移
- c(m21)水平方向的倾斜偏移
- d(m22)竖直方向的缩放
- e(dx)水平方向的移动
- f(dy)竖直方向的移动
ctx.transform(0.5, 1.1, 1.1, 0.5, 100, 100)
4、滚动的车轮
//获取dom
var canvas = document.getElementById("mycanvas");
//获取上下文
var ctx = canvas.getContext("2d");
var img = new Image();
img.src = "images/lunzi.png";
img.onload = function(){
// 定时器
// 旋转的度数
var deg = 0;
var x=187;
setInterval(function(){
ctx.clearRect(0,0,1200,800);
deg += 0.01;
x++;
//保存
ctx.save();
ctx.translate(x,200);
ctx.rotate(deg);
ctx.drawImage(img,-374/2,-374/2)
//恢复
ctx.restore();
})
}