欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

获取Canvas当前坐标系矩阵 - 方帅 -

程序员文章站 2022-10-31 15:13:55
获取canvas当前坐标系矩阵 前言 在我的另一篇博文canvas坐标系转换中,我们知道了所有的平移缩放旋转操作都会影响到画布坐标系。那在我们对画布进行了一系列操作之后,怎么再知道当前矩阵数据状态呢...

获取canvas当前坐标系矩阵 前言

在我的另一篇博文canvas坐标系转换中,我们知道了所有的平移缩放旋转操作都会影响到画布坐标系。那在我们对画布进行了一系列操作之后,怎么再知道当前矩阵数据状态呢。

具体代码

首先请看下面的一段代码(下文具体解释代码作用):

 1 window.tracktransform = function () {
 2     var svg = document.createelementns("https://www.w3.org/2000/svg", 'svg');
 3     var xform = svg.createsvgmatrix();
 4     var savedtransforms = [];
 5     this.tracktransform=function(ctx) {
 6         
 7         ctx.gettransform = function () { return xform; };
 8         
 9         var save = ctx.save;
10         ctx.save = function () {
11             savedtransforms.push(xform.translate(0, 0));
12             return save.call(ctx);
13         };
14         var restore = ctx.restore;
15         ctx.restore = function () {
16             xform = savedtransforms.pop();
17             return restore.call(ctx);
18         };
19         
20         var scale = ctx.scale;
21         ctx.scale = function (sx, sy) {
22             xform = xform.scalenonuniform(sx, sy);
23             return scale.call(ctx, sx, sy);
24         };
25         var rotate = ctx.rotate;
26         ctx.rotate = function (deg) {
27             
28             var radians = deg * math.pi / 180;
29             xform = xform.rotate(deg);
30             return rotate.call(ctx, radians);
31         };
32         var translate = ctx.translate;
33         ctx.translate = function (dx, dy) {
34             xform = xform.translate(dx, dy);
35             return translate.call(ctx, dx, dy);
36         };
37         var transform = ctx.transform;
38         ctx.transform = function (a, b, c, d, e, f) {
39             var m2 = svg.createsvgmatrix();
40             m2.a = a; m2.b = b; m2.c = c; m2.d = d; m2.e = e; m2.f = f;
41             xform = xform.multiply(m2);
42             return transform.call(ctx, a, b, c, d, e, f);
43         };
44         var settransform = ctx.settransform;
45         ctx.settransform = function (a, b, c, d, e, f) {
46             xform.a = a;
47             xform.b = b;
48             xform.c = c;
49             xform.d = d;
50             xform.e = e;
51             xform.f = f;
52             return settransform.call(ctx, a, b, c, d, e, f);
53         };
54         var pt = svg.createsvgpoint();
55         //通过原坐标系点x,y求对应当前坐标系的坐标值
56         ctx.transformedpoint = function (x, y) {
57             pt.x = x; pt.y = y;
58             return pt.matrixtransform(xform.inverse());
59         }
60         var pt2 = svg.createsvgpoint();
61         //当前坐标系中的的xy还原到原坐标系坐标值
62         ctx.transformedpoint2 = function (x, y) {
63             pt2.x = x; pt2.y = y;
64             return pt2.matrixtransform(xform);
65         }
66         var clearrect = ctx.clearrect;
67         ctx.clearrect = function (x, y, w, h) {
68             ctx.save();
69             ctx.settransform(1, 0, 0, 1, 0, 0);
70             clearrect.call(ctx, x, y, w, h);
71             ctx.restore();
72         }
73     }
74 }

代码中主要定义了一个类tracktransform,重写了canvasrenderingcontext2d对象的save,restore,scale,rotate,translate,transform,settransform,clearrect方法。

tracktransform类使用

如何使用window.tracktransform类呢?通过以下两句代码,变量contex的转换方法即进行了重写。

1 //初始化矩阵转换; context为 getcontext("2d")所得的canvasrenderingcontext2d对象。
2 var track = new tracktransform();
3 track.tracktransform(context);
方法详解

具体解释上面各行代码的作用

1 创建矩阵对象xform
 2     var svg = document.createelementns("https://www.w3.org/2000/svg", 'svg');
 3     var xform = svg.createsvgmatrix();

