> 脚本语言 > >
Canvas学习:坐标变换 2017-04-12 07:55 出处:清屏网 人气:
在Canvas里的坐标系统一节中,了解到Canvas的坐标系统如下图所示,它以Canvas画布的左上角为原点(也就是 (0,0) ), x 坐标向右方增长,而 y 坐标则向下方延伸。
然而,Canvas的坐标系统并不是一尘不变的。可以对Canvas坐标系统进行 移动 、 旋转 和 缩放 等操作。而这些操作被称为 坐标变换 。如下图所示:
在很多场景中,Canvas的坐标变换可以让我们的操作变得更简单,更灵活。今天这节我们主要来了解Canvas中的坐标变换相关的知识。
移动Translating先来看坐标变换中的移动,即 translate 方法,它用来移动Canvas和它的原点到一个不同的位置。
ctx.translate(x, y)translate 方法接受两个参数。 x 是左右偏移量, y 是上下偏移量。当偏移量操作出Canvas的 width 或 height 时,坐标将会移出Canvas的画布,这个时候你绘制的东西都将看不到。
来看一个移动的示例。为了后面更好的介绍坐标的变换,我先绘制一个坐标系统:
function drawGrid(ctx, w, h, stroke, steps){ ctx.save(); ctx.beginPath(); for (var i = 0.5; i < w; i += steps) { ctx.moveTo(i, 0); ctx.lineTo(i, h); } for(var i = 0.5; i < h; i += steps) { ctx.moveTo(0, i); ctx.lineTo(w, i); } ctx.strokeStyle = stroke; ctx.stroke(); ctx.restore(); }通过 drawGrid(ctx, w, h, '#eee', 10); 绘制一个恢复坐标系统,然后我们通过 translate() 方法来移动坐标系统:
drawGrid(ctx, w, h, '#eee', 10); ctx.translate(40, 40); drawGrid(ctx, w - 40, h - 40, 'hsl(10,70%,80%)', 10);看到的效果如下:
从上图可以看出,后面绘制出来的坐标(红色)向右向下偏移了 40 。
可以在Canvas中移动坐标系统之后,有很多时候让我们的操作变得更为方便,比如下图这样的效果:
在不使用坐标变换之前,我们需要对每个矩形的起点坐标定位:
for(var i = 0; i < 4; i++) { for (var j = 0; j < 4; j++) { ctx.fillStyle = 'rgba(' + ( 120 + j * 10 ) + ',' + ( 185 - i * 10 ) + ',' + ( 10 + j * 3 ) + ',1)'; ctx.fillRect(i * (w - 50) / 4 + (i + 1) * 10 , j * (h - 50) / 4 + (j + 1) * 10 , (w - 50) / 4, (h - 50) / 4); } }是不是感觉每次要算矩形的起点很麻烦,使用Canvas的坐标移动之后,就显得容易多了。
for(var i = 0; i < 4; i++) { for (var j = 0; j < 4; j++) { ctx.fillStyle = 'rgba(' + ( 120 + j * 10 ) + ',' + ( 185 - i * 10 ) + ',' + ( 10 + j * 3 ) + ',1)'; ctx.save(); // 通过translate移动坐标 ctx.translate(i * (w - 50) / 4 + (i + 1) * 10, j * (h - 50) / 4 + (j + 1) * 10); // 每一个矩形的起点都是(0,0) ctx.fillRect(0, 0, (w - 50) / 4, (h - 50) / 4); } }得到的 效果是一样的 。
旋转Rotating上一节看到的是坐标变换中的移动,接下来看第二个方法 rotate ,即 旋转 ,它用于以原点为中心旋转Canvas画布。
ctx.rotate(angle)rotate() 方法只接受一个参数,旋转的角度 angle ,它是顺时针方向的,以弧度为单位的值。
同样的,我们来看一个示例。
// 默认坐标系统 drawGrid(ctx, w, h, '#eee', 10); // 旋转后坐标系统 ctx.rotate(Math.PI / 6); drawGrid(ctx, w, h, 'hsl(10,70%,80%)', 10);这个时候坐标系统旋转了 Math.PI / 6 也就是 30 度:
从上面的可以看出,坐标旋转它始终是围绕Canvas坐标原点 (0,0) 进行旋转,如果需要改变的话,就要借助坐标变换中的移动 translate() 方法。
比如下面这个效果:
先通过 translate() 方法将坐标移动到Canvas画布的中心,然后 rotate() 方法旋转的中心都在移动后的画布原点(也就是说,当初的 (0,0) 变成现在的 (w/2,h/2) )。
drawGrid(ctx, w, h, '#eee', 10); // 将Canvas画布移动到画布的中心位置 ctx.translate(w / 2, h / 2); for(var i = 0; i < 10; i++) { ctx.save(); ctx.fillStyle = 'rgb(' + (51 * i ) + ',' + ( 255 - 51 * i ) + ',255)'; for (var j = 0; j < i * 10; j++) { // 旋转坐标 ctx.rotate(Math.PI * 2 / (i * 10)); ctx.beginPath(); // 绘制圆 ctx.arc(0, i * 20, 5, 0, Math.PI * 2, true); ctx.fill(); } ctx.restore(); }这样一来你将 看到上图的效果 。
在很我实际场景中,我们对某个图形元素做旋转,默认情况之下,其旋转都会围绕Canvas坐标系统原点 (0,0) 进行旋转。但实际上,我们需要围绕元素中心点来做旋转。在CSS中,我们有一个 transform-origin 属性可以修改原点。但在Canvas中,就需要借助Canvas的坐标变换中的 translate() 方法来修改元素的原点,也就是将原点移动到元素的中心位置。
比如我们绘制一个矩形:
var x = 100; var y = 100; var width = 100; var height = 100; ctx.strokeRect(x, y, width, height);上面将一个正方形绘制在 100, 100 位置处: