More tests and small fixes to the path
parent
fe71fc7505
commit
c40144d90c
|
@ -99,8 +99,8 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
|||
A = Savage.color(a);
|
||||
B = Savage.color(b);
|
||||
return {
|
||||
from: [A.r, A.g, A.b],
|
||||
to: [B.r, B.g, B.b],
|
||||
from: [A.r, A.g, A.b, A.opacity],
|
||||
to: [B.r, B.g, B.b, B.opacity],
|
||||
f: getColour
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
|||
p2s = /,?([a-z]),?/gi,
|
||||
toFloat = parseFloat,
|
||||
math = Math,
|
||||
PI = math.PI,
|
||||
mmin = math.min,
|
||||
mmax = math.max,
|
||||
pow = math.pow,
|
||||
|
@ -48,11 +49,9 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
|||
y2: y + height,
|
||||
cx: x + width / 2,
|
||||
cy: y + height / 2,
|
||||
rx: width / 2,
|
||||
ry: height / 2,
|
||||
r1: math.min(width, height) / 2,
|
||||
r2: math.max(width, height) / 2,
|
||||
r: math.sqrt(width * width + height * height) / 2,
|
||||
r0: math.sqrt(width * width + height * height) / 2,
|
||||
path: rectPath(x, y, width, height),
|
||||
vb: [x, y, width, height].join(" ")
|
||||
};
|
||||
|
@ -74,6 +73,9 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
|||
}
|
||||
}
|
||||
function getLengthFactory(istotal, subpath) {
|
||||
function O(val) {
|
||||
return +(+val).toFixed(3);
|
||||
}
|
||||
return function (path, length, onlystart) {
|
||||
path = path2curve(path);
|
||||
var x, y, p, l, sp = "", subpaths = {}, point,
|
||||
|
@ -88,10 +90,25 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
|||
if (len + l > length) {
|
||||
if (subpath && !subpaths.start) {
|
||||
point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
|
||||
sp += ["C" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y];
|
||||
sp += [
|
||||
"C" + O(point.start.x),
|
||||
O(point.start.y),
|
||||
O(point.m.x),
|
||||
O(point.m.y),
|
||||
O(point.x),
|
||||
O(point.y)
|
||||
];
|
||||
if (onlystart) {return sp;}
|
||||
subpaths.start = sp;
|
||||
sp = ["M" + point.x, point.y + "C" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join();
|
||||
sp = [
|
||||
"M" + O(point.x),
|
||||
O(point.y) + "C" + O(point.n.x),
|
||||
O(point.n.y),
|
||||
O(point.end.x),
|
||||
O(point.end.y),
|
||||
O(p[5]),
|
||||
O(p[6])
|
||||
].join();
|
||||
len += l;
|
||||
x = +p[5];
|
||||
y = +p[6];
|
||||
|
@ -99,7 +116,7 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
|||
}
|
||||
if (!istotal && !subpath) {
|
||||
point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
|
||||
return {x: point.x, y: point.y, alpha: point.alpha};
|
||||
return point;
|
||||
}
|
||||
}
|
||||
len += l;
|
||||
|
@ -109,8 +126,7 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
|||
sp += p.shift() + p;
|
||||
}
|
||||
subpaths.end = sp;
|
||||
point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
|
||||
point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});
|
||||
point = istotal ? len : subpath ? subpaths : findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
|
||||
return point;
|
||||
};
|
||||
}
|
||||
|
@ -134,7 +150,7 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
|||
cx = t1 * c2x + t * p2x,
|
||||
cy = t1 * c2y + t * p2y,
|
||||
alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI);
|
||||
(mx > nx || my < ny) && (alpha += 180);
|
||||
// (mx > nx || my < ny) && (alpha += 180);
|
||||
return {
|
||||
x: x,
|
||||
y: y,
|
||||
|
@ -158,18 +174,22 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
|||
);
|
||||
}
|
||||
function isPointInsideBBox(bbox, x, y) {
|
||||
return x >= bbox.x && x <= bbox.x2 && y >= bbox.y && y <= bbox.y2;
|
||||
return x >= bbox.x &&
|
||||
x <= bbox.x + bbox.width &&
|
||||
y >= bbox.y &&
|
||||
y <= bbox.y + bbox.height;
|
||||
}
|
||||
function isBBoxIntersect(bbox1, bbox2) {
|
||||
var i = isPointInsideBBox;
|
||||
return i(bbox2, bbox1.x, bbox1.y)
|
||||
|| i(bbox2, bbox1.x2, bbox1.y)
|
||||
|| i(bbox2, bbox1.x, bbox1.y2)
|
||||
|| i(bbox2, bbox1.x2, bbox1.y2)
|
||||
|| i(bbox1, bbox2.x, bbox2.y)
|
||||
|| i(bbox1, bbox2.x2, bbox2.y)
|
||||
|| i(bbox1, bbox2.x, bbox2.y2)
|
||||
|| i(bbox1, bbox2.x2, bbox2.y2)
|
||||
bbox1 = box(bbox1);
|
||||
bbox2 = box(bbox2);
|
||||
return isPointInsideBBox(bbox2, bbox1.x, bbox1.y)
|
||||
|| isPointInsideBBox(bbox2, bbox1.x2, bbox1.y)
|
||||
|| isPointInsideBBox(bbox2, bbox1.x, bbox1.y2)
|
||||
|| isPointInsideBBox(bbox2, bbox1.x2, bbox1.y2)
|
||||
|| isPointInsideBBox(bbox1, bbox2.x, bbox2.y)
|
||||
|| isPointInsideBBox(bbox1, bbox2.x2, bbox2.y)
|
||||
|| isPointInsideBBox(bbox1, bbox2.x, bbox2.y2)
|
||||
|| isPointInsideBBox(bbox1, bbox2.x2, bbox2.y2)
|
||||
|| (bbox1.x < bbox2.x2 && bbox1.x > bbox2.x
|
||||
|| bbox2.x < bbox1.x2 && bbox2.x > bbox1.x)
|
||||
&& (bbox1.y < bbox2.y2 && bbox1.y > bbox2.y
|
||||
|
@ -1184,7 +1204,7 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
|||
**
|
||||
* Utility method
|
||||
**
|
||||
* Returns `true` if given point is inside bounding boxes.
|
||||
* Returns `true` if given point is inside bounding box.
|
||||
> Parameters
|
||||
- bbox (string) bounding box
|
||||
- x (string) x coordinate of the point
|
||||
|
@ -1265,7 +1285,6 @@ Savage.plugin(function (Savage, Element, Paper, glob) {
|
|||
o }
|
||||
\*/
|
||||
Savage.path.getBBox = pathBBox;
|
||||
// TODO add doc
|
||||
Savage.path.get = getPath;
|
||||
/*\
|
||||
* Savage.path.toRelative
|
||||
|
|
126
svg.js
126
svg.js
|
@ -1,5 +1,6 @@
|
|||
var $VG, Savage = $VG = (function () {
|
||||
var Savage = function (w, h) {
|
||||
Savage.version = "0.0.1";
|
||||
function Savage(w, h) {
|
||||
if (w) {
|
||||
if (w.tagName) {
|
||||
return new Element(w);
|
||||
|
@ -14,6 +15,9 @@ var Savage = function (w, h) {
|
|||
w = w == null ? "100%" : w;
|
||||
h = h == null ? "100%" : h;
|
||||
return new Paper(w, h);
|
||||
}
|
||||
Savage.toString = function () {
|
||||
return "Savage v" + this.version;
|
||||
};
|
||||
Savage._ = {};
|
||||
var glob = {
|
||||
|
@ -64,7 +68,6 @@ function $(el, attr) {
|
|||
return el.getAttribute(attr);
|
||||
}
|
||||
for (var key in attr) if (attr[has](key)) {
|
||||
console.log(attr, key);
|
||||
var val = Str(attr[key]);
|
||||
if (val) {
|
||||
if (key.substring(0, 6) == "xlink:") {
|
||||
|
@ -177,9 +180,67 @@ function x_y_w_h() {
|
|||
return this.x + S + this.y + S + this.width + " \xd7 " + this.height;
|
||||
}
|
||||
|
||||
/*\
|
||||
* Raphael.rad
|
||||
[ method ]
|
||||
**
|
||||
* Transform angle to radians
|
||||
> Parameters
|
||||
- deg (number) angle in degrees
|
||||
= (number) angle in radians.
|
||||
\*/
|
||||
Savage.rad = rad;
|
||||
/*\
|
||||
* Raphael.deg
|
||||
[ method ]
|
||||
**
|
||||
* Transform angle to degrees
|
||||
> Parameters
|
||||
- deg (number) angle in radians
|
||||
= (number) angle in degrees.
|
||||
\*/
|
||||
Savage.deg = deg;
|
||||
/*\
|
||||
* Savage.is
|
||||
[ method ]
|
||||
**
|
||||
* Handfull replacement for `typeof` operator.
|
||||
> Parameters
|
||||
- o (…) any object or primitive
|
||||
- type (string) name of the type, i.e. “string”, “function”, “number”, etc.
|
||||
= (boolean) is given value is of given type
|
||||
\*/
|
||||
Savage.is = is;
|
||||
/*\
|
||||
* Savage.snapTo
|
||||
[ method ]
|
||||
**
|
||||
* Snaps given value to given grid.
|
||||
> Parameters
|
||||
- values (array|number) given array of values or step of the grid
|
||||
- value (number) value to adjust
|
||||
- tolerance (number) #optional tolerance for snapping. Default is `10`.
|
||||
= (number) adjusted value.
|
||||
\*/
|
||||
Savage.snapTo = function (values, value, tolerance) {
|
||||
tolerance = is(tolerance, "finite") ? tolerance : 10;
|
||||
if (is(values, "array")) {
|
||||
var i = values.length;
|
||||
while (i--) if (abs(values[i] - value) <= tolerance) {
|
||||
return values[i];
|
||||
}
|
||||
} else {
|
||||
values = +values;
|
||||
var rem = value % values;
|
||||
if (rem < tolerance) {
|
||||
return value - rem;
|
||||
}
|
||||
if (rem > values - tolerance) {
|
||||
return value - rem + values;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
// MATRIX
|
||||
function Matrix(a, b, c, d, e, f) {
|
||||
|
@ -435,6 +496,24 @@ function Matrix(a, b, c, d, e, f) {
|
|||
}
|
||||
};
|
||||
})(Matrix.prototype);
|
||||
/*\
|
||||
* Raphael.Matrix
|
||||
[ method ]
|
||||
**
|
||||
* Utility method
|
||||
**
|
||||
* Returns matrix based on given parameters.
|
||||
> Parameters
|
||||
- a (number)
|
||||
- b (number)
|
||||
- c (number)
|
||||
- d (number)
|
||||
- e (number)
|
||||
- f (number)
|
||||
* or
|
||||
- svgMatrix (SVGMatrix)
|
||||
= (object) @Matrix
|
||||
\*/
|
||||
Savage.Matrix = Matrix;
|
||||
// Colour
|
||||
/*\
|
||||
|
@ -574,7 +653,11 @@ Savage.hsl = cacher(function (h, s, l) {
|
|||
- b (number) blue
|
||||
= (string) hex representation of the colour.
|
||||
\*/
|
||||
Savage.rgb = cacher(function (r, g, b) {
|
||||
Savage.rgb = cacher(function (r, g, b, o) {
|
||||
if (is(o, "finite")) {
|
||||
var round = math.round;
|
||||
return "rgba(" + [round(r), round(g), round(b), +o.toFixed(2)] + ")";
|
||||
}
|
||||
return "#" + (16777216 | b | (g << 8) | (r << 16)).toString(16).slice(1);
|
||||
});
|
||||
var toHex = function (color) {
|
||||
|
@ -891,6 +974,17 @@ Savage.rgb2hsl = function (r, g, b) {
|
|||
pth.arr = Savage.path.clone(data);
|
||||
return data;
|
||||
};
|
||||
/*\
|
||||
* Savage.parseTransformString
|
||||
[ method ]
|
||||
**
|
||||
* Utility method
|
||||
**
|
||||
* Parses given path string into an array of transformations.
|
||||
> Parameters
|
||||
- TString (string|array) transform string or array of transformations (in the last case it will be returned straight away)
|
||||
= (array) array of transformations.
|
||||
\*/
|
||||
var parseTransformString = Savage.parseTransformString = function (TString) {
|
||||
if (!TString) {
|
||||
return null;
|
||||
|
@ -1034,12 +1128,6 @@ function extractTransform(el, tstr) {
|
|||
}
|
||||
}
|
||||
|
||||
/*\
|
||||
* Element.matrix
|
||||
[ property (object) ]
|
||||
**
|
||||
* Keeps @Matrix object, which represents element transformation
|
||||
\*/
|
||||
el.matrix = m;
|
||||
|
||||
_.sx = sx;
|
||||
|
@ -1138,10 +1226,27 @@ function unit2px(el, name, value) {
|
|||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/*\
|
||||
* Savage.select
|
||||
[ method ]
|
||||
**
|
||||
* Wraps DOM element specified by CSS selector as @Element
|
||||
> Parameters
|
||||
- query (string) CSS selector of the element
|
||||
= (Element)
|
||||
\*/
|
||||
Savage.select = function (query) {
|
||||
return new Element(glob.doc.querySelector(query));
|
||||
};
|
||||
/*\
|
||||
* Savage.selectAll
|
||||
[ method ]
|
||||
**
|
||||
* Wraps DOM elements specified by CSS selector as set or array of @Element
|
||||
> Parameters
|
||||
- query (string) CSS selector of the element
|
||||
= (Element)
|
||||
\*/
|
||||
Savage.selectAll = function (query) {
|
||||
var nodelist = glob.doc.querySelectorAll(query),
|
||||
set = (Savage.set || Array)();
|
||||
|
@ -1219,7 +1324,6 @@ function arrayFirstValue(arr) {
|
|||
this.realPath = Savage.path.get[this.type](this);
|
||||
}
|
||||
_.bbox = Savage.path.getBBox(Savage.path.map(this.realPath, this.matrix));
|
||||
console.log(this.attr("path"), this.realPath, Savage.path.map(this.realPath, this.matrix), _.bbox);
|
||||
_.bbox.toString = x_y_w_h;
|
||||
_.dirty = _.dirtyT = 0;
|
||||
}
|
||||
|
|
161
test/test.html
161
test/test.html
|
@ -15,6 +15,7 @@
|
|||
<script src="../mina.js"></script>
|
||||
<script src="../elemental.js"></script>
|
||||
<script src="../svg.js"></script>
|
||||
<script src="../savage.path.js"></script>
|
||||
<script src="../savage.set.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -342,6 +343,166 @@
|
|||
expect(c.node.getAttribute("rx")).to.be("5%");
|
||||
expect(c.node.getAttribute("ry")).to.be("6%");
|
||||
});
|
||||
it("path core attributes", function () {
|
||||
var c = s.path("M10,10 110,10");
|
||||
expect(c.node.getAttribute("d")).to.be("M10,10 110,10");
|
||||
c.attr({d: "M10,10 210,10"});
|
||||
expect(c.node.getAttribute("d")).to.be("M10,10 210,10");
|
||||
c.attr({path: "M10,10 310,10"});
|
||||
expect(c.node.getAttribute("d")).to.be("M10,10 310,10");
|
||||
});
|
||||
it("text core attributes", function () {
|
||||
var c = s.text(10, 15, "testing");
|
||||
expect(c.node.getAttribute("x")).to.be("10");
|
||||
expect(c.node.getAttribute("y")).to.be("15");
|
||||
expect(c.node.textContent).to.be("testing");
|
||||
c.attr({
|
||||
x: 20,
|
||||
y: 25,
|
||||
text: "texting"
|
||||
});
|
||||
expect(c.node.getAttribute("x")).to.be("20");
|
||||
expect(c.node.getAttribute("y")).to.be("25");
|
||||
expect(c.node.textContent).to.be("texting");
|
||||
});
|
||||
it("line core attributes", function () {
|
||||
var c = s.line(10, 15, 110, 17);
|
||||
expect(c.node.getAttribute("x1")).to.be("10");
|
||||
expect(c.node.getAttribute("y1")).to.be("15");
|
||||
expect(c.node.getAttribute("x2")).to.be("110");
|
||||
expect(c.node.getAttribute("y2")).to.be("17");
|
||||
c.attr({
|
||||
x1: 20,
|
||||
y1: 25,
|
||||
x2: 220,
|
||||
y2: 27
|
||||
});
|
||||
expect(c.node.getAttribute("x1")).to.be("20");
|
||||
expect(c.node.getAttribute("y1")).to.be("25");
|
||||
expect(c.node.getAttribute("x2")).to.be("220");
|
||||
expect(c.node.getAttribute("y2")).to.be("27");
|
||||
});
|
||||
it("polyline core attributes", function () {
|
||||
var c = s.polyline(10, 15, 20, 25, 30, 35);
|
||||
expect(c.node.getAttribute("points")).to.be("10,15,20,25,30,35");
|
||||
c.attr({
|
||||
points: [20, 25, 30, 35, 40, 45]
|
||||
});
|
||||
expect(c.node.getAttribute("points")).to.be("20,25,30,35,40,45");
|
||||
});
|
||||
it("polygon core attributes", function () {
|
||||
var c = s.polygon(10, 15, 20, 25, 30, 35);
|
||||
expect(c.node.getAttribute("points")).to.be("10,15,20,25,30,35");
|
||||
c.attr({
|
||||
points: [20, 25, 30, 35, 40, 45]
|
||||
});
|
||||
expect(c.node.getAttribute("points")).to.be("20,25,30,35,40,45");
|
||||
});
|
||||
});
|
||||
describe("Path methods", function () {
|
||||
it("Savage.path.getTotalLength", function () {
|
||||
expect(+Savage.path.getTotalLength("M0,0 100,0").toFixed(2)).to.be(100);
|
||||
});
|
||||
it("Savage.path.getPointAtLength", function () {
|
||||
expect(Savage.path.getPointAtLength("M0,0 100,0", 50)).to.eql({
|
||||
x: 50,
|
||||
y: 0,
|
||||
m: {
|
||||
x: 25,
|
||||
y: 0
|
||||
},
|
||||
n: {
|
||||
x: 75,
|
||||
y: 0
|
||||
},
|
||||
start: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
end: {
|
||||
x: 100,
|
||||
y: 0
|
||||
},
|
||||
alpha: 180
|
||||
});
|
||||
});
|
||||
it("Savage.path.getSubpath", function () {
|
||||
expect(Savage.path.getSubpath("M0,0 100,0", 10, 90)).to.be("M9.995,0C29.153,0,70.839,0,90,0");
|
||||
expect(Savage.path.getSubpath("M0,0 100,0", 0, 90)).to.be("M0,0C0,0,64.674,0,90,0");
|
||||
expect(Savage.path.getSubpath("M0,0 100,0", 10, 120)).to.be("M10,0C35.326,0,100,0,100,0");
|
||||
});
|
||||
it("Savage.path.findDotsAtSegment", function () {
|
||||
expect(Savage.path.findDotsAtSegment(0,0,0,0,100,0,100,0,.5)).to.eql({
|
||||
x: 50,
|
||||
y: 0,
|
||||
m: {
|
||||
x: 25,
|
||||
y: 0
|
||||
},
|
||||
n: {
|
||||
x: 75,
|
||||
y: 0
|
||||
},
|
||||
start: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
end: {
|
||||
x: 100,
|
||||
y: 0
|
||||
},
|
||||
alpha: 180
|
||||
});
|
||||
});
|
||||
it("Savage.path.bezierBBox", function () {
|
||||
var bbox = Savage.path.bezierBBox(10, 10, 10, 20, 110, 0, 110, 10);
|
||||
expect(bbox.cx).to.be(60);
|
||||
expect(bbox.cy).to.be(10);
|
||||
expect(bbox.x).to.be(10);
|
||||
expect(bbox.w).to.be(100);
|
||||
expect(bbox.width).to.be(100);
|
||||
expect(bbox.x2).to.be(110);
|
||||
});
|
||||
it("Savage.path.isPointInsideBBox", function () {
|
||||
expect(Savage.path.isPointInsideBBox({x: 0, y: 0, width: 10, height: 10}, 5, 5)).to.be(true);
|
||||
expect(Savage.path.isPointInsideBBox({x: 0, y: 0, width: 10, height: 10}, 10, 5)).to.be(true);
|
||||
expect(Savage.path.isPointInsideBBox({x: 0, y: 0, width: 10, height: 10}, 10, 10)).to.be(true);
|
||||
});
|
||||
it("Savage.path.isBBoxIntersect", function () {
|
||||
expect(Savage.path.isBBoxIntersect({
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 10,
|
||||
height: 10
|
||||
}, {
|
||||
x: 5,
|
||||
y: 5,
|
||||
width: 15,
|
||||
height: 15
|
||||
})).to.be(true);
|
||||
expect(Savage.path.isBBoxIntersect({
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 10,
|
||||
height: 10
|
||||
}, {
|
||||
x: 5,
|
||||
y: 5,
|
||||
width: 7,
|
||||
height: 7
|
||||
})).to.be(true);
|
||||
expect(Savage.path.isBBoxIntersect({
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 10,
|
||||
height: 10
|
||||
}, {
|
||||
x: 15,
|
||||
y: 15,
|
||||
width: 10,
|
||||
height: 10
|
||||
})).to.be(false);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
|
|
Loading…
Reference in New Issue