Fix for bug #17. New method Savage.angle. Fixed handling of <defs>. Fix use.getBBox. New method Element.toDefs(). Fix for gradient rgba. Fix for double defs.
parent
38ce178bb1
commit
38696874c1
|
@ -27,3 +27,9 @@ _*Savage uses Grunt 0.4.0. You might want to [read](http://gruntjs.com/getting-s
|
||||||
* Type `grunt` in the command line to build the files.
|
* Type `grunt` in the command line to build the files.
|
||||||
* The results will be built into the release folder.
|
* The results will be built into the release folder.
|
||||||
* Alternatively type `grunt watch` to have the build run automatically when you make changes to source files.
|
* Alternatively type `grunt watch` to have the build run automatically when you make changes to source files.
|
||||||
|
|
||||||
|
* For documentation generation use this command
|
||||||
|
|
||||||
|
cd node_modules/dr.js/; node dr ../../dr.json; cd ../../
|
||||||
|
|
||||||
|
_It’s ugly at the moment. Somebody should port it to grunt. May be even me :)_
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -28,7 +28,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
// build: 2013-09-17
|
// build: 2013-09-19
|
||||||
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
|
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -479,6 +479,23 @@ var mina = (function (eve) {
|
||||||
delete animations[a.id];
|
delete animations[a.id];
|
||||||
eve("mina.stop." + a.id, a);
|
eve("mina.stop." + a.id, a);
|
||||||
},
|
},
|
||||||
|
pause = function () {
|
||||||
|
var a = this;
|
||||||
|
if (a.pdif) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
delete animations[a.id];
|
||||||
|
a.pdif = a.get() - a.b;
|
||||||
|
},
|
||||||
|
resume = function () {
|
||||||
|
var a = this;
|
||||||
|
if (!a.pdif) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
a.b = a.get() - a.pdif;
|
||||||
|
delete a.pdif;
|
||||||
|
animations[a.id] = a;
|
||||||
|
},
|
||||||
frame = function () {
|
frame = function () {
|
||||||
var len = 0;
|
var len = 0;
|
||||||
for (var i in animations) if (animations.hasOwnProperty(i)) {
|
for (var i in animations) if (animations.hasOwnProperty(i)) {
|
||||||
|
@ -554,7 +571,9 @@ var mina = (function (eve) {
|
||||||
status: sta,
|
status: sta,
|
||||||
speed: speed,
|
speed: speed,
|
||||||
duration: duration,
|
duration: duration,
|
||||||
stop: stopit
|
stop: stopit,
|
||||||
|
pause: pause,
|
||||||
|
resume: resume
|
||||||
};
|
};
|
||||||
animations[anim.id] = anim;
|
animations[anim.id] = anim;
|
||||||
var len = 0, i;
|
var len = 0, i;
|
||||||
|
@ -586,7 +605,7 @@ var mina = (function (eve) {
|
||||||
= (object) See @mina
|
= (object) See @mina
|
||||||
\*/
|
\*/
|
||||||
mina.getById = function (id) {
|
mina.getById = function (id) {
|
||||||
return animations[anim.id] || null;
|
return animations[id] || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*\
|
/*\
|
||||||
|
@ -1323,6 +1342,18 @@ function cacher(f, scope, postprocessor) {
|
||||||
return newf;
|
return newf;
|
||||||
}
|
}
|
||||||
Savage._.cacher = cacher;
|
Savage._.cacher = cacher;
|
||||||
|
function angle(x1, y1, x2, y2, x3, y3) {
|
||||||
|
if (x3 == null) {
|
||||||
|
var x = x1 - x2,
|
||||||
|
y = y1 - y2;
|
||||||
|
if (!x && !y) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360;
|
||||||
|
} else {
|
||||||
|
return angle(x1, y1, x3, y3) - angle(x2, y2, x3, y3);
|
||||||
|
}
|
||||||
|
}
|
||||||
function rad(deg) {
|
function rad(deg) {
|
||||||
return deg % 360 * PI / 180;
|
return deg % 360 * PI / 180;
|
||||||
}
|
}
|
||||||
|
@ -1354,6 +1385,21 @@ Savage.rad = rad;
|
||||||
= (number) angle in degrees.
|
= (number) angle in degrees.
|
||||||
\*/
|
\*/
|
||||||
Savage.deg = deg;
|
Savage.deg = deg;
|
||||||
|
/*\
|
||||||
|
* Savage.angle
|
||||||
|
[ method ]
|
||||||
|
**
|
||||||
|
* Returns angle between two or three points.
|
||||||
|
> Parameters
|
||||||
|
- x1 (number) x coord of first point
|
||||||
|
- y1 (number) y coord of first point
|
||||||
|
- x2 (number) x coord of second point
|
||||||
|
- y2 (number) y coord of second point
|
||||||
|
- x3 (number) #optional x coord of third point
|
||||||
|
- y3 (number) #optional y coord of third point
|
||||||
|
= (number) angle in degrees.
|
||||||
|
\*/
|
||||||
|
Savage.angle = angle;
|
||||||
/*\
|
/*\
|
||||||
* Savage.is
|
* Savage.is
|
||||||
[ method ]
|
[ method ]
|
||||||
|
@ -1433,7 +1479,7 @@ function Matrix(a, b, c, d, e, f) {
|
||||||
- d (number)
|
- d (number)
|
||||||
- e (number)
|
- e (number)
|
||||||
- f (number)
|
- f (number)
|
||||||
or
|
* or
|
||||||
- matrix (object) @Matrix
|
- matrix (object) @Matrix
|
||||||
\*/
|
\*/
|
||||||
matrixproto.add = function (a, b, c, d, e, f) {
|
matrixproto.add = function (a, b, c, d, e, f) {
|
||||||
|
@ -2300,13 +2346,29 @@ function extractTransform(el, tstr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Savage._unit2px = unit2px;
|
Savage._unit2px = unit2px;
|
||||||
|
function getSomeDefs(el) {
|
||||||
|
if (Savage._.someDefs) {
|
||||||
|
return Savage._.someDefs;
|
||||||
|
}
|
||||||
|
var p = el.paper ||
|
||||||
|
(el.node.parentNode && Savage(el.node.parentNode)) ||
|
||||||
|
Savage.select("svg") ||
|
||||||
|
Savage(0, 0),
|
||||||
|
defs = p.select("defs").node;
|
||||||
|
if (!defs) {
|
||||||
|
defs = make("defs", p.node).node;
|
||||||
|
}
|
||||||
|
Savage._.someDefs = defs;
|
||||||
|
return defs;
|
||||||
|
}
|
||||||
|
Savage._.getSomeDefs = getSomeDefs;
|
||||||
function unit2px(el, name, value) {
|
function unit2px(el, name, value) {
|
||||||
var defs = el.paper.defs,
|
var defs = getSomeDefs(el),
|
||||||
out = {},
|
out = {},
|
||||||
mgr = el.paper.measurer;
|
mgr = defs.querySelector(".svg---mgr");
|
||||||
if (!mgr) {
|
if (!mgr) {
|
||||||
el.paper.measurer = mgr = $("rect");
|
mgr = $("rect");
|
||||||
$(mgr, {width: 10, height: 10});
|
$(mgr, {width: 10, height: 10, "class": "svg---mgr"});
|
||||||
defs.appendChild(mgr);
|
defs.appendChild(mgr);
|
||||||
}
|
}
|
||||||
function getW(val) {
|
function getW(val) {
|
||||||
|
@ -2545,25 +2607,29 @@ function arrayFirstValue(arr) {
|
||||||
o }
|
o }
|
||||||
\*/
|
\*/
|
||||||
elproto.getBBox = function (isWithoutTransform) {
|
elproto.getBBox = function (isWithoutTransform) {
|
||||||
if (this.removed) {
|
var el = this;
|
||||||
|
if (el.type == "use") {
|
||||||
|
el = el.original;
|
||||||
|
}
|
||||||
|
if (el.removed) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
var _ = this._;
|
var _ = el._;
|
||||||
if (isWithoutTransform) {
|
if (isWithoutTransform) {
|
||||||
if (_.dirty || !_.bboxwt) {
|
if (_.dirty || !_.bboxwt) {
|
||||||
this.realPath = Savage.path.get[this.type](this);
|
el.realPath = Savage.path.get[el.type](el);
|
||||||
_.bboxwt = Savage.path.getBBox(this.realPath);
|
_.bboxwt = Savage.path.getBBox(el.realPath);
|
||||||
_.bboxwt.toString = x_y_w_h;
|
_.bboxwt.toString = x_y_w_h;
|
||||||
_.dirty = 0;
|
_.dirty = 0;
|
||||||
}
|
}
|
||||||
return Savage._.box(_.bboxwt);
|
return Savage._.box(_.bboxwt);
|
||||||
}
|
}
|
||||||
if (_.dirty || _.dirtyT || !_.bbox) {
|
if (_.dirty || _.dirtyT || !_.bbox) {
|
||||||
if (_.dirty || !this.realPath) {
|
if (_.dirty || !el.realPath) {
|
||||||
_.bboxwt = 0;
|
_.bboxwt = 0;
|
||||||
this.realPath = Savage.path.get[this.type](this);
|
el.realPath = Savage.path.get[el.type](el);
|
||||||
}
|
}
|
||||||
_.bbox = Savage.path.getBBox(Savage.path.map(this.realPath, this.matrix));
|
_.bbox = Savage.path.getBBox(Savage.path.map(el.realPath, el.matrix));
|
||||||
_.bbox.toString = x_y_w_h;
|
_.bbox.toString = x_y_w_h;
|
||||||
_.dirty = _.dirtyT = 0;
|
_.dirty = _.dirtyT = 0;
|
||||||
}
|
}
|
||||||
|
@ -2749,7 +2815,7 @@ function arrayFirstValue(arr) {
|
||||||
= (Element) removed element
|
= (Element) removed element
|
||||||
\*/
|
\*/
|
||||||
elproto.remove = function () {
|
elproto.remove = function () {
|
||||||
this.node.parentNode.removeChild(this.node);
|
this.node.parentNode && this.node.parentNode.removeChild(this.node);
|
||||||
delete this.paper;
|
delete this.paper;
|
||||||
this.removed = true;
|
this.removed = true;
|
||||||
return this;
|
return this;
|
||||||
|
@ -2825,6 +2891,7 @@ function arrayFirstValue(arr) {
|
||||||
$(use.node, {
|
$(use.node, {
|
||||||
"xlink:href": "#" + id
|
"xlink:href": "#" + id
|
||||||
});
|
});
|
||||||
|
use.original = this;
|
||||||
return use;
|
return use;
|
||||||
};
|
};
|
||||||
/*\
|
/*\
|
||||||
|
@ -2906,6 +2973,19 @@ function arrayFirstValue(arr) {
|
||||||
clone.insertAfter(this);
|
clone.insertAfter(this);
|
||||||
return clone;
|
return clone;
|
||||||
};
|
};
|
||||||
|
/*\
|
||||||
|
* Element.toDefs
|
||||||
|
[ method ]
|
||||||
|
**
|
||||||
|
* Moves element to the relative `<defs>` section.
|
||||||
|
**
|
||||||
|
= (Element) the clone
|
||||||
|
\*/
|
||||||
|
elproto.toDefs = function () {
|
||||||
|
var defs = getSomeDefs(this);
|
||||||
|
defs.appendChild(this.node);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
/*\
|
/*\
|
||||||
* Element.pattern
|
* Element.pattern
|
||||||
[ method ]
|
[ method ]
|
||||||
|
@ -2930,7 +3010,7 @@ function arrayFirstValue(arr) {
|
||||||
| });
|
| });
|
||||||
\*/
|
\*/
|
||||||
elproto.pattern = function (x, y, width, height) {
|
elproto.pattern = function (x, y, width, height) {
|
||||||
var p = make("pattern", this.paper.defs);
|
var p = make("pattern", getSomeDefs(this));
|
||||||
if (x == null) {
|
if (x == null) {
|
||||||
x = this.getBBox();
|
x = this.getBBox();
|
||||||
}
|
}
|
||||||
|
@ -2970,7 +3050,7 @@ function arrayFirstValue(arr) {
|
||||||
\*/
|
\*/
|
||||||
// TODO add usage for markers
|
// TODO add usage for markers
|
||||||
elproto.marker = function (x, y, width, height, refX, refY) {
|
elproto.marker = function (x, y, width, height, refX, refY) {
|
||||||
var p = make("marker", this.paper.defs);
|
var p = make("marker", getSomeDefs(this));
|
||||||
if (x == null) {
|
if (x == null) {
|
||||||
x = this.getBBox();
|
x = this.getBBox();
|
||||||
}
|
}
|
||||||
|
@ -3363,6 +3443,20 @@ function Paper(w, h) {
|
||||||
res = new Element(w);
|
res = new Element(w);
|
||||||
desc = w.getElementsByTagName("desc")[0];
|
desc = w.getElementsByTagName("desc")[0];
|
||||||
defs = w.getElementsByTagName("defs")[0];
|
defs = w.getElementsByTagName("defs")[0];
|
||||||
|
if (!desc) {
|
||||||
|
desc = $("desc");
|
||||||
|
desc.appendChild(glob.doc.createTextNode("Created with Savage"));
|
||||||
|
res.node.appendChild(desc);
|
||||||
|
}
|
||||||
|
if (!defs) {
|
||||||
|
defs = $("defs");
|
||||||
|
res.node.appendChild(defs);
|
||||||
|
}
|
||||||
|
res.defs = defs;
|
||||||
|
for (var key in proto) if (proto[has](key)) {
|
||||||
|
res[key] = proto[key];
|
||||||
|
}
|
||||||
|
res.paper = res.root = res;
|
||||||
} else {
|
} else {
|
||||||
res = make("svg", glob.doc.body);
|
res = make("svg", glob.doc.body);
|
||||||
$(res.node, {
|
$(res.node, {
|
||||||
|
@ -3372,20 +3466,6 @@ function Paper(w, h) {
|
||||||
xmlns: "http://www.w3.org/2000/svg"
|
xmlns: "http://www.w3.org/2000/svg"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!desc) {
|
|
||||||
desc = $("desc");
|
|
||||||
desc.appendChild(glob.doc.createTextNode("Created with Savage"));
|
|
||||||
res.node.appendChild(desc);
|
|
||||||
}
|
|
||||||
if (!defs) {
|
|
||||||
defs = $("defs");
|
|
||||||
res.node.appendChild(defs);
|
|
||||||
}
|
|
||||||
for (var key in proto) if (proto[has](key)) {
|
|
||||||
res[key] = proto[key];
|
|
||||||
}
|
|
||||||
res.paper = res.root = res;
|
|
||||||
res.defs = defs;
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
function wrap(dom) {
|
function wrap(dom) {
|
||||||
|
@ -3400,6 +3480,115 @@ function wrap(dom) {
|
||||||
}
|
}
|
||||||
return new Element(dom);
|
return new Element(dom);
|
||||||
}
|
}
|
||||||
|
// gradients’ helpers
|
||||||
|
function Gstops() {
|
||||||
|
return this.selectAll("stop");
|
||||||
|
}
|
||||||
|
function GaddStop(color, offset) {
|
||||||
|
var stop = $("stop"),
|
||||||
|
attr = {
|
||||||
|
offset: +offset + "%"
|
||||||
|
};
|
||||||
|
color = Savage.color(color);
|
||||||
|
attr["stop-color"] = color.hex;
|
||||||
|
if (color.opacity < 1) {
|
||||||
|
attr["stop-opacity"] = color.opacity;
|
||||||
|
}
|
||||||
|
$(stop, attr);
|
||||||
|
this.node.appendChild(stop);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
function GgetBBox() {
|
||||||
|
if (this.type == "linearGradient") {
|
||||||
|
var x1 = $(this.node, "x1") || 0,
|
||||||
|
x2 = $(this.node, "x2") || 1,
|
||||||
|
y1 = $(this.node, "y1") || 0,
|
||||||
|
y2 = $(this.node, "y2") || 0;
|
||||||
|
return Savage._.box(x1, y1, math.abs(x2 - x1), math.abs(y2 - y1));
|
||||||
|
} else {
|
||||||
|
var cx = this.node.cx || .5,
|
||||||
|
cy = this.node.cy || .5,
|
||||||
|
r = this.node.r || 0;
|
||||||
|
return Savage._.box(cx - r, cy - r, r * 2, r * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function gradient(defs, str) {
|
||||||
|
var grad = arrayFirstValue(eve("savage.util.grad.parse", null, str)),
|
||||||
|
el;
|
||||||
|
if (!grad) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
grad.params.unshift(defs);
|
||||||
|
if (grad.type.toLowerCase() == "l") {
|
||||||
|
el = gradientLinear.apply(0, grad.params);
|
||||||
|
} else {
|
||||||
|
el = gradientRadial.apply(0, grad.params);
|
||||||
|
}
|
||||||
|
if (grad.type != grad.type.toLowerCase()) {
|
||||||
|
$(el.node, {
|
||||||
|
gradientUnits: "userSpaceOnUse"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var stops = grad.stops,
|
||||||
|
len = stops.length,
|
||||||
|
start = 0,
|
||||||
|
j = 0;
|
||||||
|
function seed(i, end) {
|
||||||
|
var step = (end - start) / (i - j);
|
||||||
|
for (var k = j; k < i; k++) {
|
||||||
|
stops[k].offset = +(+start + step * (k - j)).toFixed(2);
|
||||||
|
}
|
||||||
|
j = i;
|
||||||
|
start = end;
|
||||||
|
}
|
||||||
|
len--;
|
||||||
|
for (var i = 0; i < len; i++) if ("offset" in stops[i]) {
|
||||||
|
seed(i, stops[i].offset);
|
||||||
|
}
|
||||||
|
stops[len].offset = stops[len].offset || 100;
|
||||||
|
seed(len, stops[len].offset);
|
||||||
|
for (i = 0; i <= len; i++) {
|
||||||
|
var stop = stops[i];
|
||||||
|
el.addStop(stop.color, stop.offset);
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
function gradientLinear(defs, x1, y1, x2, y2) {
|
||||||
|
var el = make("linearGradient", defs);
|
||||||
|
el.stops = Gstops;
|
||||||
|
el.addStop = GaddStop;
|
||||||
|
el.getBBox = GgetBBox;
|
||||||
|
if (x1 != null) {
|
||||||
|
$(el.node, {
|
||||||
|
x1: x1,
|
||||||
|
y1: y1,
|
||||||
|
x2: x2,
|
||||||
|
y2: y2
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
function gradientRadial(defs, cx, cy, r, fx, fy) {
|
||||||
|
var el = make("radialGradient", defs);
|
||||||
|
el.stops = Gstops;
|
||||||
|
el.addStop = GaddStop;
|
||||||
|
el.getBBox = GgetBBox;
|
||||||
|
if (cx != null) {
|
||||||
|
$(el.node, {
|
||||||
|
cx: cx,
|
||||||
|
cy: cy,
|
||||||
|
r: r
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (fx != null && fy != null) {
|
||||||
|
$(el.node, {
|
||||||
|
fx: fx,
|
||||||
|
fy: fy
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
// Paper prototype methods
|
||||||
(function (proto) {
|
(function (proto) {
|
||||||
/*\
|
/*\
|
||||||
* Paper.el
|
* Paper.el
|
||||||
|
@ -3801,105 +3990,13 @@ function wrap(dom) {
|
||||||
= (object) Element object with type “gradient”
|
= (object) Element object with type “gradient”
|
||||||
\*/
|
\*/
|
||||||
proto.gradient = function (str) {
|
proto.gradient = function (str) {
|
||||||
var grad = arrayFirstValue(eve("savage.util.grad.parse", null, str)),
|
return gradient(this.defs, str);
|
||||||
el;
|
|
||||||
if (!grad) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (grad.type.toLowerCase() == "l") {
|
|
||||||
el = this.gradientLinear.apply(this, grad.params);
|
|
||||||
} else {
|
|
||||||
el = this.gradientRadial.apply(this, grad.params);
|
|
||||||
}
|
|
||||||
if (grad.type != grad.type.toLowerCase()) {
|
|
||||||
$(el.node, {
|
|
||||||
gradientUnits: "userSpaceOnUse"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
var stops = grad.stops,
|
|
||||||
len = stops.length,
|
|
||||||
start = 0,
|
|
||||||
j = 0;
|
|
||||||
function seed(i, end) {
|
|
||||||
var step = (end - start) / (i - j);
|
|
||||||
for (var k = j; k < i; k++) {
|
|
||||||
stops[k].offset = +(+start + step * (k - j)).toFixed(2);
|
|
||||||
}
|
|
||||||
j = i;
|
|
||||||
start = end;
|
|
||||||
}
|
|
||||||
len--;
|
|
||||||
for (var i = 0; i < len; i++) if ("offset" in stops[i]) {
|
|
||||||
seed(i, stops[i].offset);
|
|
||||||
}
|
|
||||||
stops[len].offset = stops[len].offset || 100;
|
|
||||||
seed(len, stops[len].offset);
|
|
||||||
for (i = 0; i <= len; i++) {
|
|
||||||
var stop = stops[i];
|
|
||||||
el.addStop(stop.color, stop.offset);
|
|
||||||
}
|
|
||||||
return el;
|
|
||||||
};
|
};
|
||||||
function stops() {
|
|
||||||
return this.selectAll("stop");
|
|
||||||
}
|
|
||||||
function addStop(color, offset) {
|
|
||||||
var stop = $("stop");
|
|
||||||
$(stop, {
|
|
||||||
"stop-color": color,
|
|
||||||
offset: +offset + "%"
|
|
||||||
});
|
|
||||||
this.node.appendChild(stop);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
function getBBox() {
|
|
||||||
if (this.type == "linearGradient") {
|
|
||||||
var x1 = $(this.node, "x1") || 0,
|
|
||||||
x2 = $(this.node, "x2") || 1,
|
|
||||||
y1 = $(this.node, "y1") || 0,
|
|
||||||
y2 = $(this.node, "y2") || 0;
|
|
||||||
return Savage._.box(x1, y1, math.abs(x2 - x1), math.abs(y2 - y1));
|
|
||||||
} else {
|
|
||||||
var cx = this.node.cx || .5,
|
|
||||||
cy = this.node.cy || .5,
|
|
||||||
r = this.node.r || 0;
|
|
||||||
return Savage._.box(cx - r, cy - r, r * 2, r * 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
proto.gradientLinear = function (x1, y1, x2, y2) {
|
proto.gradientLinear = function (x1, y1, x2, y2) {
|
||||||
var el = make("linearGradient", this.node);
|
return gradientLinear(this.defs, x1, y1, x2, y2);
|
||||||
el.stops = stops;
|
|
||||||
el.addStop = addStop;
|
|
||||||
el.getBBox = getBBox;
|
|
||||||
if (x1 != null) {
|
|
||||||
$(el.node, {
|
|
||||||
x1: x1,
|
|
||||||
y1: y1,
|
|
||||||
x2: x2,
|
|
||||||
y2: y2
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return el;
|
|
||||||
};
|
};
|
||||||
proto.gradientRadial = function (cx, cy, r, fx, fy) {
|
proto.gradientRadial = function (cx, cy, r, fx, fy) {
|
||||||
var el = make("radialGradient", this.node);
|
return gradientRadial(this.defs, cx, cy, r, fx, fy);
|
||||||
el.stops = stops;
|
|
||||||
el.addStop = addStop;
|
|
||||||
el.getBBox = getBBox;
|
|
||||||
if (cx != null) {
|
|
||||||
$(el.node, {
|
|
||||||
cx: cx,
|
|
||||||
cy: cy,
|
|
||||||
r: r
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (fx != null && fy != null) {
|
|
||||||
$(el.node, {
|
|
||||||
fx: fx,
|
|
||||||
fy: fy
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return el;
|
|
||||||
};
|
};
|
||||||
/*\
|
/*\
|
||||||
* Paper.toString
|
* Paper.toString
|
||||||
|
@ -3999,13 +4096,13 @@ eve.on("savage.util.attr.mask", function (value) {
|
||||||
eve.stop();
|
eve.stop();
|
||||||
if (value instanceof Fragment && value.node.childNodes.length == 1) {
|
if (value instanceof Fragment && value.node.childNodes.length == 1) {
|
||||||
value = value.node.firstChild;
|
value = value.node.firstChild;
|
||||||
this.paper.defs.appendChild(value);
|
getSomeDefs(this).appendChild(value);
|
||||||
value = wrap(value);
|
value = wrap(value);
|
||||||
}
|
}
|
||||||
if (value.type == "mask") {
|
if (value.type == "mask") {
|
||||||
var mask = value;
|
var mask = value;
|
||||||
} else {
|
} else {
|
||||||
mask = make("mask", this.paper.defs);
|
mask = make("mask", getSomeDefs(this));
|
||||||
mask.node.appendChild(value.node);
|
mask.node.appendChild(value.node);
|
||||||
!mask.node.id && $(mask.node, {
|
!mask.node.id && $(mask.node, {
|
||||||
id: mask.id
|
id: mask.id
|
||||||
|
@ -4026,7 +4123,7 @@ eve.on("savage.util.attr.mask", function (value) {
|
||||||
if (value.type == "clipPath") {
|
if (value.type == "clipPath") {
|
||||||
var clip = value;
|
var clip = value;
|
||||||
} else {
|
} else {
|
||||||
clip = make("clipPath", this.paper.defs);
|
clip = make("clipPath", getSomeDefs(this));
|
||||||
clip.node.appendChild(value.node);
|
clip.node.appendChild(value.node);
|
||||||
!clip.node.id && $(clip.node, {
|
!clip.node.id && $(clip.node, {
|
||||||
id: clip.id
|
id: clip.id
|
||||||
|
@ -4045,7 +4142,7 @@ function fillStroke(name) {
|
||||||
value.node.firstChild.tagName == "linearGradient" ||
|
value.node.firstChild.tagName == "linearGradient" ||
|
||||||
value.node.firstChild.tagName == "pattern")) {
|
value.node.firstChild.tagName == "pattern")) {
|
||||||
value = value.node.firstChild;
|
value = value.node.firstChild;
|
||||||
this.paper.defs.appendChild(value);
|
getSomeDefs(this).appendChild(value);
|
||||||
value = wrap(value);
|
value = wrap(value);
|
||||||
}
|
}
|
||||||
if (value instanceof Element) {
|
if (value instanceof Element) {
|
||||||
|
@ -4063,7 +4160,7 @@ function fillStroke(name) {
|
||||||
} else {
|
} else {
|
||||||
fill = Savage.color(value);
|
fill = Savage.color(value);
|
||||||
if (fill.error) {
|
if (fill.error) {
|
||||||
var grad = this.paper.gradient(value);
|
var grad = gradient(getSomeDefs(this), value);
|
||||||
if (grad) {
|
if (grad) {
|
||||||
if (!grad.node.id) {
|
if (!grad.node.id) {
|
||||||
$(grad.node, {
|
$(grad.node, {
|
||||||
|
@ -4806,7 +4903,7 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
||||||
function O(val) {
|
function O(val) {
|
||||||
return +(+val).toFixed(3);
|
return +(+val).toFixed(3);
|
||||||
}
|
}
|
||||||
return function (path, length, onlystart) {
|
return Savage._.cacher(function (path, length, onlystart) {
|
||||||
if (path instanceof Element) {
|
if (path instanceof Element) {
|
||||||
path = path.attr("d");
|
path = path.attr("d");
|
||||||
}
|
}
|
||||||
|
@ -4861,7 +4958,7 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
||||||
subpaths.end = sp;
|
subpaths.end = sp;
|
||||||
point = istotal ? len : subpath ? subpaths : findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
|
point = istotal ? len : subpath ? subpaths : findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
|
||||||
return point;
|
return point;
|
||||||
};
|
}, null, Savage._.clone);
|
||||||
}
|
}
|
||||||
var getTotalLength = getLengthFactory(1),
|
var getTotalLength = getLengthFactory(1),
|
||||||
getPointAtLength = getLengthFactory(),
|
getPointAtLength = getLengthFactory(),
|
||||||
|
@ -5242,7 +5339,8 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
function pathToRelative(pathArray) {
|
function pathToRelative(pathArray) {
|
||||||
var pth = paths(pathArray);
|
var pth = paths(pathArray),
|
||||||
|
lowerCase = String.prototype.toLowerCase;
|
||||||
if (pth.rel) {
|
if (pth.rel) {
|
||||||
return pathClone(pth.rel);
|
return pathClone(pth.rel);
|
||||||
}
|
}
|
||||||
|
@ -6200,6 +6298,7 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
||||||
this.splice(i, 1);
|
this.splice(i, 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
setproto.insertAfter = function (el) {
|
setproto.insertAfter = function (el) {
|
||||||
var i = this.items.length;
|
var i = this.items.length;
|
||||||
|
@ -7005,6 +7104,10 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
||||||
if (blur == null) {
|
if (blur == null) {
|
||||||
blur = 4;
|
blur = 4;
|
||||||
}
|
}
|
||||||
|
if (typeof blur == "string") {
|
||||||
|
color = blur;
|
||||||
|
blur = 4;
|
||||||
|
}
|
||||||
if (dx == null) {
|
if (dx == null) {
|
||||||
dx = 0;
|
dx = 0;
|
||||||
dy = 2;
|
dy = 2;
|
||||||
|
@ -7012,6 +7115,7 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
||||||
if (dy == null) {
|
if (dy == null) {
|
||||||
dy = dx;
|
dy = dx;
|
||||||
}
|
}
|
||||||
|
color = Savage.color(color);
|
||||||
return Savage.format('<feGaussianBlur in="SourceAlpha" stdDeviation="{blur}"/><feOffset dx="{dx}" dy="{dy}" result="offsetblur"/><feFlood flood-color="{color}"/><feComposite in2="offsetblur" operator="in"/><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>', {
|
return Savage.format('<feGaussianBlur in="SourceAlpha" stdDeviation="{blur}"/><feOffset dx="{dx}" dy="{dy}" result="offsetblur"/><feFlood flood-color="{color}"/><feComposite in2="offsetblur" operator="in"/><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>', {
|
||||||
color: color,
|
color: color,
|
||||||
dx: dx,
|
dx: dx,
|
||||||
|
|
|
@ -149,6 +149,7 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
||||||
this.splice(i, 1);
|
this.splice(i, 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
setproto.insertAfter = function (el) {
|
setproto.insertAfter = function (el) {
|
||||||
var i = this.items.length;
|
var i = this.items.length;
|
||||||
|
|
336
src/svg.js
336
src/svg.js
|
@ -245,6 +245,18 @@ function cacher(f, scope, postprocessor) {
|
||||||
return newf;
|
return newf;
|
||||||
}
|
}
|
||||||
Savage._.cacher = cacher;
|
Savage._.cacher = cacher;
|
||||||
|
function angle(x1, y1, x2, y2, x3, y3) {
|
||||||
|
if (x3 == null) {
|
||||||
|
var x = x1 - x2,
|
||||||
|
y = y1 - y2;
|
||||||
|
if (!x && !y) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360;
|
||||||
|
} else {
|
||||||
|
return angle(x1, y1, x3, y3) - angle(x2, y2, x3, y3);
|
||||||
|
}
|
||||||
|
}
|
||||||
function rad(deg) {
|
function rad(deg) {
|
||||||
return deg % 360 * PI / 180;
|
return deg % 360 * PI / 180;
|
||||||
}
|
}
|
||||||
|
@ -276,6 +288,21 @@ Savage.rad = rad;
|
||||||
= (number) angle in degrees.
|
= (number) angle in degrees.
|
||||||
\*/
|
\*/
|
||||||
Savage.deg = deg;
|
Savage.deg = deg;
|
||||||
|
/*\
|
||||||
|
* Savage.angle
|
||||||
|
[ method ]
|
||||||
|
**
|
||||||
|
* Returns angle between two or three points.
|
||||||
|
> Parameters
|
||||||
|
- x1 (number) x coord of first point
|
||||||
|
- y1 (number) y coord of first point
|
||||||
|
- x2 (number) x coord of second point
|
||||||
|
- y2 (number) y coord of second point
|
||||||
|
- x3 (number) #optional x coord of third point
|
||||||
|
- y3 (number) #optional y coord of third point
|
||||||
|
= (number) angle in degrees.
|
||||||
|
\*/
|
||||||
|
Savage.angle = angle;
|
||||||
/*\
|
/*\
|
||||||
* Savage.is
|
* Savage.is
|
||||||
[ method ]
|
[ method ]
|
||||||
|
@ -355,7 +382,7 @@ function Matrix(a, b, c, d, e, f) {
|
||||||
- d (number)
|
- d (number)
|
||||||
- e (number)
|
- e (number)
|
||||||
- f (number)
|
- f (number)
|
||||||
or
|
* or
|
||||||
- matrix (object) @Matrix
|
- matrix (object) @Matrix
|
||||||
\*/
|
\*/
|
||||||
matrixproto.add = function (a, b, c, d, e, f) {
|
matrixproto.add = function (a, b, c, d, e, f) {
|
||||||
|
@ -1222,13 +1249,29 @@ function extractTransform(el, tstr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Savage._unit2px = unit2px;
|
Savage._unit2px = unit2px;
|
||||||
|
function getSomeDefs(el) {
|
||||||
|
if (Savage._.someDefs) {
|
||||||
|
return Savage._.someDefs;
|
||||||
|
}
|
||||||
|
var p = el.paper ||
|
||||||
|
(el.node.parentNode && Savage(el.node.parentNode)) ||
|
||||||
|
Savage.select("svg") ||
|
||||||
|
Savage(0, 0),
|
||||||
|
defs = p.select("defs").node;
|
||||||
|
if (!defs) {
|
||||||
|
defs = make("defs", p.node).node;
|
||||||
|
}
|
||||||
|
Savage._.someDefs = defs;
|
||||||
|
return defs;
|
||||||
|
}
|
||||||
|
Savage._.getSomeDefs = getSomeDefs;
|
||||||
function unit2px(el, name, value) {
|
function unit2px(el, name, value) {
|
||||||
var defs = el.paper.defs,
|
var defs = getSomeDefs(el),
|
||||||
out = {},
|
out = {},
|
||||||
mgr = el.paper.measurer;
|
mgr = defs.querySelector(".svg---mgr");
|
||||||
if (!mgr) {
|
if (!mgr) {
|
||||||
el.paper.measurer = mgr = $("rect");
|
mgr = $("rect");
|
||||||
$(mgr, {width: 10, height: 10});
|
$(mgr, {width: 10, height: 10, "class": "svg---mgr"});
|
||||||
defs.appendChild(mgr);
|
defs.appendChild(mgr);
|
||||||
}
|
}
|
||||||
function getW(val) {
|
function getW(val) {
|
||||||
|
@ -1467,25 +1510,29 @@ function arrayFirstValue(arr) {
|
||||||
o }
|
o }
|
||||||
\*/
|
\*/
|
||||||
elproto.getBBox = function (isWithoutTransform) {
|
elproto.getBBox = function (isWithoutTransform) {
|
||||||
if (this.removed) {
|
var el = this;
|
||||||
|
if (el.type == "use") {
|
||||||
|
el = el.original;
|
||||||
|
}
|
||||||
|
if (el.removed) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
var _ = this._;
|
var _ = el._;
|
||||||
if (isWithoutTransform) {
|
if (isWithoutTransform) {
|
||||||
if (_.dirty || !_.bboxwt) {
|
if (_.dirty || !_.bboxwt) {
|
||||||
this.realPath = Savage.path.get[this.type](this);
|
el.realPath = Savage.path.get[el.type](el);
|
||||||
_.bboxwt = Savage.path.getBBox(this.realPath);
|
_.bboxwt = Savage.path.getBBox(el.realPath);
|
||||||
_.bboxwt.toString = x_y_w_h;
|
_.bboxwt.toString = x_y_w_h;
|
||||||
_.dirty = 0;
|
_.dirty = 0;
|
||||||
}
|
}
|
||||||
return Savage._.box(_.bboxwt);
|
return Savage._.box(_.bboxwt);
|
||||||
}
|
}
|
||||||
if (_.dirty || _.dirtyT || !_.bbox) {
|
if (_.dirty || _.dirtyT || !_.bbox) {
|
||||||
if (_.dirty || !this.realPath) {
|
if (_.dirty || !el.realPath) {
|
||||||
_.bboxwt = 0;
|
_.bboxwt = 0;
|
||||||
this.realPath = Savage.path.get[this.type](this);
|
el.realPath = Savage.path.get[el.type](el);
|
||||||
}
|
}
|
||||||
_.bbox = Savage.path.getBBox(Savage.path.map(this.realPath, this.matrix));
|
_.bbox = Savage.path.getBBox(Savage.path.map(el.realPath, el.matrix));
|
||||||
_.bbox.toString = x_y_w_h;
|
_.bbox.toString = x_y_w_h;
|
||||||
_.dirty = _.dirtyT = 0;
|
_.dirty = _.dirtyT = 0;
|
||||||
}
|
}
|
||||||
|
@ -1671,7 +1718,7 @@ function arrayFirstValue(arr) {
|
||||||
= (Element) removed element
|
= (Element) removed element
|
||||||
\*/
|
\*/
|
||||||
elproto.remove = function () {
|
elproto.remove = function () {
|
||||||
this.node.parentNode.removeChild(this.node);
|
this.node.parentNode && this.node.parentNode.removeChild(this.node);
|
||||||
delete this.paper;
|
delete this.paper;
|
||||||
this.removed = true;
|
this.removed = true;
|
||||||
return this;
|
return this;
|
||||||
|
@ -1747,6 +1794,7 @@ function arrayFirstValue(arr) {
|
||||||
$(use.node, {
|
$(use.node, {
|
||||||
"xlink:href": "#" + id
|
"xlink:href": "#" + id
|
||||||
});
|
});
|
||||||
|
use.original = this;
|
||||||
return use;
|
return use;
|
||||||
};
|
};
|
||||||
/*\
|
/*\
|
||||||
|
@ -1828,6 +1876,19 @@ function arrayFirstValue(arr) {
|
||||||
clone.insertAfter(this);
|
clone.insertAfter(this);
|
||||||
return clone;
|
return clone;
|
||||||
};
|
};
|
||||||
|
/*\
|
||||||
|
* Element.toDefs
|
||||||
|
[ method ]
|
||||||
|
**
|
||||||
|
* Moves element to the relative `<defs>` section.
|
||||||
|
**
|
||||||
|
= (Element) the clone
|
||||||
|
\*/
|
||||||
|
elproto.toDefs = function () {
|
||||||
|
var defs = getSomeDefs(this);
|
||||||
|
defs.appendChild(this.node);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
/*\
|
/*\
|
||||||
* Element.pattern
|
* Element.pattern
|
||||||
[ method ]
|
[ method ]
|
||||||
|
@ -1852,7 +1913,7 @@ function arrayFirstValue(arr) {
|
||||||
| });
|
| });
|
||||||
\*/
|
\*/
|
||||||
elproto.pattern = function (x, y, width, height) {
|
elproto.pattern = function (x, y, width, height) {
|
||||||
var p = make("pattern", this.paper.defs);
|
var p = make("pattern", getSomeDefs(this));
|
||||||
if (x == null) {
|
if (x == null) {
|
||||||
x = this.getBBox();
|
x = this.getBBox();
|
||||||
}
|
}
|
||||||
|
@ -1892,7 +1953,7 @@ function arrayFirstValue(arr) {
|
||||||
\*/
|
\*/
|
||||||
// TODO add usage for markers
|
// TODO add usage for markers
|
||||||
elproto.marker = function (x, y, width, height, refX, refY) {
|
elproto.marker = function (x, y, width, height, refX, refY) {
|
||||||
var p = make("marker", this.paper.defs);
|
var p = make("marker", getSomeDefs(this));
|
||||||
if (x == null) {
|
if (x == null) {
|
||||||
x = this.getBBox();
|
x = this.getBBox();
|
||||||
}
|
}
|
||||||
|
@ -2285,6 +2346,20 @@ function Paper(w, h) {
|
||||||
res = new Element(w);
|
res = new Element(w);
|
||||||
desc = w.getElementsByTagName("desc")[0];
|
desc = w.getElementsByTagName("desc")[0];
|
||||||
defs = w.getElementsByTagName("defs")[0];
|
defs = w.getElementsByTagName("defs")[0];
|
||||||
|
if (!desc) {
|
||||||
|
desc = $("desc");
|
||||||
|
desc.appendChild(glob.doc.createTextNode("Created with Savage"));
|
||||||
|
res.node.appendChild(desc);
|
||||||
|
}
|
||||||
|
if (!defs) {
|
||||||
|
defs = $("defs");
|
||||||
|
res.node.appendChild(defs);
|
||||||
|
}
|
||||||
|
res.defs = defs;
|
||||||
|
for (var key in proto) if (proto[has](key)) {
|
||||||
|
res[key] = proto[key];
|
||||||
|
}
|
||||||
|
res.paper = res.root = res;
|
||||||
} else {
|
} else {
|
||||||
res = make("svg", glob.doc.body);
|
res = make("svg", glob.doc.body);
|
||||||
$(res.node, {
|
$(res.node, {
|
||||||
|
@ -2294,20 +2369,6 @@ function Paper(w, h) {
|
||||||
xmlns: "http://www.w3.org/2000/svg"
|
xmlns: "http://www.w3.org/2000/svg"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!desc) {
|
|
||||||
desc = $("desc");
|
|
||||||
desc.appendChild(glob.doc.createTextNode("Created with Savage"));
|
|
||||||
res.node.appendChild(desc);
|
|
||||||
}
|
|
||||||
if (!defs) {
|
|
||||||
defs = $("defs");
|
|
||||||
res.node.appendChild(defs);
|
|
||||||
}
|
|
||||||
for (var key in proto) if (proto[has](key)) {
|
|
||||||
res[key] = proto[key];
|
|
||||||
}
|
|
||||||
res.paper = res.root = res;
|
|
||||||
res.defs = defs;
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
function wrap(dom) {
|
function wrap(dom) {
|
||||||
|
@ -2322,6 +2383,115 @@ function wrap(dom) {
|
||||||
}
|
}
|
||||||
return new Element(dom);
|
return new Element(dom);
|
||||||
}
|
}
|
||||||
|
// gradients’ helpers
|
||||||
|
function Gstops() {
|
||||||
|
return this.selectAll("stop");
|
||||||
|
}
|
||||||
|
function GaddStop(color, offset) {
|
||||||
|
var stop = $("stop"),
|
||||||
|
attr = {
|
||||||
|
offset: +offset + "%"
|
||||||
|
};
|
||||||
|
color = Savage.color(color);
|
||||||
|
attr["stop-color"] = color.hex;
|
||||||
|
if (color.opacity < 1) {
|
||||||
|
attr["stop-opacity"] = color.opacity;
|
||||||
|
}
|
||||||
|
$(stop, attr);
|
||||||
|
this.node.appendChild(stop);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
function GgetBBox() {
|
||||||
|
if (this.type == "linearGradient") {
|
||||||
|
var x1 = $(this.node, "x1") || 0,
|
||||||
|
x2 = $(this.node, "x2") || 1,
|
||||||
|
y1 = $(this.node, "y1") || 0,
|
||||||
|
y2 = $(this.node, "y2") || 0;
|
||||||
|
return Savage._.box(x1, y1, math.abs(x2 - x1), math.abs(y2 - y1));
|
||||||
|
} else {
|
||||||
|
var cx = this.node.cx || .5,
|
||||||
|
cy = this.node.cy || .5,
|
||||||
|
r = this.node.r || 0;
|
||||||
|
return Savage._.box(cx - r, cy - r, r * 2, r * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function gradient(defs, str) {
|
||||||
|
var grad = arrayFirstValue(eve("savage.util.grad.parse", null, str)),
|
||||||
|
el;
|
||||||
|
if (!grad) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
grad.params.unshift(defs);
|
||||||
|
if (grad.type.toLowerCase() == "l") {
|
||||||
|
el = gradientLinear.apply(0, grad.params);
|
||||||
|
} else {
|
||||||
|
el = gradientRadial.apply(0, grad.params);
|
||||||
|
}
|
||||||
|
if (grad.type != grad.type.toLowerCase()) {
|
||||||
|
$(el.node, {
|
||||||
|
gradientUnits: "userSpaceOnUse"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var stops = grad.stops,
|
||||||
|
len = stops.length,
|
||||||
|
start = 0,
|
||||||
|
j = 0;
|
||||||
|
function seed(i, end) {
|
||||||
|
var step = (end - start) / (i - j);
|
||||||
|
for (var k = j; k < i; k++) {
|
||||||
|
stops[k].offset = +(+start + step * (k - j)).toFixed(2);
|
||||||
|
}
|
||||||
|
j = i;
|
||||||
|
start = end;
|
||||||
|
}
|
||||||
|
len--;
|
||||||
|
for (var i = 0; i < len; i++) if ("offset" in stops[i]) {
|
||||||
|
seed(i, stops[i].offset);
|
||||||
|
}
|
||||||
|
stops[len].offset = stops[len].offset || 100;
|
||||||
|
seed(len, stops[len].offset);
|
||||||
|
for (i = 0; i <= len; i++) {
|
||||||
|
var stop = stops[i];
|
||||||
|
el.addStop(stop.color, stop.offset);
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
function gradientLinear(defs, x1, y1, x2, y2) {
|
||||||
|
var el = make("linearGradient", defs);
|
||||||
|
el.stops = Gstops;
|
||||||
|
el.addStop = GaddStop;
|
||||||
|
el.getBBox = GgetBBox;
|
||||||
|
if (x1 != null) {
|
||||||
|
$(el.node, {
|
||||||
|
x1: x1,
|
||||||
|
y1: y1,
|
||||||
|
x2: x2,
|
||||||
|
y2: y2
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
function gradientRadial(defs, cx, cy, r, fx, fy) {
|
||||||
|
var el = make("radialGradient", defs);
|
||||||
|
el.stops = Gstops;
|
||||||
|
el.addStop = GaddStop;
|
||||||
|
el.getBBox = GgetBBox;
|
||||||
|
if (cx != null) {
|
||||||
|
$(el.node, {
|
||||||
|
cx: cx,
|
||||||
|
cy: cy,
|
||||||
|
r: r
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (fx != null && fy != null) {
|
||||||
|
$(el.node, {
|
||||||
|
fx: fx,
|
||||||
|
fy: fy
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
// Paper prototype methods
|
||||||
(function (proto) {
|
(function (proto) {
|
||||||
/*\
|
/*\
|
||||||
* Paper.el
|
* Paper.el
|
||||||
|
@ -2723,105 +2893,13 @@ function wrap(dom) {
|
||||||
= (object) Element object with type “gradient”
|
= (object) Element object with type “gradient”
|
||||||
\*/
|
\*/
|
||||||
proto.gradient = function (str) {
|
proto.gradient = function (str) {
|
||||||
var grad = arrayFirstValue(eve("savage.util.grad.parse", null, str)),
|
return gradient(this.defs, str);
|
||||||
el;
|
|
||||||
if (!grad) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (grad.type.toLowerCase() == "l") {
|
|
||||||
el = this.gradientLinear.apply(this, grad.params);
|
|
||||||
} else {
|
|
||||||
el = this.gradientRadial.apply(this, grad.params);
|
|
||||||
}
|
|
||||||
if (grad.type != grad.type.toLowerCase()) {
|
|
||||||
$(el.node, {
|
|
||||||
gradientUnits: "userSpaceOnUse"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
var stops = grad.stops,
|
|
||||||
len = stops.length,
|
|
||||||
start = 0,
|
|
||||||
j = 0;
|
|
||||||
function seed(i, end) {
|
|
||||||
var step = (end - start) / (i - j);
|
|
||||||
for (var k = j; k < i; k++) {
|
|
||||||
stops[k].offset = +(+start + step * (k - j)).toFixed(2);
|
|
||||||
}
|
|
||||||
j = i;
|
|
||||||
start = end;
|
|
||||||
}
|
|
||||||
len--;
|
|
||||||
for (var i = 0; i < len; i++) if ("offset" in stops[i]) {
|
|
||||||
seed(i, stops[i].offset);
|
|
||||||
}
|
|
||||||
stops[len].offset = stops[len].offset || 100;
|
|
||||||
seed(len, stops[len].offset);
|
|
||||||
for (i = 0; i <= len; i++) {
|
|
||||||
var stop = stops[i];
|
|
||||||
el.addStop(stop.color, stop.offset);
|
|
||||||
}
|
|
||||||
return el;
|
|
||||||
};
|
};
|
||||||
function stops() {
|
|
||||||
return this.selectAll("stop");
|
|
||||||
}
|
|
||||||
function addStop(color, offset) {
|
|
||||||
var stop = $("stop");
|
|
||||||
$(stop, {
|
|
||||||
"stop-color": color,
|
|
||||||
offset: +offset + "%"
|
|
||||||
});
|
|
||||||
this.node.appendChild(stop);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
function getBBox() {
|
|
||||||
if (this.type == "linearGradient") {
|
|
||||||
var x1 = $(this.node, "x1") || 0,
|
|
||||||
x2 = $(this.node, "x2") || 1,
|
|
||||||
y1 = $(this.node, "y1") || 0,
|
|
||||||
y2 = $(this.node, "y2") || 0;
|
|
||||||
return Savage._.box(x1, y1, math.abs(x2 - x1), math.abs(y2 - y1));
|
|
||||||
} else {
|
|
||||||
var cx = this.node.cx || .5,
|
|
||||||
cy = this.node.cy || .5,
|
|
||||||
r = this.node.r || 0;
|
|
||||||
return Savage._.box(cx - r, cy - r, r * 2, r * 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
proto.gradientLinear = function (x1, y1, x2, y2) {
|
proto.gradientLinear = function (x1, y1, x2, y2) {
|
||||||
var el = make("linearGradient", this.node);
|
return gradientLinear(this.defs, x1, y1, x2, y2);
|
||||||
el.stops = stops;
|
|
||||||
el.addStop = addStop;
|
|
||||||
el.getBBox = getBBox;
|
|
||||||
if (x1 != null) {
|
|
||||||
$(el.node, {
|
|
||||||
x1: x1,
|
|
||||||
y1: y1,
|
|
||||||
x2: x2,
|
|
||||||
y2: y2
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return el;
|
|
||||||
};
|
};
|
||||||
proto.gradientRadial = function (cx, cy, r, fx, fy) {
|
proto.gradientRadial = function (cx, cy, r, fx, fy) {
|
||||||
var el = make("radialGradient", this.node);
|
return gradientRadial(this.defs, cx, cy, r, fx, fy);
|
||||||
el.stops = stops;
|
|
||||||
el.addStop = addStop;
|
|
||||||
el.getBBox = getBBox;
|
|
||||||
if (cx != null) {
|
|
||||||
$(el.node, {
|
|
||||||
cx: cx,
|
|
||||||
cy: cy,
|
|
||||||
r: r
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (fx != null && fy != null) {
|
|
||||||
$(el.node, {
|
|
||||||
fx: fx,
|
|
||||||
fy: fy
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return el;
|
|
||||||
};
|
};
|
||||||
/*\
|
/*\
|
||||||
* Paper.toString
|
* Paper.toString
|
||||||
|
@ -2921,13 +2999,13 @@ eve.on("savage.util.attr.mask", function (value) {
|
||||||
eve.stop();
|
eve.stop();
|
||||||
if (value instanceof Fragment && value.node.childNodes.length == 1) {
|
if (value instanceof Fragment && value.node.childNodes.length == 1) {
|
||||||
value = value.node.firstChild;
|
value = value.node.firstChild;
|
||||||
this.paper.defs.appendChild(value);
|
getSomeDefs(this).appendChild(value);
|
||||||
value = wrap(value);
|
value = wrap(value);
|
||||||
}
|
}
|
||||||
if (value.type == "mask") {
|
if (value.type == "mask") {
|
||||||
var mask = value;
|
var mask = value;
|
||||||
} else {
|
} else {
|
||||||
mask = make("mask", this.paper.defs);
|
mask = make("mask", getSomeDefs(this));
|
||||||
mask.node.appendChild(value.node);
|
mask.node.appendChild(value.node);
|
||||||
!mask.node.id && $(mask.node, {
|
!mask.node.id && $(mask.node, {
|
||||||
id: mask.id
|
id: mask.id
|
||||||
|
@ -2948,7 +3026,7 @@ eve.on("savage.util.attr.mask", function (value) {
|
||||||
if (value.type == "clipPath") {
|
if (value.type == "clipPath") {
|
||||||
var clip = value;
|
var clip = value;
|
||||||
} else {
|
} else {
|
||||||
clip = make("clipPath", this.paper.defs);
|
clip = make("clipPath", getSomeDefs(this));
|
||||||
clip.node.appendChild(value.node);
|
clip.node.appendChild(value.node);
|
||||||
!clip.node.id && $(clip.node, {
|
!clip.node.id && $(clip.node, {
|
||||||
id: clip.id
|
id: clip.id
|
||||||
|
@ -2967,7 +3045,7 @@ function fillStroke(name) {
|
||||||
value.node.firstChild.tagName == "linearGradient" ||
|
value.node.firstChild.tagName == "linearGradient" ||
|
||||||
value.node.firstChild.tagName == "pattern")) {
|
value.node.firstChild.tagName == "pattern")) {
|
||||||
value = value.node.firstChild;
|
value = value.node.firstChild;
|
||||||
this.paper.defs.appendChild(value);
|
getSomeDefs(this).appendChild(value);
|
||||||
value = wrap(value);
|
value = wrap(value);
|
||||||
}
|
}
|
||||||
if (value instanceof Element) {
|
if (value instanceof Element) {
|
||||||
|
@ -2985,7 +3063,7 @@ function fillStroke(name) {
|
||||||
} else {
|
} else {
|
||||||
fill = Savage.color(value);
|
fill = Savage.color(value);
|
||||||
if (fill.error) {
|
if (fill.error) {
|
||||||
var grad = this.paper.gradient(value);
|
var grad = gradient(getSomeDefs(this), value);
|
||||||
if (grad) {
|
if (grad) {
|
||||||
if (!grad.node.id) {
|
if (!grad.node.id) {
|
||||||
$(grad.node, {
|
$(grad.node, {
|
||||||
|
|
Loading…
Reference in New Issue