html5 matrix,javascript - HTML5 Canvas get transform matrix? - Stack Overflow

EDIT(1/10/2020): MDN now indicates that getTransform() is supported in most major browsers; the code below may still have value as a part of implementing a polyfill for Internet Explorer, Edge, and Android Firefox.

EDIT(6/27/2016): The WHATWG spec now has a function getTransform() instead of currentTransform and it appears semantically clear that getTransform() creates a copy of the transformation matrix. Looks like it is still missing from major browsers.

EDIT, again:

Here's a rough implementation:

//in theory, SVGMatrix will be used by the Canvas API in the future;

//in practice, we can borrow an SVG matrix today!

var createMatrix = function() {

var svgNamespace = "http://www.w3.org/2000/svg";

return document.createElementNS(svgNamespace, "g").getCTM();

}

//`enhanceContext` takes a 2d canvas context and wraps its matrix-changing

//functions so that `context._matrix` should always correspond to its

//current transformation matrix.

//Call `enhanceContext` on a freshly-fetched 2d canvas context for best

//results.

var enhanceContext = function(context) {

var m = createMatrix();

context._matrix = m;

//the stack of saved matrices

context._savedMatrices = [m];

var super_ = context.__proto__;

context.__proto__ = ({

//helper for manually forcing the canvas transformation matrix to

//match the stored matrix.

_setMatrix: function() {

var m = this._matrix;

super_.setTransform.call(this, m.a, m.b, m.c, m.d, m.e, m.f);

},

save: function() {

this._savedMatrices.push(this._matrix);

super_.save.call(this);

},

//if the stack of matrices we're managing doesn't have a saved matrix,

//we won't even call the context's original `restore` method.

restore: function() {

if(this._savedMatrices.length == 0)

return;

super_.restore.call(this);

this._matrix = this._savedMatrices.pop();

this._setMatrix();

},

scale: function(x, y) {

this._matrix = this._matrix.scaleNonUniform(x, y);

super_.scale.call(this, x, y);

},

rotate: function(theta) {

//canvas `rotate` uses radians, SVGMatrix uses degrees.

this._matrix = this._matrix.rotate(theta * 180 / Math.PI);

super_.rotate.call(this, theta);

},

translate: function(x, y) {

this._matrix = this._matrix.translate(x, y);

super_.translate.call(this, x, y);

},

transform: function(a, b, c, d, e, f) {

var rhs = createMatrix();

//2x2 scale-skew matrix

rhs.a = a; rhs.b = b;

rhs.c = c; rhs.d = d;

//translation vector

rhs.e = e; rhs.f = f;

this._matrix = this._matrix.multiply(rhs);

super_.transform.call(this, a, b, c, d, e, f);

},

//warning: `resetTransform` is not implemented in at least some browsers

//and this is _not_ a shim.

resetTransform: function() {

this._matrix = createMatrix();

super_.resetTransform.call(this);

},

__proto__: super_

});

return context;

};

EDIT:

The attribute currentTransform has been added to the spec; it is reported to be supported in Firefox and Opera. I checked on Firefox and found it vendor-prefixed as mozCurrentTransform. Presumably it can be used to both get and set the transform matrix.

OLDER STUFF, STILL MOSTLY TRUE:

If you want to get the current transformation matrix, you'll have to keep track of it yourself. One way of doing this would be to use Javascript's prototypical inheritance to add a getMatrix() method and augment the methods which modify the matrix:

var context = canvas.getContext("2d");

var super = context.__proto__;

context.__proto__ = ({

__proto__: super, //"inherit" default behavior

getMatrix: function() { return this.matrix; },

scale: function(x, y) {

//assuming the matrix manipulations are already defined...

var newMatrix = scaleMatrix(x, y, this.getMatrix());

this.matrix = newMatrix;

return super.scale.call(this, x, y);

},

/* similar things for rotate, translate, transform, setTransform */

/* ... */

});

context.matrix = makeDefaultMatrix();

To really get it right, you'd need to track multiple matrices when the save() and restore() methods of the context are used.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值