軟件項目技術點(2)——Canvas之獲取Canvas當前座標系矩陣 AxeSlide軟件項目梳理

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還原到原座標系座標值。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章