Commit 9962a268 by Dmitry Baranovskiy

Added split method to matrix, fixed caching a bit, first iteration of fix for…

Added split method to matrix, fixed caching a bit, first iteration of fix for correct transformation in IE for gradient and images.
parent f02c9d89
...@@ -659,6 +659,11 @@ ...@@ -659,6 +659,11 @@
R._path2string = function () { R._path2string = function () {
return this.join(",").replace(p2s, "$1"); return this.join(",").replace(p2s, "$1");
}; };
function repush(array, item) {
for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) {
return array.push(array.splice(i, 1)[0]);
}
}
function cacher(f, scope, postprocessor) { function cacher(f, scope, postprocessor) {
function newf() { function newf() {
var arg = Array.prototype.slice.call(arguments, 0), var arg = Array.prototype.slice.call(arguments, 0),
...@@ -666,6 +671,7 @@ ...@@ -666,6 +671,7 @@
cache = newf.cache = newf.cache || {}, cache = newf.cache = newf.cache || {},
count = newf.count = newf.count || []; count = newf.count = newf.count || [];
if (cache[has](args)) { if (cache[has](args)) {
repush(count, args);
return postprocessor ? postprocessor(cache[args]) : cache[args]; return postprocessor ? postprocessor(cache[args]) : cache[args];
} }
count.length >= 1e3 && delete cache[count.shift()]; count.length >= 1e3 && delete cache[count.shift()];
...@@ -1650,6 +1656,7 @@ ...@@ -1650,6 +1656,7 @@
} }
}, },
equaliseTransform = function (t1, t2) { equaliseTransform = function (t1, t2) {
t2 = Str(t2).replace(/\.{3}|\u2026/g, t1);
t1 = R.parseTransformString(t1) || []; t1 = R.parseTransformString(t1) || [];
t2 = R.parseTransformString(t2) || []; t2 = R.parseTransformString(t2) || [];
var maxlength = mmax(t1.length, t2.length), var maxlength = mmax(t1.length, t2.length),
...@@ -1660,7 +1667,7 @@ ...@@ -1660,7 +1667,7 @@
for (; i < maxlength; i++) { for (; i < maxlength; i++) {
tt1 = t1[i] || getEmpty(t2[i]); tt1 = t1[i] || getEmpty(t2[i]);
tt2 = t2[i] || getEmpty(tt1); tt2 = t2[i] || getEmpty(tt1);
if ( (tt1[0] != tt2[0]) || if ((tt1[0] != tt2[0]) ||
(tt1[0] == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) || (tt1[0] == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||
(tt1[0] == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4])) (tt1[0] == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))
) { ) {
...@@ -1738,7 +1745,7 @@ ...@@ -1738,7 +1745,7 @@
this.f = 0; this.f = 0;
} }
} }
var matrixproto = Matrix.prototype; (function (matrixproto) {
matrixproto.add = function (a, b, c, d, e, f) { matrixproto.add = function (a, b, c, d, e, f) {
var out = [[], [], []], var out = [[], [], []],
m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]], m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]],
...@@ -1806,11 +1813,54 @@ ...@@ -1806,11 +1813,54 @@
matrixproto.toFilter = function () { matrixproto.toFilter = function () {
return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.get(0) + return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.get(0) +
", M12=" + this.get(2) + ", M21=" + this.get(1) + ", M22=" + this.get(3) + ", M12=" + this.get(2) + ", M21=" + this.get(1) + ", M22=" + this.get(3) +
", Dx=" + this.get(4) + ", Dy=" + this.get(5) + ", sizingmedthod='auto expand')"; ", Dx=" + this.get(4) + ", Dy=" + this.get(5) + ", sizingmethod='auto expand')";
}; };
matrixproto.offset = function () { matrixproto.offset = function () {
return [this.e.toFixed(4), this.f.toFixed(4)]; return [this.e.toFixed(4), this.f.toFixed(4)];
}; };
function norm(a) {
return a[0] * a[0] + a[1] * a[1];
}
function normalize(a) {
var mag = math.sqrt(norm(a));
a[0] /= mag;
a[1] /= mag;
}
matrixproto.split = function () {
var out = {};
// translation
out.dx = this.e;
out.dy = this.f;
this.e = this.f = 0;
// scale and shear
var row = [[this.a, this.c], [this.b, this.d]];
out.scalex = math.sqrt(norm(row[0]));
normalize(row[0]);
out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];
row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];
out.scaley = math.sqrt(norm(row[1]));
normalize(row[1]);
out.shear /= out.scaley;
// rotation
out.rotate = R.deg(math.asin(-row[0][1]));
out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate);
return out;
};
matrixproto.toTransformString = function () {
var s = this.split();
if (s.isSimple) {
return "t" + [s.dx, s.dy] + "s" + [s.scalex, s.scaley, 0, 0] + "r" + [s.rotate, 0, 0];
} else {
return "m" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)];
}
};
})(Matrix.prototype);
// SVG // SVG
if (R.svg) { if (R.svg) {
...@@ -2609,7 +2659,6 @@ ...@@ -2609,7 +2659,6 @@
extractTransform(this, tstr); extractTransform(this, tstr);
this.clip && $(this.clip, {transform: this.matrix.invert()}); this.clip && $(this.clip, {transform: this.matrix.invert()});
// this.gradient && $(this.gradient, {gradientTransform: this.matrix.invert()});
this.pattern && updatePosition(this); this.pattern && updatePosition(this);
this.node && $(this.node, {transform: this.matrix}); this.node && $(this.node, {transform: this.matrix});
...@@ -3154,18 +3203,19 @@ ...@@ -3154,18 +3203,19 @@
dy: m.y(dx, dy) dy: m.y(dx, dy)
}; };
}, },
setCoords = function (p) { setCoords = function (p, sx, sy, dx, dy, deg) {
var _ = p._, var _ = p._,
sx = _.sx, m = p.matrix,
sy = _.sy, // sp = m.split(),
deg = _.deg, // sx = sp.scalex,
dx = _.dx, // sy = sp.scaley,
dy = _.dy, // deg = sp.rotate,
// dx = sp.dx,
// dy = sp.dy,
fillpos = _.fillpos, fillpos = _.fillpos,
o = p.node, o = p.node,
s = o.style, s = o.style,
y = 1, y = 1,
m = p.matrix,
flip = "", flip = "",
dxdy, dxdy,
kx = zoom / sx, kx = zoom / sx,
...@@ -3330,7 +3380,7 @@ ...@@ -3330,7 +3380,7 @@
fill.on = false; fill.on = false;
} }
if (fill.on && params.fill) { if (fill.on && params.fill) {
var isURL = params.fill.match(ISURL); var isURL = Str(params.fill).match(ISURL);
if (isURL) { if (isURL) {
fill.parentNode == node && node.removeChild(fill); fill.parentNode == node && node.removeChild(fill);
fill.rotate = true; fill.rotate = true;
...@@ -3534,50 +3584,34 @@ ...@@ -3534,50 +3584,34 @@
extractTransform(this, tstr); extractTransform(this, tstr);
var matrix = this.matrix.clone(), var matrix = this.matrix.clone(),
vbs = this.paper._viewBoxShift, vbs = this.paper._viewBoxShift,
skew = this.skew; skew = this.skew,
o = this.node;
matrix.translate(-.5, -.5); matrix.translate(-.5, -.5);
if (vbs) { if (vbs) {
matrix.scale(vbs.scale, vbs.scale, -1, -1); matrix.scale(vbs.scale, vbs.scale, -1, -1);
matrix.add(1, 0, 0, 1, vbs.dx, vbs.dy); matrix.translate(vbs.dx, vbs.dy);
} }
if (this.type == "image") { if (Str(this.attrs.fill).indexOf("-") + 1 || this.type == "image") {
if (Str(tstr).indexOf("m") + 1) { skew.matrix = "1 0 0 1";
this.node.style.filter = matrix.toFilter(); skew.offset = "0 0";
var split = matrix.split();
if (!split.isSimple) {
o.style.filter = matrix.toFilter();
var bb = this.getBBox(), var bb = this.getBBox(),
bbt = this.getBBox(1), bbt = this.getBBox(1),
im = matrix.invert(), dx = bb.x - bbt.x,
dx = im.x(bb.x, bb.y) - im.x(bbt.x, bbt.y), dy = bb.y - bbt.y;
dy = im.y(bb.x, bb.y) - im.y(bbt.x, bbt.y); o.coordorigin = (dx * -zoom) + S + (dy * -zoom);
// skew.offset = dx + S + dy; setCoords(this, 1, 1, dx, dy, 0);
// this.node.getElementsByTagName(fillString)[0].position = skew.offset;
} else { } else {
this.node.style.filter = E; o.style.filter = E;
setCoords(this); alert("clean");
setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate);
} }
} else { } else {
// o = this.node, o.style.filter = E;
// _ = this._,
// fillpos = _.fillpos,
// deg,
// matrix = this.matrix;
// fill = o.getElementsByTagName(fillString)[0],
// angle = fill.angle;
this.node.style.filter = E;
skew.matrix = Str(matrix); skew.matrix = Str(matrix);
skew.offset = matrix.offset(); skew.offset = matrix.offset();
// if (0&&angle) {
// angle = R.rad(270 - angle);
// var dx = 100 * math.cos(angle),
// dy = 100 * math.sin(angle),
// zx = matrix.x(0, 0),
// zy = matrix.y(0, 0),
// mx = matrix.x(dx, dy),
// my = matrix.y(dx, dy);
// angle = R.angle(zx, zy, mx, my);
// fill.angle = (270 - angle) % 360;
// }
} }
return this; return this;
}; };
...@@ -3692,6 +3726,7 @@ ...@@ -3692,6 +3726,7 @@
res[i] = this.attrs[i]; res[i] = this.attrs[i];
} }
res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient; res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
res.transform = this._.transform;
return res; return res;
} }
if (value == null && R.is(name, "string")) { if (value == null && R.is(name, "string")) {
...@@ -3878,7 +3913,7 @@ ...@@ -3878,7 +3913,7 @@
res._.fillpos = [x, y]; res._.fillpos = [x, y];
res._.fillsize = [w, h]; res._.fillsize = [w, h];
node.appendChild(fill); node.appendChild(fill);
setCoords(res); setCoords(res, 1, 1, 0, 0, 0);
return res; return res;
}; };
theText = function (vml, x, y, text) { theText = function (vml, x, y, text) {
...@@ -3892,7 +3927,7 @@ ...@@ -3892,7 +3927,7 @@
path.textpathok = true; path.textpathok = true;
o.string = Str(text); o.string = Str(text);
o.on = true; o.on = true;
el.style.cssText = "position:absolute;left:0;top:0;width:1;height:1"; el.style.cssText = "position:absolute;left:0;top:0;width:1px;height:1px";
el.coordsize = zoom + S + zoom; el.coordsize = zoom + S + zoom;
el.coordorigin = "0 0"; el.coordorigin = "0 0";
var p = new Element(el, vml), var p = new Element(el, vml),
...@@ -5074,15 +5109,13 @@ ...@@ -5074,15 +5109,13 @@
R.is(f, "function") && f.call(el); R.is(f, "function") && f.call(el);
}); });
})(e.callback, that, e.anim); })(e.callback, that, e.anim);
if (--e.repeat) {
that.attr(e.origin);
e.start = Now;
} else {
that.attr(to); that.attr(to);
animationElements.splice(l--, 1); animationElements.splice(l--, 1);
if (e.repeat > 1 && !e.next) {
runAnimation(e.anim, e.el, e.anim.percents[0], null, e.totalOrigin, e.repeat - 1);
} }
if (e.next && !e.stop) { if (e.next && !e.stop) {
runAnimation(e.anim, e.el, e.next, null, e.totalOrigin); runAnimation(e.anim, e.el, e.next, null, e.totalOrigin, e.repeat);
} }
} }
} }
...@@ -5090,7 +5123,7 @@ ...@@ -5090,7 +5123,7 @@
animationElements.length && requestAnimFrame(animation); animationElements.length && requestAnimFrame(animation);
}, },
upto255 = function (color) { upto255 = function (color) {
return mmax(mmin(color, 255), 0); return color > 255 ? 255 : color < 0 ? 0 : color;
}; };
/*\ /*\
* Element.animateWith * Element.animateWith
...@@ -5228,7 +5261,7 @@ ...@@ -5228,7 +5261,7 @@
a.times = math.floor(mmax(times, 0)) || 1; a.times = math.floor(mmax(times, 0)) || 1;
return a; return a;
}; };
function runAnimation(anim, element, percent, status, totalOrigin) { function runAnimation(anim, element, percent, status, totalOrigin, times) {
percent = toFloat(percent); percent = toFloat(percent);
var params, var params,
isInAnim, isInAnim,
...@@ -5319,25 +5352,25 @@ ...@@ -5319,25 +5352,25 @@
} }
} }
} else { } else {
var m = (element.matrix || new Matrix).m, var m = (element.matrix || new Matrix),
to2 = {_:{transform: _.transform}, getBBox: function () { return element.getBBox(); }}; to2 = {_:{transform: _.transform}, getBBox: function () { return element.getBBox(); }};
from[attr] = [ from[attr] = [
m[0][0], m.a,
m[1][0], m.b,
m[0][1], m.c,
m[1][1], m.d,
m[0][2], m.e,
m[1][2] m.f
]; ];
extractTransform(to2, to[attr]); extractTransform(to2, to[attr]);
to[attr] = to2._.transform; to[attr] = to2._.transform;
diff[attr] = [ diff[attr] = [
(to2.matrix.m[0][0] - m[0][0]) / ms, (to2.matrix.a - m.a) / ms,
(to2.matrix.m[1][0] - m[1][0]) / ms, (to2.matrix.b - m.b) / ms,
(to2.matrix.m[0][1] - m[0][1]) / ms, (to2.matrix.c - m.c) / ms,
(to2.matrix.m[1][1] - m[1][1]) / ms, (to2.matrix.d - m.d) / ms,
(to2.matrix.m[0][2] - m[0][2]) / ms, (to2.matrix.e - m.e) / ms,
(to2.matrix.m[1][2] - m[1][2]) / ms (to2.matrix.e - m.f) / ms
]; ];
// from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy]; // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy];
// var to2 = {_:{}, getBBox: function () { return element.getBBox(); }}; // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }};
...@@ -5407,7 +5440,7 @@ ...@@ -5407,7 +5440,7 @@
callback: params.callback, callback: params.callback,
prev: prev, prev: prev,
next: next, next: next,
repeat: anim.times, repeat: times || anim.times,
origin: element.attr(), origin: element.attr(),
totalOrigin: totalOrigin totalOrigin: totalOrigin
}; };
...@@ -5909,34 +5942,103 @@ ...@@ -5909,34 +5942,103 @@
oldRaphael.was ? (g.win.Raphael = R) : (Raphael = R); oldRaphael.was ? (g.win.Raphael = R) : (Raphael = R);
/* /*
* Eve 0.2.1 - JavaScript Events Library * Eve 0.2.3 - JavaScript Events Library
* *
* Copyright (c) 2010 Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) * Copyright (c) 2010 Dmitry Baranovskiy (http://dmitry.baranovskiy.com/)
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
*/ */
var eve = R.eve = (function () { var eve = R.eve = (function () {
var version = "0.2.1", var version = "0.2.3",
has = "hasOwnProperty", has = "hasOwnProperty",
separator = /[\.\/]/, separator = /[\.\/]/,
wildcard = "*", wildcard = "*",
fun = function () {},
numsort = function (a, b) {
return a - b;
},
current_event,
events = {n: {}}, events = {n: {}},
/*\
* eve
[ method ]
**
* Fires event with given `name`, given scope and other parameters.
**
> Arguments
**
- name (string) name of the event, dot (`.`) or slash (`/`) separated
- scope (object) context for the event handlers
- varargs (...) the rest of arguments will be sent to event handlers
**
= (array) array of errors, if any. Each element of the array is in format:
o {
o error (string) error message
o func (function) handler that caused error
o }
\*/
eve = function (name, scope) { eve = function (name, scope) {
var e = events, var e = events,
args = Array.prototype.slice.call(arguments, 2), args = Array.prototype.slice.call(arguments, 2),
listeners = eve.listeners(name), listeners = eve.listeners(name),
z = 0,
f = false,
l,
indexed = [],
queue = {},
errors = []; errors = [];
for (var i = 0, ii = listeners.length; i < ii; i++) { current_event = name;
try { for (var i = 0, ii = listeners.length; i < ii; i++) if ("zIndex" in listeners[i]) {
listeners[i].apply(scope, args); indexed.push(listeners[i].zIndex);
} catch (ex) { if (listeners[i].zIndex < 0) {
errors.push({error: ex && ex.message || ex, func: listeners[i]}); queue[listeners[i].zIndex] = listeners[i];
}
}
indexed.sort(numsort);
while (indexed[z] < 0) {
l = queue[indexed[z++]];
if (l.apply(scope, args) === f) {
return f;
}
}
for (i = 0; i < ii; i++) {
l = listeners[i];
if ("zIndex" in l) {
if (l.zIndex == indexed[z]) {
if (l.apply(scope, args) === f) {
return f;
}
do {
z++;
l = queue[indexed[z]];
if (l) {
if (l.apply(scope, args) === f) {
return f;
}
}
} while (l)
} else {
queue[l.zIndex] = l;
}
} else {
if (l.apply(scope, args) === f) {
return f;
} }
} }
if (errors.length) {
return errors;
} }
}; };
/*\
* eve.listeners
[ method ]
**
* Internal method which gives you array of all event handlers that will be triggered by the given `name`.
**
> Arguments
**
- name (string) name of the event, dot (`.`) or slash (`/`) separated
**
= (array) array of event handlers
\*/
eve.listeners = function (name) { eve.listeners = function (name) {
var names = name.split(separator), var names = name.split(separator),
e = events, e = events,
...@@ -5968,6 +6070,30 @@ ...@@ -5968,6 +6070,30 @@
} }
return out; return out;
}; };
/*\
* eve.on
[ method ]
**
* Binds given event handler with a given name. You can use wildcards “`*`” for the names:
| eve.on("*.under.*", f);
| eve("mouse.under.floor"); // triggers f
* Use @eve to trigger the listener.
**
> Arguments
**
- name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards
- f (function) event handler function
**
= (function) returned function accept one number parameter that represents z-index of the handler. It is optional feature and only used when you need to ensure that some subset of handlers will be invoked in a given order, despite of the order of assignment.
> Example:
| eve.on("mouse", eat)(2);
| eve.on("mouse", scream);
| eve.on("mouse", catch)(1);
* This will ensure that `catch` function will be called before `eat`.
* If you want to put you hadler before not indexed handlers specify negative value.
* Note: I assume most of the time you don’t need to worry about z-index, but it’s nice to have this feature “just in case”.
\*/
eve.on = function (name, f) { eve.on = function (name, f) {
var names = name.split(separator), var names = name.split(separator),
e = events; e = events;
...@@ -5978,10 +6104,46 @@ ...@@ -5978,10 +6104,46 @@
} }
e.f = e.f || []; e.f = e.f || [];
for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) { for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) {
return false; return fun;
} }
e.f.push(f); e.f.push(f);
return function (zIndex) {
if (+zIndex == +zIndex) {
f.zIndex = +zIndex;
}
}; };
};
/*\
* eve.nt
[ method ]
**
* Could be used inside event handler to figure out actual name of the event.
**
> Arguments
**
- subname (string) #optional subname of the event
**
= (string) name of the event, if `subname` is not specified
* or
= (boolean) `true`, if current event’s name contains `subname`
\*/
eve.nt = function (subname) {
if (subname) {
return new RegExp("(?:\\.|\\/|^)" + subname + "(?:\\.|\\/|$)").test(current_event);
}
return current_event;
};
/*\
* eve.unbind
[ method ]
**
* Removes given function from the list of event listeners assigned to given name.
**
> Arguments
**
- name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards
- f (function) event handler function
\*/
eve.unbind = function (name, f) { eve.unbind = function (name, f) {
var names = name.split(separator), var names = name.split(separator),
e, e,
...@@ -6032,8 +6194,13 @@ ...@@ -6032,8 +6194,13 @@
e = e.n; e = e.n;
} }
} }
return true;
}; };
/*\
* eve.version
[ property (string) ]
**
* Current version of the library.
\*/
eve.version = version; eve.version = version;
eve.toString = function () { eve.toString = function () {
return "You are running Eve " + version; return "You are running Eve " + version;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment