matrix transformation

1,071 views
Skip to first unread message

Sebastian Gurin

unread,
Mar 3, 2010, 1:37:47 PM3/3/10
to raph...@googlegroups.com
Hello all. I would like to ask about the reasons why transformation matrix is not available in raphael's api. I'm talking about http://www.w3.org/TR/SVG/coords.html#TransformAttribute (in svg) and http://msdn.microsoft.com/en-us/library/ms533014(VS.85).aspx (in VML). It seems that both svg and vml support this (powerfull) operation so I would like to know why raphael elements doens't support it.

I have created a raphael plugin that supports a matrix() method and some example operations (based on matrix()), like shear and reflect (currently not supported by raphael) (see below). Also, I published 2 examples in the web:

http://www.cancerbero.vacau.com/works/yui/htmls/raphaelprobes/reflect.html
http://www.cancerbero.vacau.com/works/yui/htmls/raphaelprobes/shear.html

they seems to work OK both in svg and vml.

A coment about matrix transformation. It seems that both in svg and vml, a transformed element system coordinate is changed (by the matrix passed). In my plugin, I have overwriting Raphael.el.translate to respect the new coordinate system (see Raphael.el.translate_matrix).

Well, as I said my big question is why this general and powerful operation, both supported by svg and vml is not available in raphael.....

My plugin's code is the next:


/* matrix transformation plugin
*
* using matrix filter in vml (http://msdn.microsoft.com/en-us/library/ms533014(VS.85).aspx)
*
* and transform (http://www.w3.org/TR/SVG/coords.html#TransformAttribute) in svg
* check http://www.w3.org/TR/SVG/coords.html#TransformMatrixDefined
*
* note: when a matrix transformation is applied, the element coordinate system change
* according to that matrix. So we override translate method to behave correctly
*
* @author: sgurin
*/
(function () {
Raphael.Matrix=function(m11, m12, m21, m22, dx, dy) {
this.m = [
[m11 || 1, m12 || 0, 0],
[m21 || 0, m22 || 1, 0],
[dx || 0, dy || 0, 1]
];
};
if (Raphael.vml) {
Raphael.Matrix.prototype.toString = function () {
return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.m[0][0] +
", M12=" + this.m[0][1] + ", M21=" + this.m[1][0] + ", M22=" + this.m[1][1] +
", Dx=" + this.m[2][0] + ", Dy=" + this.m[2][1] + ", sizingmethod='auto expand', filtertype='bilinear')";
};
Raphael.el.matrix = function (xx, xy, yx, yy, dx, dy) {
tMatrix = new Raphael.Matrix(xx, xy, yx, yy, dx, dy);
this.Group.style.filter = tMatrix.toString();
return this;
};
} else {
Raphael.Matrix.prototype.toString = function () {
return "matrix(" + this.m[0][0] +
", " + this.m[1][0] + ", " + this.m[0][1] + ", " + this.m[1][1] +
", " + this.m[2][0] + ", " + this.m[2][1] + ")";
};
Raphael.el.matrix = function (xx, xy, yx, yy, dx, dy) {
if(xx==null) {
this.transformations[Raphael.el.matrix._TransfIdx]="";
}
else {
this.transformations[Raphael.el.matrix._TransfIdx] = new Raphael.Matrix(xx, xy, yx, yy, dx, dy);
}
this.node.setAttribute("transform", this.transformations.join(" "));

this.M = xx==null?null:[xx, xy, yx, yy, dx, dy];

return this;

};
Raphael.el.matrix._TransfIdx=8;
};

//translate method overwriting to respect new matrix defined coordinate system
Raphael.el.translate_matrix=function(dx,dy) {
if(this.M==null)
return this.translateSuper(dx, dy);
var fixedDx = this.M[0]*dx+this.M[1]*dy,
fixedDy = this.M[2]*dx+this.M[3]*dy;
return this.translateSuper(fixedDx, fixedDy);
}
Raphael.el.translateSuper=Raphael.el.translate;
Raphael.el.translate=Raphael.el.translate_matrix;

//matrix derived operations:
Raphael.el.shear=function(s, horizontal) {
var x =this.getBBox().x, y=this.getBBox().y;
if(horizontal) {
this.matrix(
1.0, s,
0.0, 1.0,
0.0, 0.0
);
this.translate(y*s*(-1),0);
}
else {
this.matrix(
1.0, 0.0,
s, 1.0,
0.0, 0.0
);
this.translate(0, x*s*(-1));
}
return this;
};

/**
* reflects the element about a line that goes through the center of the image
* and has an angle slope
*
* for reflecting, first we translate the element so its center equals the origin,
* then apply reflection (so its position doesn't change) and then
*
* @param angle must be in angle (pi) not radians, valid values are PI/2, PI/3, etc
*
* http://planetmath.org/encyclopedia/DerivationOf2DReflectionMatrix.html
* */
Raphael.el.reflect=function(angle) {
//la transladamos para que quede centrada en el origen, aplicamos transformación y la retrasladamos a su lugar de origen.
var b_ = this.getBBox(), b={x: b_.x, y: b_.y, width: b_.width, height: b_.height};
this.translate((b.x+b.width/2)*(-1), (b.y+b.height/2)*(-1));
var m = Math.tan(angle), A = 1/(m*m+1);
this.matrix(
(1-m*m)*A, 2*m*A,
2*m*A, (m*m-1)*A,
0,0);
this.translate(b.x+b.width/2, b.y+b.height/2);
return this;
};
})();