第2行代码通过createelementns创建与获取到svg对象。

第3行代码通过createsvgmatrix()方法创建并返回一个新的2x3的矩阵svgmatrix矩阵对象赋值到xform。

我们在中打开开发者工具,到控制台可以输出矩阵看看初始值。

获取Canvas当前坐标系矩阵 - 方帅 -

a b c d e f 这6个值就对应了我们在介绍transform方法的那6个参数。这个2x3的矩阵为了方便矩阵运算我们把它扩展为一个3x3的矩阵。

获取Canvas当前坐标系矩阵 - 方帅 -

svgmatrix介绍

这里再简单解释下svgmatrix:

svgmatrix的方法和属性如下图(具体可参阅:https://developer.mozilla.org/en-us/docs/web/api/svgmatrix)

获取Canvas当前坐标系矩阵 - 方帅 -

 

2 save方法
             savedtransforms.push(xform.translate(0, 0));
             return save.call(ctx);

先将xform存储在一个数组savedtransforms中,然后调用原api方法。

3 restore方法
            xform = savedtransforms.pop();
            return restore.call(ctx);

从savedtransforms数组中去除最后一个对象,并将其赋值到变量xform,然后调用原api方法。

4 scale方法
            xform = xform.scalenonuniform(sx, sy);
            return scale.call(ctx, sx, sy);

维护xform,将其缩放,然后调用原api方法。

5 rotate方法
        var radians = deg * math.pi / 180;
            xform = xform.rotate(deg);
            return rotate.call(ctx, radians);

将角度转为弧度,维护xform将其进行旋转变换,然后调用原api方法。

6 translate方法
            xform = xform.translate(dx, dy);
            return translate.call(ctx, dx, dy);

维护xform将其进行平移变换,然后调用原api方法。

7 transform方法
            var m2 = svg.createsvgmatrix();
            m2.a = a; m2.b = b; m2.c = c; m2.d = d; m2.e = e; m2.f = f;
            xform = xform.multiply(m2);
            return transform.call(ctx, a, b, c, d, e, f);
首先声明一个新的矩阵m2,m2赋值为要进行变换的6个参数值,然后xform和m2执行矩阵乘法运算,运算结果赋值到xform将其维护。然后调用原api方法。
8 settransform方法
            xform.a = a;
            xform.b = b;
            xform.c = c;
            xform.d = d;
            xform.e = e;
            xform.f = f;
            return settransform.call(ctx, a, b, c, d, e, f);

维护xform的值,然后调用原api方法。

9 clearrect方法
            ctx.save();
            ctx.settransform(1, 0, 0, 1, 0, 0);
            clearrect.call(ctx, x, y, w, h);
            ctx.restore();

首先保存context的当前状态,将画布重置到原始状态(可以理解为坐标系重置到默认坐标系),然后调用原api方法清除画布指定范围内容。清除后调用restore恢复canvas之前保存的状态。

10 getteansform方法
ctx.gettransform = function () { return xform; };

接下来介绍的三个方法都是原api没有的。getteansform直接返回xform,可以看到代表画布矩阵的6个值abcdef。

11transformedpoint方法
54         var pt = svg.createsvgpoint();
55         //通过原坐标系点x,y求对应当前坐标系的坐标值
56         ctx.transformedpoint = function (x, y) {
57             pt.x = x; pt.y = y;
58             return pt.matrixtransform(xform.inverse());
59         }

通过原坐标系点x,y求对应当前坐标系的坐标值。

createsvgpoint创建的点为(0,0),xform.inverse()是求xform的逆矩阵。matrixtransform则是通过一种矩阵算法来进行运算得到相应的变形的效果的。矩阵的一些基本算法就不多总结了,以前上课就学过了,网上也有不少讲解。

12transformedpoint2方法
60         var pt2 = svg.createsvgpoint();
61         //当前坐标系中的的xy还原到原坐标系坐标值
62         ctx.transformedpoint2 = function (x, y) {
63             pt2.x = x; pt2.y = y;
64             return pt2.matrixtransform(xform);
65         }

当前坐标系中的的x,y还原到原坐标系坐标值。