HTML实现坐标转换成图,HTML5 Canvas的图形变换

很多时候,我们绘制出一个图形之后,并不能达到我们预期的效果,这个时候,适当地运用图形的变换(transformations,如旋转和缩放等),可以创建出大量复杂多变的图形。

1、保存和恢复Canvas状态

Canvas指的是当前画面的所有样式、变形和裁切的一个快照,以堆的方式保存。save和restore方法用于保存和恢复Canvas状态,这两个方法都不需要任何参数,用法如下:

context.save();

context.restore();

sava方法可以暂时将当前状态保存在堆中,这些状态可以是各种属性(如strokeStyle、fillStyle和globalCompositeOperation等)的值。当前应用的变形、当前裁切的路径等。restore方法用于将上一个保存状态从堆中再次取出,恢复该状态的所有设置。

举一个简单的示例:

先来看看最后的效果图:

10c3108e7ada25b96695fa9a215c2ef8.png

我们保存的Canvas状态属性值是fillStyle填充为红色,strokeStyle轮廓为蓝色,当我们没有调用restore方法恢复时,依旧使用的是我们自己定义的属性值。但是,我们可以看到当我们调用restore后,绘制出来的矩形填充以及轮廓就是我们之前保存的值。

2、移动坐标空间

在上一篇Canvas元素中我们提到过,画布的坐标空间默认的是以画布左上角(0,0)为原点,x轴水平向右为正向,y轴垂直向下为正向。而在绘制图形时,我们可以使用translate方法移动坐标空间,使画布的变换矩阵发生水平和垂直方向的偏移,其用法如下:

context.translate(dx,dy);

其中dx和dy分别为坐标原点沿水平和垂直两个方向的偏移量。如下图所示:

2fb5c520948a718a82f0c009755e6e1e.png

当然了,在进行图形变换之前,最好先要养成使用save方法保存当前状态的好习惯。在许多情况下,使用restore方法来自动恢复原来的状态要比手动恢复更高效,特别是当重复某种运算时。接下来,我们就通过绘制一个伞状图形的示例加深对它的理解。

最后的效果图:

6fd82b7f36d507d51b1e857a7ee9f5ff.png

在这里,我只想说的一点是,关于

ctx.fillRect(-1.5,0,1.5,40);和ctx.arc(-5,40,4,Math.PI,Math.PI*2,true);

这两个语句的坐标问题,主要是取决于你后面绘制的图形的宽度。

Canvas中图形移动的实现,实际上是通过改变画布的坐标原点实现的,所谓的“移动图形”,只是看上去被移动的样子,移动的是其实是坐标空间。

3、旋转坐标空间

rotate方法用于以原点为中心旋转Canvas,实质上旋转的是Canvas上下文对象的坐标空间,具体用法是:

context.rotate(angle);

rotate方法只有一个参数,即旋转角度angle,其顺时针方向为正方向,以弧度为单位,旋转中心是Canvas的原点。

拿上一个伞状例子来说,我现在的状态是一行排列的,那么我现在想要将它旋转成一个圆形队列,又该怎么实现呢?

function draw(){

var ctx = document.getElementById("myCanvas").getContext("2d");

// 垂直方向和水平方向发生了偏移

ctx.translate(150,150);

for(var i=1;i<9;i++){

ctx.save();

// 图片旋转角度

ctx.rotate(Math.PI*(2/4+i/4));

// 水平方向发生偏移

ctx.translate(0,-100);

// 绘制伞状图形的上半部分,也就是半圆部分,第二个参数表示填充颜色

drawTop(ctx,"rgb("+(30*i)+","+(255-30*i)+",255)");

// 绘制伞状图形的下半部分

drawGrip(ctx);

ctx.restore();

}

}

其实,到最后,我们会发现,只是draw方法发生了变化。具体是什么变化呢?无非就是多了ctx.rotate(Math.PI*(2/4+i/4));和ctx.translate(0,-100);语句。那么接下来,我们一起思考为什么要使用这两个方法里的数据。

首先,我们首先明确Math.PI是180度,那么很显然旋转一圈是360度,也就是说,后面的参数(2/4+i/4)中,i=1时表示初始旋转的位置,后面的则依次递加。

其次,为什么每次都要将坐标空间沿y轴负方向移动100px呢?那是因为,如果我们不移动,最后所有的图形都会重合成一个圆,就像下面这样:

2bc9e24213c786686652b9a8ab5124a3.png

而我们实际想要的效果是什么呢?

6440b7d3881a155d068ca2eca3c2113c.png

4、缩放图形

scale方法用于增减Canvas上下文对象中的像素数目,从而实现图形或位图的放大或缩小,其用法是:

context.scale(x,y);

其中x,y为必须接受的参数,x为横轴的缩放因子,y轴为纵轴的缩放因子,它们的值必须是正值。

若放大图形,参数值需大于1;

若缩小图形,参数值需小于1;

若参数值等于1,无任何效果。

我们可以用一个螺旋状由大到小的例子来深入理解缩放的使用:

其实,这也不难理解,我们反反复复使用的都是提到过的方法,唯一的不同是,我们现在把所有的方法整合在了一起,我们传递的参数不再是一个确定的值,所以,我们实现的效果也是千变万化的。

a23e6c7e5c8a393bd945d9a779188308.png

关于Canvas元素其实还有其他的很多方法,后续将会继续补充,希望大家能够共同进步!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值