--
Sebastian Gurin <sgu...@softpoint.org>

charles thomas

unread,
Mar 3, 2010, 2:32:40 PM3/3/10
to raph...@googlegroups.com
Sebastian

This is a guess so here goes.

Simple transforms like Translate and Scale are included in Raphael because the users can easily understand these but as we move "up" skew is not supported and neither is the "king" of SVG transform methods "matrix"

The transform "matrix" also stores the order of the simpler transforms (Depending on the order of simple transforms, the end result could be different) but basically all transforms can be contained within it.

I think a new transform method (Skew) should be introduced but do you know anyone who could work out the 6 parameters for a new "matrix" method?

That's why the only place for the SVG matrix method is in a computer generated SVG file.

Charles

--- On Wed, 3/3/10, Sebastian Gurin <sgu...@softpoint.org> wrote:
--
You received this message because you are subscribed to the Google Groups "Raphaël" group.
To post to this group, send an email to raph...@googlegroups.com.
To unsubscribe from this group, send email to raphaeljs+unsub...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/raphaeljs?hl=en-GB.



Make your browsing faster, safer, and easier with the new Internet Explorer® 8. Optimized for Yahoo! Get it Now for Free!

charles thomas

unread,
Mar 3, 2010, 2:41:28 PM3/3/10
to raph...@googlegroups.com
Sebastiian

great work on the plugins.

I'm fearing we are missing a lot of useful plugins like this as they are buried in GitHub so it was nice of you to send them as an email also.

Regards Charles

--- On Wed, 3/3/10, charles thomas <charl...@yahoo.com> wrote:
To unsubscribe from this group, send email to raphaeljs+...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/raphaeljs?hl=en-GB.


Looking for the perfect gift? Give the gift of Flickr!

Sebastian Gurin

unread,
Mar 3, 2010, 2:54:24 PM3/3/10
to raph...@googlegroups.com
Hi Charles. It would be nice to have a raphael "comunity plugins" collection where users can search for plugins that satisfy its needs, other can contribute, all of this without make dirty in raphael core library...

About matrix operation, lot of "high level" operations can be implementing using (only) matrix, for example, rotation, scaling, shearing, reflection, orthogonal projection. Of course, as you said, will be uncommon that users use matrix directly, but, I am amazed that this powerfull tool don't be available in raphael and as a consequence, mentioned high level operations, also be unavailable.

regards.

> To unsubscribe from this group, send email to raphaeljs+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/raphaeljs?hl=en-GB.
>
>
>
> Make your browsing faster, safer, and easier with the new Internet Explorer® 8. Optimized for Yahoo! Get it Now for Free!
>
>
>
> --
>
> You received this message because you are subscribed to the Google Groups "Raphaël" group.
>
> To post to this group, send an email to raph...@googlegroups.com.
>
> To unsubscribe from this group, send email to raphaeljs+...@googlegroups.com.
>
>
> For more options, visit this group at http://groups.google.com/group/raphaeljs?hl=en-GB.
>
>
>
>
>
>

> __________________________________________________________________


> Looking for the perfect gift? Give the gift of Flickr!
>

> http://www.flickr.com/gift/


>
> --
> You received this message because you are subscribed to the Google Groups "Raphaël" group.
> To post to this group, send an email to raph...@googlegroups.com.
> To unsubscribe from this group, send email to raphaeljs+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/raphaeljs?hl=en-GB.
>
>


--
Sebastian Gurin <sgu...@softpoint.org>

charles thomas

unread,
Mar 3, 2010, 3:04:07 PM3/3/10
to raph...@googlegroups.com
Sebastian,

I'm collecting a few and (with authors permission) will list them when I finish something i'm working on in about 2 to 3 weeks @

http://www.irunmywebsite.com/raphael/raphaelsource.html
> To unsubscribe from this group, send email to raphaeljs+unsub...@googlegroups.com.

