zoukankan      html  css  js  c++  java
  • 软件项目技术点(2)——Canvas之获取Canvas当前坐标系矩阵

    AxeSlide软件项目梳理   canvas绘图系列知识点整理

    前言

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

    具体代码

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

     1 window.TrackTransform = function () {
     2     var svg = document.createElementNS("http://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("http://www.w3.org/2000/svg", 'svg');
     3     var xform = svg.createSVGMatrix();

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

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

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

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

    svgMatrix介绍

    这里再简单解释下svgMatrix:

    svgMatrix的方法和属性如下图(具体可参阅:https://developer.mozilla.org/en-US/docs/Web/API/SVGMatrix)

    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。

    11 transformedPoint方法

    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则是通过一种矩阵算法来进行运算得到相应的变形的效果的。矩阵的一些基本算法就不多总结了,以前上课就学过了,网上也有不少讲解。

    12 transformedPoint2方法

    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还原到原坐标系坐标值。

  • 相关阅读:
    php程序去除文件 bom头
    类继承接口后,实现接口的方法
    virtual和abstract的使用场景分别是什么?待更新。
    get请求和post请求的总结
    ES6新语法,持续更新
    display:flex中的不懂的问题,待处理
    css相邻兄弟选择器(+),伪类(:hover),伪元素(::after)
    HTML中的input的type类型
    命令行打开程序的集合
    sqlserver 常用的语句
  • 原文地址:https://www.cnblogs.com/fangsmile/p/5651429.html
Copyright © 2011-2022 走看看