> For more options, visit this group at http://groups.google.com/group/raphaeljs?hl=en-GB.
>
>
>
>       Make your browsing faster, safer, and easier with the new Internet Explorer® 8. Optimized for Yahoo! Get it Now for Free!
>
>
>
> --
>
> You received this message because you are subscribed to the Google Groups "Raphaël" group.
>
> To post to this group, send an email to raph...@googlegroups.com.
>
> To unsubscribe from this group, send email to raphaeljs+unsub...@googlegroups.com.

>
>
> For more options, visit this group at http://groups.google.com/group/raphaeljs?hl=en-GB.
>
>
>
>
>
>
>       __________________________________________________________________
> Looking for the perfect gift? Give the gift of Flickr!
>
> http://www.flickr.com/gift/
>
> --
> You received this message because you are subscribed to the Google Groups "Raphaël" group.
> To post to this group, send an email to raph...@googlegroups.com.
> To unsubscribe from this group, send email to raphaeljs+unsub...@googlegroups.com.

> For more options, visit this group at http://groups.google.com/group/raphaeljs?hl=en-GB.
>
>


--
Sebastian Gurin <sgu...@softpoint.org>

--
You received this message because you are subscribed to the Google Groups "Raphaël" group.
To post to this group, send an email to raph...@googlegroups.com.
To unsubscribe from this group, send email to raphaeljs+unsub...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/raphaeljs?hl=en-GB.

Priit

unread,
Mar 3, 2010, 5:16:46 PM3/3/10
to Raphaël
Raphael is a cross browser library and matrix is not supported by VML,
additionally matrix is only in very simple cases breakable into basic
transformations as rotate, translate etc, so it can not be emulated in
VML either.

Sebastian Gurin

unread,
Mar 3, 2010, 6:33:40 PM3/3/10
to raph...@googlegroups.com

Hi Priit, I appreciate your response.

About "matrix is not supported by VML", well I think the examples using my plugin (very poor tested) shows the opposite. As I said It seems that VML matrix filter (http://msdn.microsoft.com/en-us/library/ms533014(VS.85).aspx) has the same behaviour an a very similar interface of svg's matrix transformation (http://www.w3.org/TR/SVG/coords.html#TransformAttribute ). In fact it is one of the only vector operation that exists in both technologies... That is the main reason for my question ¿why is it not available?

About "matrix is only in very simple cases breakable into basic transformations as rotate, translate" ... mmm I don't think you can archive shear/skew or reflect using rotation, translation, scale.

regards

>
> --
> You received this message because you are subscribed to the Google Groups "Raphaël" group.
> To post to this group, send an email to raph...@googlegroups.com.

> To unsubscribe from this group, send email to raphaeljs+...@googlegroups.com.

Dmitry Baranovskiy

unread,
Mar 3, 2010, 7:25:05 PM3/3/10
to raph...@googlegroups.com
Hello,
Lets make it clear: matrix transformations are not a part of Raphaël
and not going to be in near future.
You can have reflect effect right now without it. http://raphaeljs.com/reflection.html
I wonder how you missed it.
I don’t think skew effect is valuable enough, so I should go across
all the hassle of having matrix in the API. If you will manage to put
matrix in the code in such a way that it will not broke things when
you do matrix().rotate().translate().rotate().matrix() then go for it,
I will pull it back into codebase.

As for my opinion it adds more complexity than value.

best,
Dmitry

Sebastian Gurin

unread,
Aug 16, 2010, 1:01:57 PM8/16/10
to raph...@googlegroups.com
I just put my matrix transformation plugin (with some fixes) at github http://github.com/cancerberoSgx/sgxRaphaelJsPlugins.

> --
> You received this message because you are subscribed to the Google Groups "Raphaël" group.
> To post to this group, send an email to raph...@googlegroups.com.
> To unsubscribe from this group, send email to raphaeljs+...@googlegroups.com.

Sebastian Gurin

unread,
Apr 3, 2011, 12:20:52 PM4/3/11
to raph...@googlegroups.com
On Thu, 4 Mar 2010 11:25:05 +1100
Dmitry Baranovskiy <dmitry.ba...@gmail.com> wrote:

> I don’t think skew effect is valuable enough, so I should go across
> all the hassle of having matrix in the API. If you will manage to put
> matrix in the code in such a way that it will not broke things when
> you do matrix().rotate().translate().rotate().matrix() then go for it,
> I will pull it back into codebase.
>
> As for my opinion it adds more complexity than value.

I think this is true no more for raphael version 2. Good work!


--
Sebastian Gurin <sgu...@softpoint.org>

Reply all
Reply to author
Forward
0 new messages