Merge branch 'dev'
commit
064ad5b081
|
@ -2,3 +2,5 @@ TAGS
|
|||
*~
|
||||
_*
|
||||
.DS_Store
|
||||
node_modules
|
||||
playground
|
|
@ -31,12 +31,16 @@ module.exports = function(grunt) {
|
|||
"./src/amd-banner.js",
|
||||
"./src/mina.js",
|
||||
"./src/svg.js",
|
||||
"./src/matrix.js",
|
||||
"./src/attr.js",
|
||||
"./src/attradd.js",
|
||||
"./src/paper.js",
|
||||
"./src/path.js",
|
||||
"./src/set.js",
|
||||
"./src/equal.js",
|
||||
"./src/mouse.js",
|
||||
"./src/filter.js",
|
||||
"./src/amd-footer.js",
|
||||
"./src/amd-footer.js"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "Snap.svg",
|
||||
"version": "0.1.1",
|
||||
"version": "0.3.0",
|
||||
"homepage": "http://snapsvg.io",
|
||||
"authors": [
|
||||
"Dmitry Baranovskiy <dmitry@baranovskiy.com>"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "Snap.svg",
|
||||
"repo": "adobe-webplatform/Snap.svg",
|
||||
"description": "The JavaScript library for modern SVG graphics.",
|
||||
"version": "0.1.1",
|
||||
"version": "0.3.0",
|
||||
"keywords": ["svg", "snap", "js", "javascript"],
|
||||
"dependencies": {},
|
||||
"development": {},
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
display: "none"
|
||||
});
|
||||
var flag,
|
||||
len = pth.getTotalLength();
|
||||
len = Snap.path.getTotalLength(pth.attr("d"));
|
||||
Snap.animate(0, len, function (l) {
|
||||
// Safari bug workaround: forcing redraw
|
||||
g.attr({width: 100 + (flag = !flag ? 1e-5 : 0) + "%"});
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="copyright" content="Copyright © 2013 Adobe Systems Incorporated. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the “License”);
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an “AS IS” BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.">
|
||||
<title>Snap</title>
|
||||
<style media="screen">
|
||||
body {
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
<script src="../../dist/snap.svg-min.js"></script>
|
||||
<script>
|
||||
window.onload = function () {
|
||||
var s = Snap(600, 600);
|
||||
var path = "",
|
||||
nums = s.text(300, 300, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]).attr({
|
||||
font: "300 40px Helvetica Neue",
|
||||
textAnchor: "middle"
|
||||
});
|
||||
for (var i = 0; i < 72; i++) {
|
||||
var r = i % 6 ? i % 3 ? 247 : 240 : 230,
|
||||
sin = Math.sin(Snap.rad(5 * i)),
|
||||
cos = Math.cos(Snap.rad(5 * i));
|
||||
path += "M" + [300 + 250 * cos, 300 + 250 * sin] + "L" + [300 + r * cos, 300 + r * sin];
|
||||
if (!(i % 6)) {
|
||||
nums.select("tspan:nth-child(" + (i / 6 + 1) + ")").attr({
|
||||
x: 300 + 200 * Math.cos(Snap.rad(5 * i - 60)),
|
||||
y: 300 + 200 * Math.sin(Snap.rad(5 * i - 60)) + 15,
|
||||
});
|
||||
}
|
||||
}
|
||||
var table = s.g(nums, s.path(path).attr({
|
||||
fill: "none",
|
||||
stroke: "#000",
|
||||
strokeWidth: 2
|
||||
})).attr({
|
||||
transform: "t0,210"
|
||||
});
|
||||
s.g(table).attr({
|
||||
clip: s.circle(300, 300, 100)
|
||||
});
|
||||
var hand = s.line(300, 200, 300, 400).attr({
|
||||
fill: "none",
|
||||
stroke: "#f63",
|
||||
strokeWidth: 2
|
||||
});
|
||||
s.circle(300, 300, 100).attr({
|
||||
stroke: "#000",
|
||||
strokeWidth: 10,
|
||||
fillOpacity: 0
|
||||
}).click(function () {
|
||||
Snap.animate(0, 360, function (val) {
|
||||
table.transform("t" +
|
||||
[
|
||||
210 * Math.cos(Snap.rad(val + 90)),
|
||||
210 * Math.sin(Snap.rad(val + 90))
|
||||
]);
|
||||
hand.transform("r" + [val, 300, 300]);
|
||||
}, 12000);
|
||||
});
|
||||
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,180 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tutorial</title>
|
||||
<link rel="stylesheet" href="../../doc/fonts/stylesheet.css">
|
||||
<link rel="stylesheet" href="../../doc/css/prism.css">
|
||||
<style media="screen">
|
||||
pre.code {
|
||||
-moz-border-radius: 10px;
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
height: 280px;
|
||||
overflow: auto;
|
||||
background: #181818;
|
||||
border: solid 2px #181818;
|
||||
}
|
||||
#codelines {
|
||||
display: none;
|
||||
}
|
||||
#svg {
|
||||
-moz-border-radius: 10px;
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
border: solid 2px #ccc;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
font: 1em source-sans-pro, Source Sans Pro, Helvetica, sans-serif;
|
||||
}
|
||||
</style>
|
||||
<script src="../../dist/snap.svg-min.js"></script>
|
||||
<script src="../../doc/js/prism.js"></script>
|
||||
<script>
|
||||
var S;
|
||||
window.onload = function () {
|
||||
var s = Snap(850, 35);
|
||||
function chooser(s, count) {
|
||||
var loop = "M35,65a30,30,0,0,0,0-60a30,30,0,0,0,0,60",
|
||||
line = "M35,65a30,30,0,0,0,0-60a30,30,0,0,0,0,60c30,0,60-60,90-60a30,30,0,0,1,0,60a30,30,0,0,1,0-60",
|
||||
l1 = Snap.path.getTotalLength(loop),
|
||||
l2 = Snap.path.getTotalLength(line),
|
||||
cur = 1,
|
||||
p = s.path({
|
||||
path: loop,
|
||||
fill: "none",
|
||||
stroke: "#f00",
|
||||
strokeWidth: 6,
|
||||
strokeLinecap: "round"
|
||||
});
|
||||
for (var i = 1; i <= count; i++) {
|
||||
s.text(90 * i - 55, 49, i).attr({
|
||||
font: "45px source-sans-pro, Source Sans Pro, Helvetica, sans-serif",
|
||||
textAnchor: "middle"
|
||||
});
|
||||
(function (i) {
|
||||
s.circle(90 * i - 55, 35, 40).attr({
|
||||
opacity: 0
|
||||
}).click(eve.f("tut.click", i - 1));
|
||||
}(i));
|
||||
}
|
||||
s.path("M11.166,23.963L22.359,17.5c1.43-0.824,1.43-2.175,0-3L11.166,8.037c-1.429-0.826-2.598-0.15-2.598,1.5v12.926C8.568,24.113,9.737,24.789,11.166,23.963z").transform("t" + (90 * (count + 1) - 68) + ",18s2");
|
||||
var but = s.circle(90 * (count + 1) - 55, 35, 30).attr({
|
||||
fillOpacity: 0,
|
||||
stroke: "#333",
|
||||
strokeWidth: 2
|
||||
});
|
||||
eve.on("tut.click", function (I) {
|
||||
p.attr({
|
||||
path: loop,
|
||||
transform: "t" + (90 * I) + ",0"
|
||||
});
|
||||
cur = I + 1;
|
||||
});
|
||||
function frameHandler(frame) {
|
||||
function anim() {
|
||||
cur++;
|
||||
if (cur > count) {
|
||||
return;
|
||||
}
|
||||
if (typeof frame == "function") {
|
||||
frame(cur);
|
||||
}
|
||||
Snap.animate(0, l2 - l1, function (val) {
|
||||
p.attr({
|
||||
path: Snap.path.getSubpath(line, val, val + l1)
|
||||
});
|
||||
}, 500, function () {
|
||||
p.attr({
|
||||
path: loop,
|
||||
transform: p.transform() + "t90,0"
|
||||
});
|
||||
});
|
||||
}
|
||||
if (typeof frame == "function") {
|
||||
but.click(anim);
|
||||
} else {
|
||||
anim();
|
||||
}
|
||||
}
|
||||
return frameHandler;
|
||||
}
|
||||
var g = s.g();
|
||||
g.attr({
|
||||
transform: "s.5,.5,0,0"
|
||||
});
|
||||
var str = "",
|
||||
code = document.getElementById("code");
|
||||
var domcodelines = document.querySelectorAll("#codelines li"),
|
||||
codelines = [],
|
||||
replacers = {},
|
||||
lines = [],
|
||||
callback = function (i) {
|
||||
lines = [];
|
||||
for (var j = 1; j <= i; j++) {
|
||||
replacers[j - 1] && lines.pop();
|
||||
lines.push(codelines[j - 1]);
|
||||
}
|
||||
Snap("#svg").clear();
|
||||
str = lines.join("\n");
|
||||
eval(str);
|
||||
code.innerHTML = Prism.highlight(str, Prism.languages.javascript);
|
||||
code.parentNode.scrollTop = code.parentNode.scrollTopMax || 1e9;
|
||||
};
|
||||
for (var i = 0, ii = domcodelines.length; i < ii; i++) {
|
||||
codelines[i] = domcodelines[i].innerHTML;
|
||||
if (domcodelines[i].className == "replace") {
|
||||
replacers[i] = true;
|
||||
}
|
||||
}
|
||||
callback(1);
|
||||
chooser(g, codelines.length)(callback);
|
||||
eve.on("tut.click", function (I) {
|
||||
callback(I + 1);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<ol id="codelines">
|
||||
<li>// Simple dashed pattern on circle
|
||||
var s = Snap("#svg");</li>
|
||||
<li>// This will be our shape. It could be anything.
|
||||
var bigCircle = s.circle(150, 150, 100);</li>
|
||||
<li>bigCircle.attr({
|
||||
stroke: "#000",
|
||||
strokeWidth: 5
|
||||
});</li>
|
||||
<li>// Now let's create pattern
|
||||
var p = s.path("M110,95,95,110M115,100,100,115").attr({
|
||||
fill: "none",
|
||||
stroke: "#bada55",
|
||||
strokeWidth: 4
|
||||
});
|
||||
</li>
|
||||
<li>//This is where our pattern cut will happen:
|
||||
var cut = s.rect(100, 100, 10, 10).attr({fill: "#fff", opacity: .5})</li>
|
||||
<li>cut.remove();</li>
|
||||
<li>//make it a pattern
|
||||
var ptrn = p.pattern(100, 100, 10, 10);
|
||||
//ptrn is an invisible <pattern> element.</li>
|
||||
<li>// Then use it as a fill on the big circle
|
||||
bigCircle.attr({
|
||||
fill: ptrn
|
||||
});</li>
|
||||
<li>//We still have access to original path for the pattern, lets animate it a bit:</li>
|
||||
<li>p.animate({strokeWidth: 1, stroke: "#FF4136"}, 1e3);
|
||||
//Note that pattern could have as many elements as you want</li>
|
||||
</ol>
|
||||
<svg id="svg"></svg>
|
||||
<pre class="javascript code"><code data-language="javascript" class="language-javascript" id="code"></code></pre>
|
||||
<svg width="0" height="0">
|
||||
<pattern id="pattern" patternUnits="userSpaceOnUse" x="0" y="0" width="10" height="10" viewBox="0 0 10 10">
|
||||
<path d="M-5,0,10,15M0-5,15,10" stroke="white" stroke-width="5"/>
|
||||
</pattern>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,194 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tutorial</title>
|
||||
<link rel="stylesheet" href="../../doc/fonts/stylesheet.css">
|
||||
<link rel="stylesheet" href="../../doc/css/prism.css">
|
||||
<style media="screen">
|
||||
pre.code {
|
||||
-moz-border-radius: 10px;
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
height: 280px;
|
||||
overflow: auto;
|
||||
background: #181818;
|
||||
border: solid 2px #181818;
|
||||
}
|
||||
#codelines {
|
||||
display: none;
|
||||
}
|
||||
#svg {
|
||||
-moz-border-radius: 10px;
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
border: solid 2px #ccc;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
font: 1em source-sans-pro, Source Sans Pro, Helvetica, sans-serif;
|
||||
}
|
||||
</style>
|
||||
<script src="../../dist/snap.svg-min.js"></script>
|
||||
<script src="../../doc/js/prism.js"></script>
|
||||
<script>
|
||||
var S;
|
||||
window.onload = function () {
|
||||
var s = Snap(850, 35);
|
||||
function chooser(s, count) {
|
||||
var loop = "M35,65a30,30,0,0,0,0-60a30,30,0,0,0,0,60",
|
||||
line = "M35,65a30,30,0,0,0,0-60a30,30,0,0,0,0,60c30,0,60-60,90-60a30,30,0,0,1,0,60a30,30,0,0,1,0-60",
|
||||
l1 = Snap.path.getTotalLength(loop),
|
||||
l2 = Snap.path.getTotalLength(line),
|
||||
cur = 1,
|
||||
p = s.path({
|
||||
path: loop,
|
||||
fill: "none",
|
||||
stroke: "#f00",
|
||||
strokeWidth: 6,
|
||||
strokeLinecap: "round"
|
||||
});
|
||||
for (var i = 1; i <= count; i++) {
|
||||
s.text(90 * i - 55, 49, i).attr({
|
||||
font: "45px source-sans-pro, Source Sans Pro, Helvetica, sans-serif",
|
||||
textAnchor: "middle"
|
||||
});
|
||||
(function (i) {
|
||||
s.circle(90 * i - 55, 35, 40).attr({
|
||||
opacity: 0
|
||||
}).click(eve.f("tut.click", i - 1));
|
||||
}(i));
|
||||
}
|
||||
s.path("M11.166,23.963L22.359,17.5c1.43-0.824,1.43-2.175,0-3L11.166,8.037c-1.429-0.826-2.598-0.15-2.598,1.5v12.926C8.568,24.113,9.737,24.789,11.166,23.963z").transform("t" + (90 * (count + 1) - 68) + ",18s2");
|
||||
var but = s.circle(90 * (count + 1) - 55, 35, 30).attr({
|
||||
fillOpacity: 0,
|
||||
stroke: "#333",
|
||||
strokeWidth: 2
|
||||
});
|
||||
eve.on("tut.click", function (I) {
|
||||
p.attr({
|
||||
path: loop,
|
||||
transform: "t" + (90 * I) + ",0"
|
||||
});
|
||||
cur = I + 1;
|
||||
});
|
||||
function frameHandler(frame) {
|
||||
function anim() {
|
||||
cur++;
|
||||
if (cur > count) {
|
||||
return;
|
||||
}
|
||||
if (typeof frame == "function") {
|
||||
frame(cur);
|
||||
}
|
||||
Snap.animate(0, l2 - l1, function (val) {
|
||||
p.attr({
|
||||
path: Snap.path.getSubpath(line, val, val + l1)
|
||||
});
|
||||
}, 500, function () {
|
||||
p.attr({
|
||||
path: loop,
|
||||
transform: p.transform() + "t90,0"
|
||||
});
|
||||
});
|
||||
}
|
||||
if (typeof frame == "function") {
|
||||
but.click(anim);
|
||||
} else {
|
||||
anim();
|
||||
}
|
||||
}
|
||||
return frameHandler;
|
||||
}
|
||||
var g = s.g();
|
||||
g.attr({
|
||||
transform: "s.5,.5,0,0"
|
||||
});
|
||||
var str = "",
|
||||
code = document.getElementById("code");
|
||||
var domcodelines = document.querySelectorAll("#codelines li"),
|
||||
codelines = [],
|
||||
replacers = {},
|
||||
lines = [],
|
||||
callback = function (i) {
|
||||
lines = [];
|
||||
for (var j = 1; j <= i; j++) {
|
||||
replacers[j - 1] && lines.pop();
|
||||
lines.push(codelines[j - 1]);
|
||||
}
|
||||
Snap("#svg").clear();
|
||||
str = lines.join("\n");
|
||||
eval(str);
|
||||
code.innerHTML = Prism.highlight(str, Prism.languages.javascript);
|
||||
code.parentNode.scrollTop = code.parentNode.scrollTopMax || 1e9;
|
||||
};
|
||||
for (var i = 0, ii = domcodelines.length; i < ii; i++) {
|
||||
codelines[i] = domcodelines[i].innerHTML;
|
||||
if (domcodelines[i].className == "replace") {
|
||||
replacers[i] = true;
|
||||
}
|
||||
}
|
||||
callback(1);
|
||||
chooser(g, codelines.length)(callback);
|
||||
eve.on("tut.click", function (I) {
|
||||
callback(I + 1);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<ol id="codelines">
|
||||
<li>// Simple dashed pattern on circle with mask
|
||||
var s = Snap("#svg");
|
||||
var bigCircle = s.circle(150, 150, 100).attr({
|
||||
fill: "#bada55",
|
||||
stroke: "#000",
|
||||
strokeWidth: 6
|
||||
});
|
||||
var p = s.path("M110,95,95,110M115,100,100,115").attr({
|
||||
fill: "none",
|
||||
stroke: "#bada55",
|
||||
strokeWidth: 4
|
||||
});
|
||||
var ptrn = p.pattern(100, 100, 10, 10);
|
||||
bigCircle.attr({
|
||||
fill: ptrn
|
||||
});
|
||||
//Here is our circle from the first Snap-bit.
|
||||
</li>
|
||||
<li>//Lets create a masking circle</li>
|
||||
<li>var ring = s.circle(150, 150, 92).attr({
|
||||
fill: "none",
|
||||
stroke: "#fff",
|
||||
strokeWidth: 10
|
||||
});</li>
|
||||
<li>//This looks correct, but only because our background is white</li>
|
||||
<li>s.rect(0, 150, 300, 30).attr({fill: "#85144B"}).insertBefore(bigCircle);
|
||||
//Uh-oh, lets try to apply this ring as a mask:</li>
|
||||
<li>bigCircle.attr({
|
||||
mask: ring
|
||||
});</li>
|
||||
<li>//Not exactly what we want. We need to invert the mask</li>
|
||||
<li>var mask = s.mask();</li>
|
||||
<li>// Background rect:
|
||||
mask.add(s.rect(0, 0, "100%", "100%").attr({fill: "#fff"}));</li>
|
||||
<li>// and our ring, but black
|
||||
mask.add(ring.attr({stroke: "#000"}));</li>
|
||||
<li>bigCircle.attr({
|
||||
mask: mask
|
||||
});</li>
|
||||
<li>//Now, let’s animate the ring:</li>
|
||||
<li>ring.animate({r: 10}, 1e3);</li>
|
||||
|
||||
</ol>
|
||||
<svg id="svg"></svg>
|
||||
<pre class="javascript code"><code data-language="javascript" class="language-javascript" id="code"></code></pre>
|
||||
<svg width="0" height="0">
|
||||
<pattern id="pattern" patternUnits="userSpaceOnUse" x="0" y="0" width="10" height="10" viewBox="0 0 10 10">
|
||||
<path d="M-5,0,10,15M0-5,15,10" stroke="white" stroke-width="5"/>
|
||||
</pattern>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,202 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tutorial</title>
|
||||
<link rel="stylesheet" href="../../doc/fonts/stylesheet.css">
|
||||
<link rel="stylesheet" href="../../doc/css/prism.css">
|
||||
<style media="screen">
|
||||
pre.code {
|
||||
-moz-border-radius: 10px;
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
height: 280px;
|
||||
overflow: auto;
|
||||
background: #181818;
|
||||
border: solid 2px #181818;
|
||||
}
|
||||
#codelines {
|
||||
display: none;
|
||||
}
|
||||
#svg {
|
||||
-moz-border-radius: 10px;
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
border: solid 2px #ccc;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
font: 1em source-sans-pro, Source Sans Pro, Helvetica, sans-serif;
|
||||
}
|
||||
</style>
|
||||
<script src="../../dist/snap.svg-min.js"></script>
|
||||
<script src="../../doc/js/prism.js"></script>
|
||||
<script>
|
||||
var S;
|
||||
window.onload = function () {
|
||||
var s = Snap(850, 35);
|
||||
function chooser(s, count) {
|
||||
var loop = "M35,65a30,30,0,0,0,0-60a30,30,0,0,0,0,60",
|
||||
line = "M35,65a30,30,0,0,0,0-60a30,30,0,0,0,0,60c30,0,60-60,90-60a30,30,0,0,1,0,60a30,30,0,0,1,0-60",
|
||||
l1 = Snap.path.getTotalLength(loop),
|
||||
l2 = Snap.path.getTotalLength(line),
|
||||
cur = 1,
|
||||
p = s.path({
|
||||
path: loop,
|
||||
fill: "none",
|
||||
stroke: "#f00",
|
||||
strokeWidth: 6,
|
||||
strokeLinecap: "round"
|
||||
});
|
||||
for (var i = 1; i <= count; i++) {
|
||||
s.text(90 * i - 55, 49, i).attr({
|
||||
font: "45px source-sans-pro, Source Sans Pro, Helvetica, sans-serif",
|
||||
textAnchor: "middle"
|
||||
});
|
||||
(function (i) {
|
||||
s.circle(90 * i - 55, 35, 40).attr({
|
||||
opacity: 0
|
||||
}).click(eve.f("tut.click", i - 1));
|
||||
}(i));
|
||||
}
|
||||
s.path("M11.166,23.963L22.359,17.5c1.43-0.824,1.43-2.175,0-3L11.166,8.037c-1.429-0.826-2.598-0.15-2.598,1.5v12.926C8.568,24.113,9.737,24.789,11.166,23.963z").transform("t" + (90 * (count + 1) - 68) + ",18s2");
|
||||
var but = s.circle(90 * (count + 1) - 55, 35, 30).attr({
|
||||
fillOpacity: 0,
|
||||
stroke: "#333",
|
||||
strokeWidth: 2
|
||||
});
|
||||
eve.on("tut.click", function (I) {
|
||||
p.attr({
|
||||
path: loop,
|
||||
transform: "t" + (90 * I) + ",0"
|
||||
});
|
||||
cur = I + 1;
|
||||
});
|
||||
function frameHandler(frame) {
|
||||
function anim() {
|
||||
cur++;
|
||||
if (cur > count) {
|
||||
return;
|
||||
}
|
||||
if (typeof frame == "function") {
|
||||
frame(cur);
|
||||
}
|
||||
Snap.animate(0, l2 - l1, function (val) {
|
||||
p.attr({
|
||||
path: Snap.path.getSubpath(line, val, val + l1)
|
||||
});
|
||||
}, 500, function () {
|
||||
p.attr({
|
||||
path: loop,
|
||||
transform: p.transform() + "t90,0"
|
||||
});
|
||||
});
|
||||
}
|
||||
if (typeof frame == "function") {
|
||||
but.click(anim);
|
||||
} else {
|
||||
anim();
|
||||
}
|
||||
}
|
||||
return frameHandler;
|
||||
}
|
||||
var g = s.g();
|
||||
g.attr({
|
||||
transform: "s.5,.5,0,0"
|
||||
});
|
||||
var str = "",
|
||||
code = document.getElementById("code");
|
||||
var domcodelines = document.querySelectorAll("#codelines li"),
|
||||
codelines = [],
|
||||
replacers = {},
|
||||
lines = [],
|
||||
callback = function (i) {
|
||||
lines = [];
|
||||
for (var j = 1; j <= i; j++) {
|
||||
replacers[j - 1] && lines.pop();
|
||||
lines.push(codelines[j - 1]);
|
||||
}
|
||||
Snap("#svg").clear();
|
||||
str = lines.join("\n");
|
||||
eval(str);
|
||||
code.innerHTML = Prism.highlight(str, Prism.languages.javascript);
|
||||
code.parentNode.scrollTop = code.parentNode.scrollTopMax || 1e9;
|
||||
};
|
||||
for (var i = 0, ii = domcodelines.length; i < ii; i++) {
|
||||
codelines[i] = domcodelines[i].innerHTML;
|
||||
if (domcodelines[i].className == "replace") {
|
||||
replacers[i] = true;
|
||||
}
|
||||
}
|
||||
callback(1);
|
||||
chooser(g, codelines.length)(callback);
|
||||
eve.on("tut.click", function (I) {
|
||||
callback(I + 1);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<ol id="codelines">
|
||||
<li>// Simple dashed pattern on circle with mask
|
||||
// Lets connect mask and circle together. Also useful if we have a path
|
||||
// and can’t calculate offset easily.
|
||||
var s = Snap("#svg");
|
||||
// So, lets start with an empty circle.
|
||||
// It’s important that it will not have any attributes set
|
||||
var bigCircle = s.circle(150, 150, 100);</li>
|
||||
<li>//-----------------------------------------------------
|
||||
// Lets use it again for patterned fill
|
||||
var c1 = bigCircle.use();
|
||||
// Create pattern
|
||||
var p = s.path("M110,95,95,110M115,100,100,115").attr({
|
||||
fill: "none",
|
||||
stroke: "#bada55",
|
||||
strokeWidth: 4
|
||||
});
|
||||
var ptrn = p.pattern(100, 100, 10, 10);
|
||||
// and apply some nice attributes
|
||||
c1.attr({
|
||||
fill: ptrn
|
||||
});</li>
|
||||
<li>//-----------------------------------------------------
|
||||
// Lets use it for stroke
|
||||
var c2 = bigCircle.use();
|
||||
c2.attr({
|
||||
fill: "none",
|
||||
stroke: "#000",
|
||||
strokeWidth: 6
|
||||
});</li>
|
||||
<li>// Lets create a masking circle</li>
|
||||
<li>var ring = bigCircle.use();
|
||||
ring.attr({
|
||||
fill: "none",
|
||||
stroke: "#000",
|
||||
strokeWidth: 20 // we need only inner 10px of it
|
||||
});</li>
|
||||
<li>// Hide bigCircle by moving it to <defs>
|
||||
bigCircle.toDefs();</li>
|
||||
<li>var mask = s.mask();</li>
|
||||
<li>// Background rect:
|
||||
mask.add(s.rect(0, 0, "100%", "100%").attr({fill: "#fff"}));</li>
|
||||
<li>// and our ring
|
||||
mask.add(ring);</li>
|
||||
<li>c1.attr({
|
||||
mask: mask
|
||||
});</li>
|
||||
<li>//Now, let’s animate bigCircle:</li>
|
||||
<li>bigCircle.animate({r: 50}, 5e3, mina.elastic);
|
||||
// Despite bigCircle is not visible it affect all 3 “uses” of it.</li>
|
||||
|
||||
</ol>
|
||||
<svg id="svg"></svg>
|
||||
<pre class="javascript code"><code data-language="javascript" class="language-javascript" id="code"></code></pre>
|
||||
<svg width="0" height="0">
|
||||
<pattern id="pattern" patternUnits="userSpaceOnUse" x="0" y="0" width="10" height="10" viewBox="0 0 10 10">
|
||||
<path d="M-5,0,10,15M0-5,15,10" stroke="white" stroke-width="5"/>
|
||||
</pattern>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,180 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tutorial</title>
|
||||
<link rel="stylesheet" href="../../doc/fonts/stylesheet.css">
|
||||
<link rel="stylesheet" href="../../doc/css/prism.css">
|
||||
<style media="screen">
|
||||
pre.code {
|
||||
-moz-border-radius: 10px;
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
height: 280px;
|
||||
overflow: auto;
|
||||
background: #181818;
|
||||
border: solid 2px #181818;
|
||||
}
|
||||
#codelines {
|
||||
display: none;
|
||||
}
|
||||
#svg {
|
||||
-moz-border-radius: 10px;
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
border: solid 2px #ccc;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
font: 1em source-sans-pro, Source Sans Pro, Helvetica, sans-serif;
|
||||
}
|
||||
</style>
|
||||
<script src="../../dist/snap.svg-min.js"></script>
|
||||
<script src="../../doc/js/prism.js"></script>
|
||||
<script>
|
||||
var S;
|
||||
window.onload = function () {
|
||||
var s = Snap(850, 35);
|
||||
function chooser(s, count) {
|
||||
var loop = "M35,65a30,30,0,0,0,0-60a30,30,0,0,0,0,60",
|
||||
line = "M35,65a30,30,0,0,0,0-60a30,30,0,0,0,0,60c30,0,60-60,90-60a30,30,0,0,1,0,60a30,30,0,0,1,0-60",
|
||||
l1 = Snap.path.getTotalLength(loop),
|
||||
l2 = Snap.path.getTotalLength(line),
|
||||
cur = 1,
|
||||
p = s.path({
|
||||
path: loop,
|
||||
fill: "none",
|
||||
stroke: "#f00",
|
||||
strokeWidth: 6,
|
||||
strokeLinecap: "round"
|
||||
});
|
||||
for (var i = 1; i <= count; i++) {
|
||||
s.text(90 * i - 55, 49, i).attr({
|
||||
font: "45px source-sans-pro, Source Sans Pro, Helvetica, sans-serif",
|
||||
textAnchor: "middle"
|
||||
});
|
||||
(function (i) {
|
||||
s.circle(90 * i - 55, 35, 40).attr({
|
||||
opacity: 0
|
||||
}).click(eve.f("tut.click", i - 1));
|
||||
}(i));
|
||||
}
|
||||
s.path("M11.166,23.963L22.359,17.5c1.43-0.824,1.43-2.175,0-3L11.166,8.037c-1.429-0.826-2.598-0.15-2.598,1.5v12.926C8.568,24.113,9.737,24.789,11.166,23.963z").transform("t" + (90 * (count + 1) - 68) + ",18s2");
|
||||
var but = s.circle(90 * (count + 1) - 55, 35, 30).attr({
|
||||
fillOpacity: 0,
|
||||
stroke: "#333",
|
||||
strokeWidth: 2
|
||||
});
|
||||
eve.on("tut.click", function (I) {
|
||||
p.attr({
|
||||
path: loop,
|
||||
transform: "t" + (90 * I) + ",0"
|
||||
});
|
||||
cur = I + 1;
|
||||
});
|
||||
function frameHandler(frame) {
|
||||
function anim() {
|
||||
cur++;
|
||||
if (cur > count) {
|
||||
return;
|
||||
}
|
||||
if (typeof frame == "function") {
|
||||
frame(cur);
|
||||
}
|
||||
Snap.animate(0, l2 - l1, function (val) {
|
||||
p.attr({
|
||||
path: Snap.path.getSubpath(line, val, val + l1)
|
||||
});
|
||||
}, 500, function () {
|
||||
p.attr({
|
||||
path: loop,
|
||||
transform: p.transform() + "t90,0"
|
||||
});
|
||||
});
|
||||
}
|
||||
if (typeof frame == "function") {
|
||||
but.click(anim);
|
||||
} else {
|
||||
anim();
|
||||
}
|
||||
}
|
||||
return frameHandler;
|
||||
}
|
||||
var g = s.g();
|
||||
g.attr({
|
||||
transform: "s.5,.5,0,0"
|
||||
});
|
||||
var str = "",
|
||||
code = document.getElementById("code");
|
||||
var domcodelines = document.querySelectorAll("#codelines li"),
|
||||
codelines = [],
|
||||
replacers = {},
|
||||
lines = [],
|
||||
callback = function (i) {
|
||||
lines = [];
|
||||
for (var j = 1; j <= i; j++) {
|
||||
replacers[j - 1] && lines.pop();
|
||||
lines.push(codelines[j - 1]);
|
||||
}
|
||||
Snap("#svg").clear();
|
||||
str = lines.join("\n");
|
||||
eval(str);
|
||||
code.innerHTML = Prism.highlight(str, Prism.languages.javascript);
|
||||
code.parentNode.scrollTop = code.parentNode.scrollTopMax || 1e9;
|
||||
};
|
||||
for (var i = 0, ii = domcodelines.length; i < ii; i++) {
|
||||
codelines[i] = domcodelines[i].innerHTML;
|
||||
if (domcodelines[i].className == "replace") {
|
||||
replacers[i] = true;
|
||||
}
|
||||
}
|
||||
callback(1);
|
||||
chooser(g, codelines.length)(callback);
|
||||
eve.on("tut.click", function (I) {
|
||||
callback(I + 1);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<ol id="codelines">
|
||||
<li>// Text on the path
|
||||
var s = Snap("#svg");</li>
|
||||
<li>// Setting the background
|
||||
var bg = s.rect(50, 50, 200, 200, 10).attr({fill: "#ccc"});</li>
|
||||
<li>var t = s.text(150, 150, "Test Text").attr({
|
||||
font: "30px Helvetica, sans-serif",
|
||||
textAnchor: "middle",
|
||||
fill: "#ddd"
|
||||
});</li>
|
||||
<li>// Lets create a mask</li>
|
||||
<li>var t2 = t.use().attr({
|
||||
stroke: "#000",
|
||||
strokeWidth: 10,
|
||||
strokeLinecap: "round",
|
||||
strokeLinejoin: "round"
|
||||
});
|
||||
</li>
|
||||
<li>var mask = s.mask();</li>
|
||||
<li>// Background rect:
|
||||
mask.add(s.rect(0, 0, "100%", "100%").attr({fill: "#fff"}));</li>
|
||||
<li>// and our ring
|
||||
mask.add(t2);</li>
|
||||
<li>bg.attr({
|
||||
mask: mask
|
||||
});</li>
|
||||
<li>//Now, let’s animate:</li>
|
||||
<li>t2.animate({strokeWidth: 4}, 5e3, mina.bounce);</li>
|
||||
|
||||
</ol>
|
||||
<svg id="svg"></svg>
|
||||
<pre class="javascript code"><code data-language="javascript" class="language-javascript" id="code"></code></pre>
|
||||
<svg width="0" height="0">
|
||||
<pattern id="pattern" patternUnits="userSpaceOnUse" x="0" y="0" width="10" height="10" viewBox="0 0 10 10">
|
||||
<path d="M-5,0,10,15M0-5,15,10" stroke="white" stroke-width="5"/>
|
||||
</pattern>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -3,8 +3,8 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Tutorial</title>
|
||||
<link rel="stylesheet" href="../../dist/fonts/stylesheet.css">
|
||||
<link rel="stylesheet" href="../../dist/css/prism.css">
|
||||
<link rel="stylesheet" href="../../doc/fonts/stylesheet.css">
|
||||
<link rel="stylesheet" href="../../doc/css/prism.css">
|
||||
<style media="screen">
|
||||
pre.code {
|
||||
-moz-border-radius: 10px;
|
||||
|
@ -32,7 +32,7 @@
|
|||
}
|
||||
</style>
|
||||
<script src="../../dist/snap.svg-min.js"></script>
|
||||
<script src="../../dist/js/prism.js"></script>
|
||||
<script src="../../doc/js/prism.js"></script>
|
||||
<script>
|
||||
var S;
|
||||
window.onload = function () {
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -38,6 +38,10 @@ h5:hover a.dr-sourceline {
|
|||
.dr-type {
|
||||
float: left;
|
||||
}
|
||||
.dr-title {
|
||||
float: left;
|
||||
margin: 0 8px 0 0;
|
||||
}
|
||||
.dr-type em,
|
||||
.dr-returns em,
|
||||
.dr-property em {
|
||||
|
|
3248
doc/reference.html
3248
doc/reference.html
File diff suppressed because it is too large
Load Diff
20
dr.json
20
dr.json
|
@ -4,24 +4,30 @@
|
|||
"template": "template.dot",
|
||||
"files": [{
|
||||
"url": "src/svg.js",
|
||||
"link": "https://github.com/adobe-webplatform/savage/blob/master/src/svg.js"
|
||||
"link": "https://github.com/adobe-webplatform/Snap.svg/blob/master/src/svg.js"
|
||||
}, {
|
||||
"url": "src/matrix.js",
|
||||
"link": "https://github.com/adobe-webplatform/Snap.svg/blob/master/src/matrix.js"
|
||||
}, {
|
||||
"url": "src/paper.js",
|
||||
"link": "https://github.com/adobe-webplatform/Snap.svg/blob/master/src/paper.js"
|
||||
}, {
|
||||
"url": "src/equal.js",
|
||||
"link": "https://github.com/adobe-webplatform/savage/blob/master/src/equal.js"
|
||||
"link": "https://github.com/adobe-webplatform/Snap.svg/blob/master/src/equal.js"
|
||||
}, {
|
||||
"url": "src/mina.js",
|
||||
"link": "https://github.com/adobe-webplatform/savage/blob/master/src/mina.js"
|
||||
"link": "https://github.com/adobe-webplatform/Snap.svg/blob/master/src/mina.js"
|
||||
}, {
|
||||
"url": "src/filter.js",
|
||||
"link": "https://github.com/adobe-webplatform/savage/blob/master/src/filter.js"
|
||||
"link": "https://github.com/adobe-webplatform/Snap.svg/blob/master/src/filter.js"
|
||||
}, {
|
||||
"url": "src/mouse.js",
|
||||
"link": "https://github.com/adobe-webplatform/savage/blob/master/src/mouse.js"
|
||||
"link": "https://github.com/adobe-webplatform/Snap.svg/blob/master/src/mouse.js"
|
||||
}, {
|
||||
"url": "src/path.js",
|
||||
"link": "https://github.com/adobe-webplatform/savage/blob/master/src/path.js"
|
||||
"link": "https://github.com/adobe-webplatform/Snap.svg/blob/master/src/path.js"
|
||||
}, {
|
||||
"url": "src/set.js",
|
||||
"link": "https://github.com/adobe-webplatform/savage/blob/master/src/set.js"
|
||||
"link": "https://github.com/adobe-webplatform/Snap.svg/blob/master/src/set.js"
|
||||
}]
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#0.3.0
|
||||
|
||||
* Added `.addClass()`, `.removeClass()`, `.toggleClass()` and `.hasClass()` APIs
|
||||
* Added `Paper.mask()`, `Paper.ptrn()`, `Paper.use()`, `Paper.svg()`
|
||||
* Mask & pattern elements are sharing paper methods (just like group)
|
||||
* Added `Set.bind()` method
|
||||
* Added syncronisation for `Set.animate()`
|
||||
* Added opacity to the shadow filter
|
||||
* Added ability to specify attributes as `"+=10"` or `"-=1em"` or `"*=2"`
|
||||
* Fix negative scale
|
||||
* Fix for `path2curve`
|
||||
* Fixed shared `<defs>` issue
|
||||
* Various bug fixes
|
||||
|
||||
#0.2.0
|
||||
|
||||
* Added support for text path
|
||||
* Added `getBBox` method to the paper object
|
||||
* Added `Element.appendTo()` and `Element.prependTo()`
|
||||
* Added `getElementByPoint()`
|
||||
* Added `Set.remove()` method
|
||||
* Get rid of internal SVG parser in favor of the browser
|
||||
* Fix for `xlink:href` setting for images
|
||||
* Fix `Element.animate()`
|
||||
* Fix for animate and stroke-dashoffset
|
||||
* Absolute transforms fix
|
||||
* Fix for animation of SVG transformations, matrices and polygon points
|
||||
* Various bug fixes
|
||||
|
||||
#0.1.0
|
||||
* Initial release
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "snapsvg",
|
||||
"version": "0.2.0",
|
||||
"version": "0.3.0",
|
||||
"description": "JavaScript Vector Library",
|
||||
"main": "Gruntfile.js",
|
||||
"repository": {
|
||||
|
@ -16,7 +16,7 @@
|
|||
"grunt-exec": "~0.4.2",
|
||||
"mocha": "*",
|
||||
"expect.js": "*",
|
||||
"eve": "*",
|
||||
"eve": "~0.4.2",
|
||||
"dr.js": "~0.1.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,411 @@
|
|||
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
Snap.plugin(function (Snap, Element, Paper, glob, Fragment) {
|
||||
var has = "hasOwnProperty",
|
||||
make = Snap._.make,
|
||||
wrap = Snap._.wrap,
|
||||
is = Snap.is,
|
||||
getSomeDefs = Snap._.getSomeDefs,
|
||||
reURLValue = /^url\(#?([^)]+)\)$/,
|
||||
$ = Snap._.$,
|
||||
URL = Snap.url,
|
||||
Str = String,
|
||||
separator = Snap._.separator,
|
||||
E = "";
|
||||
// Attributes event handlers
|
||||
eve.on("snap.util.attr.mask", function (value) {
|
||||
if (value instanceof Element || value instanceof Fragment) {
|
||||
eve.stop();
|
||||
if (value instanceof Fragment && value.node.childNodes.length == 1) {
|
||||
value = value.node.firstChild;
|
||||
getSomeDefs(this).appendChild(value);
|
||||
value = wrap(value);
|
||||
}
|
||||
if (value.type == "mask") {
|
||||
var mask = value;
|
||||
} else {
|
||||
mask = make("mask", getSomeDefs(this));
|
||||
mask.node.appendChild(value.node);
|
||||
}
|
||||
!mask.node.id && $(mask.node, {
|
||||
id: mask.id
|
||||
});
|
||||
$(this.node, {
|
||||
mask: URL(mask.id)
|
||||
});
|
||||
}
|
||||
});
|
||||
(function (clipIt) {
|
||||
eve.on("snap.util.attr.clip", clipIt);
|
||||
eve.on("snap.util.attr.clip-path", clipIt);
|
||||
eve.on("snap.util.attr.clipPath", clipIt);
|
||||
}(function (value) {
|
||||
if (value instanceof Element || value instanceof Fragment) {
|
||||
eve.stop();
|
||||
if (value.type == "clipPath") {
|
||||
var clip = value;
|
||||
} else {
|
||||
clip = make("clipPath", getSomeDefs(this));
|
||||
clip.node.appendChild(value.node);
|
||||
!clip.node.id && $(clip.node, {
|
||||
id: clip.id
|
||||
});
|
||||
}
|
||||
$(this.node, {
|
||||
"clip-path": URL(clip.id)
|
||||
});
|
||||
}
|
||||
}));
|
||||
function fillStroke(name) {
|
||||
return function (value) {
|
||||
eve.stop();
|
||||
if (value instanceof Fragment && value.node.childNodes.length == 1 &&
|
||||
(value.node.firstChild.tagName == "radialGradient" ||
|
||||
value.node.firstChild.tagName == "linearGradient" ||
|
||||
value.node.firstChild.tagName == "pattern")) {
|
||||
value = value.node.firstChild;
|
||||
getSomeDefs(this).appendChild(value);
|
||||
value = wrap(value);
|
||||
}
|
||||
if (value instanceof Element) {
|
||||
if (value.type == "radialGradient" || value.type == "linearGradient"
|
||||
|| value.type == "pattern") {
|
||||
if (!value.node.id) {
|
||||
$(value.node, {
|
||||
id: value.id
|
||||
});
|
||||
}
|
||||
var fill = URL(value.node.id);
|
||||
} else {
|
||||
fill = value.attr(name);
|
||||
}
|
||||
} else {
|
||||
fill = Snap.color(value);
|
||||
if (fill.error) {
|
||||
var grad = Snap(getSomeDefs(this).ownerSVGElement).gradient(value);
|
||||
if (grad) {
|
||||
if (!grad.node.id) {
|
||||
$(grad.node, {
|
||||
id: grad.id
|
||||
});
|
||||
}
|
||||
fill = URL(grad.node.id);
|
||||
} else {
|
||||
fill = value;
|
||||
}
|
||||
} else {
|
||||
fill = Str(fill);
|
||||
}
|
||||
}
|
||||
var attrs = {};
|
||||
attrs[name] = fill;
|
||||
$(this.node, attrs);
|
||||
this.node.style[name] = E;
|
||||
};
|
||||
}
|
||||
eve.on("snap.util.attr.fill", fillStroke("fill"));
|
||||
eve.on("snap.util.attr.stroke", fillStroke("stroke"));
|
||||
var gradrg = /^([lr])(?:\(([^)]*)\))?(.*)$/i;
|
||||
eve.on("snap.util.grad.parse", function parseGrad(string) {
|
||||
string = Str(string);
|
||||
var tokens = string.match(gradrg);
|
||||
if (!tokens) {
|
||||
return null;
|
||||
}
|
||||
var type = tokens[1],
|
||||
params = tokens[2],
|
||||
stops = tokens[3];
|
||||
params = params.split(/\s*,\s*/).map(function (el) {
|
||||
return +el == el ? +el : el;
|
||||
});
|
||||
if (params.length == 1 && params[0] == 0) {
|
||||
params = [];
|
||||
}
|
||||
stops = stops.split("-");
|
||||
stops = stops.map(function (el) {
|
||||
el = el.split(":");
|
||||
var out = {
|
||||
color: el[0]
|
||||
};
|
||||
if (el[1]) {
|
||||
out.offset = parseFloat(el[1]);
|
||||
}
|
||||
return out;
|
||||
});
|
||||
return {
|
||||
type: type,
|
||||
params: params,
|
||||
stops: stops
|
||||
};
|
||||
});
|
||||
|
||||
eve.on("snap.util.attr.d", function (value) {
|
||||
eve.stop();
|
||||
if (is(value, "array") && is(value[0], "array")) {
|
||||
value = Snap.path.toString.call(value);
|
||||
}
|
||||
value = Str(value);
|
||||
if (value.match(/[ruo]/i)) {
|
||||
value = Snap.path.toAbsolute(value);
|
||||
}
|
||||
$(this.node, {d: value});
|
||||
})(-1);
|
||||
eve.on("snap.util.attr.#text", function (value) {
|
||||
eve.stop();
|
||||
value = Str(value);
|
||||
var txt = glob.doc.createTextNode(value);
|
||||
while (this.node.firstChild) {
|
||||
this.node.removeChild(this.node.firstChild);
|
||||
}
|
||||
this.node.appendChild(txt);
|
||||
})(-1);
|
||||
eve.on("snap.util.attr.path", function (value) {
|
||||
eve.stop();
|
||||
this.attr({d: value});
|
||||
})(-1);
|
||||
eve.on("snap.util.attr.class", function (value) {
|
||||
eve.stop();
|
||||
this.node.className.baseVal = value;
|
||||
})(-1);
|
||||
eve.on("snap.util.attr.viewBox", function (value) {
|
||||
var vb;
|
||||
if (is(value, "object") && "x" in value) {
|
||||
vb = [value.x, value.y, value.width, value.height].join(" ");
|
||||
} else if (is(value, "array")) {
|
||||
vb = value.join(" ");
|
||||
} else {
|
||||
vb = value;
|
||||
}
|
||||
$(this.node, {
|
||||
viewBox: vb
|
||||
});
|
||||
eve.stop();
|
||||
})(-1);
|
||||
eve.on("snap.util.attr.transform", function (value) {
|
||||
this.transform(value);
|
||||
eve.stop();
|
||||
})(-1);
|
||||
eve.on("snap.util.attr.r", function (value) {
|
||||
if (this.type == "rect") {
|
||||
eve.stop();
|
||||
$(this.node, {
|
||||
rx: value,
|
||||
ry: value
|
||||
});
|
||||
}
|
||||
})(-1);
|
||||
eve.on("snap.util.attr.textpath", function (value) {
|
||||
eve.stop();
|
||||
if (this.type == "text") {
|
||||
var id, tp, node;
|
||||
if (!value && this.textPath) {
|
||||
tp = this.textPath;
|
||||
while (tp.node.firstChild) {
|
||||
this.node.appendChild(tp.node.firstChild);
|
||||
}
|
||||
tp.remove();
|
||||
delete this.textPath;
|
||||
return;
|
||||
}
|
||||
if (is(value, "string")) {
|
||||
var defs = getSomeDefs(this),
|
||||
path = wrap(defs.parentNode).path(value);
|
||||
defs.appendChild(path.node);
|
||||
id = path.id;
|
||||
path.attr({id: id});
|
||||
} else {
|
||||
value = wrap(value);
|
||||
if (value instanceof Element) {
|
||||
id = value.attr("id");
|
||||
if (!id) {
|
||||
id = value.id;
|
||||
value.attr({id: id});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (id) {
|
||||
tp = this.textPath;
|
||||
node = this.node;
|
||||
if (tp) {
|
||||
tp.attr({"xlink:href": "#" + id});
|
||||
} else {
|
||||
tp = $("textPath", {
|
||||
"xlink:href": "#" + id
|
||||
});
|
||||
while (node.firstChild) {
|
||||
tp.appendChild(node.firstChild);
|
||||
}
|
||||
node.appendChild(tp);
|
||||
this.textPath = wrap(tp);
|
||||
}
|
||||
}
|
||||
}
|
||||
})(-1);
|
||||
eve.on("snap.util.attr.text", function (value) {
|
||||
if (this.type == "text") {
|
||||
var i = 0,
|
||||
node = this.node,
|
||||
tuner = function (chunk) {
|
||||
var out = $("tspan");
|
||||
if (is(chunk, "array")) {
|
||||
for (var i = 0; i < chunk.length; i++) {
|
||||
out.appendChild(tuner(chunk[i]));
|
||||
}
|
||||
} else {
|
||||
out.appendChild(glob.doc.createTextNode(chunk));
|
||||
}
|
||||
out.normalize && out.normalize();
|
||||
return out;
|
||||
};
|
||||
while (node.firstChild) {
|
||||
node.removeChild(node.firstChild);
|
||||
}
|
||||
var tuned = tuner(value);
|
||||
while (tuned.firstChild) {
|
||||
node.appendChild(tuned.firstChild);
|
||||
}
|
||||
}
|
||||
eve.stop();
|
||||
})(-1);
|
||||
function setFontSize(value) {
|
||||
eve.stop();
|
||||
if (value == +value) {
|
||||
value += "px";
|
||||
}
|
||||
this.node.style.fontSize = value;
|
||||
}
|
||||
eve.on("snap.util.attr.fontSize", setFontSize)(-1);
|
||||
eve.on("snap.util.attr.font-size", setFontSize)(-1);
|
||||
|
||||
|
||||
eve.on("snap.util.getattr.transform", function () {
|
||||
eve.stop();
|
||||
return this.transform();
|
||||
})(-1);
|
||||
eve.on("snap.util.getattr.textpath", function () {
|
||||
eve.stop();
|
||||
return this.textPath;
|
||||
})(-1);
|
||||
// Markers
|
||||
(function () {
|
||||
function getter(end) {
|
||||
return function () {
|
||||
eve.stop();
|
||||
var style = glob.doc.defaultView.getComputedStyle(this.node, null).getPropertyValue("marker-" + end);
|
||||
if (style == "none") {
|
||||
return style;
|
||||
} else {
|
||||
return Snap(glob.doc.getElementById(style.match(reURLValue)[1]));
|
||||
}
|
||||
};
|
||||
}
|
||||
function setter(end) {
|
||||
return function (value) {
|
||||
eve.stop();
|
||||
var name = "marker" + end.charAt(0).toUpperCase() + end.substring(1);
|
||||
if (value == "" || !value) {
|
||||
this.node.style[name] = "none";
|
||||
return;
|
||||
}
|
||||
if (value.type == "marker") {
|
||||
var id = value.node.id;
|
||||
if (!id) {
|
||||
$(value.node, {id: value.id});
|
||||
}
|
||||
this.node.style[name] = URL(id);
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
eve.on("snap.util.getattr.marker-end", getter("end"))(-1);
|
||||
eve.on("snap.util.getattr.markerEnd", getter("end"))(-1);
|
||||
eve.on("snap.util.getattr.marker-start", getter("start"))(-1);
|
||||
eve.on("snap.util.getattr.markerStart", getter("start"))(-1);
|
||||
eve.on("snap.util.getattr.marker-mid", getter("mid"))(-1);
|
||||
eve.on("snap.util.getattr.markerMid", getter("mid"))(-1);
|
||||
eve.on("snap.util.attr.marker-end", setter("end"))(-1);
|
||||
eve.on("snap.util.attr.markerEnd", setter("end"))(-1);
|
||||
eve.on("snap.util.attr.marker-start", setter("start"))(-1);
|
||||
eve.on("snap.util.attr.markerStart", setter("start"))(-1);
|
||||
eve.on("snap.util.attr.marker-mid", setter("mid"))(-1);
|
||||
eve.on("snap.util.attr.markerMid", setter("mid"))(-1);
|
||||
}());
|
||||
eve.on("snap.util.getattr.r", function () {
|
||||
if (this.type == "rect" && $(this.node, "rx") == $(this.node, "ry")) {
|
||||
eve.stop();
|
||||
return $(this.node, "rx");
|
||||
}
|
||||
})(-1);
|
||||
function textExtract(node) {
|
||||
var out = [];
|
||||
var children = node.childNodes;
|
||||
for (var i = 0, ii = children.length; i < ii; i++) {
|
||||
var chi = children[i];
|
||||
if (chi.nodeType == 3) {
|
||||
out.push(chi.nodeValue);
|
||||
}
|
||||
if (chi.tagName == "tspan") {
|
||||
if (chi.childNodes.length == 1 && chi.firstChild.nodeType == 3) {
|
||||
out.push(chi.firstChild.nodeValue);
|
||||
} else {
|
||||
out.push(textExtract(chi));
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
eve.on("snap.util.getattr.text", function () {
|
||||
if (this.type == "text" || this.type == "tspan") {
|
||||
eve.stop();
|
||||
var out = textExtract(this.node);
|
||||
return out.length == 1 ? out[0] : out;
|
||||
}
|
||||
})(-1);
|
||||
eve.on("snap.util.getattr.#text", function () {
|
||||
return this.node.textContent;
|
||||
})(-1);
|
||||
eve.on("snap.util.getattr.viewBox", function () {
|
||||
eve.stop();
|
||||
var vb = $(this.node, "viewBox");
|
||||
if (vb) {
|
||||
vb = vb.split(separator);
|
||||
return Snap._.box(+vb[0], +vb[1], +vb[2], +vb[3]);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
})(-1);
|
||||
eve.on("snap.util.getattr.points", function () {
|
||||
var p = $(this.node, "points");
|
||||
eve.stop();
|
||||
if (p) {
|
||||
return p.split(separator);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
})(-1);
|
||||
eve.on("snap.util.getattr.path", function () {
|
||||
var p = $(this.node, "d");
|
||||
eve.stop();
|
||||
return p;
|
||||
})(-1);
|
||||
eve.on("snap.util.getattr.class", function () {
|
||||
return this.node.className.baseVal;
|
||||
})(-1);
|
||||
function getFontSize() {
|
||||
eve.stop();
|
||||
return this.node.style.fontSize;
|
||||
}
|
||||
eve.on("snap.util.getattr.fontSize", getFontSize)(-1);
|
||||
eve.on("snap.util.getattr.font-size", getFontSize)(-1);
|
||||
});
|
|
@ -0,0 +1,89 @@
|
|||
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
Snap.plugin(function (Snap, Element, Paper, glob, Fragment) {
|
||||
var operators = {
|
||||
"+": function (x, y) {
|
||||
return x + y;
|
||||
},
|
||||
"-": function (x, y) {
|
||||
return x - y;
|
||||
},
|
||||
"/": function (x, y) {
|
||||
return x / y;
|
||||
},
|
||||
"*": function (x, y) {
|
||||
return x * y;
|
||||
}
|
||||
},
|
||||
Str = String,
|
||||
reUnit = /[a-z]+$/i,
|
||||
reAddon = /^\s*([+\-\/*])\s*=\s*([\d.eE+\-]+)\s*([^\d\s]+)?\s*$/;
|
||||
function getNumber(val) {
|
||||
return val;
|
||||
}
|
||||
function getUnit(unit) {
|
||||
return function (val) {
|
||||
return +val.toFixed(3) + unit;
|
||||
};
|
||||
}
|
||||
eve.on("snap.util.attr", function (val) {
|
||||
var plus = Str(val).match(reAddon);
|
||||
if (plus) {
|
||||
var evnt = eve.nt(),
|
||||
name = evnt.substring(evnt.lastIndexOf(".") + 1),
|
||||
a = this.attr(name),
|
||||
atr = {};
|
||||
eve.stop();
|
||||
var unit = plus[3] || "",
|
||||
aUnit = a.match(reUnit),
|
||||
op = operators[plus[1]];
|
||||
if (aUnit && aUnit == unit) {
|
||||
val = op(parseFloat(a), +plus[2]);
|
||||
} else {
|
||||
a = this.asPX(name);
|
||||
val = op(this.asPX(name), this.asPX(name, plus[2] + unit));
|
||||
}
|
||||
if (isNaN(a) || isNaN(val)) {
|
||||
return;
|
||||
}
|
||||
atr[name] = val;
|
||||
this.attr(atr);
|
||||
}
|
||||
})(-10);
|
||||
eve.on("snap.util.equal", function (name, b) {
|
||||
var A, B, a = Str(this.attr(name) || ""),
|
||||
el = this,
|
||||
bplus = Str(b).match(reAddon);
|
||||
if (bplus) {
|
||||
eve.stop();
|
||||
var unit = bplus[3] || "",
|
||||
aUnit = a.match(reUnit),
|
||||
op = operators[bplus[1]];
|
||||
if (aUnit && aUnit == unit) {
|
||||
return {
|
||||
from: parseFloat(a),
|
||||
to: op(parseFloat(a), +bplus[2]),
|
||||
f: getUnit(aUnit)
|
||||
};
|
||||
} else {
|
||||
a = this.asPX(name);
|
||||
return {
|
||||
from: a,
|
||||
to: op(a, this.asPX(name, bplus[2] + unit)),
|
||||
f: getNumber
|
||||
};
|
||||
}
|
||||
}
|
||||
})(-10);
|
||||
});
|
13
src/equal.js
13
src/equal.js
|
@ -104,6 +104,9 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
return out;
|
||||
}
|
||||
Element.prototype.equal = function (name, b) {
|
||||
return eve("snap.util.equal", this, name, b).firstDefined();
|
||||
};
|
||||
eve.on("snap.util.equal", function (name, b) {
|
||||
var A, B, a = Str(this.attr(name) || ""),
|
||||
el = this;
|
||||
if (a == +a && b == +b) {
|
||||
|
@ -142,16 +145,16 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
};
|
||||
}
|
||||
if (name == "points") {
|
||||
A = Str(a).split(",");
|
||||
B = Str(b).split(",");
|
||||
A = Str(a).split(Snap._.separator);
|
||||
B = Str(b).split(Snap._.separator);
|
||||
return {
|
||||
from: A,
|
||||
to: B,
|
||||
f: function (val) { return val; }
|
||||
};
|
||||
}
|
||||
var aUnit = a.match(reUnit),
|
||||
bUnit = Str(b).match(reUnit);
|
||||
aUnit = a.match(reUnit);
|
||||
var bUnit = Str(b).match(reUnit);
|
||||
if (aUnit && aUnit == bUnit) {
|
||||
return {
|
||||
from: parseFloat(a),
|
||||
|
@ -165,5 +168,5 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
f: getNumber
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
|
@ -111,10 +111,20 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
**
|
||||
* Returns an SVG markup string for the shadow filter
|
||||
**
|
||||
- dx (number) horizontal shift of the shadow, in pixels
|
||||
- dy (number) vertical shift of the shadow, in pixels
|
||||
- dx (number) #optional horizontal shift of the shadow, in pixels
|
||||
- dy (number) #optional vertical shift of the shadow, in pixels
|
||||
- blur (number) #optional amount of blur
|
||||
- color (string) #optional color of the shadow
|
||||
- opacity (number) #optional `0..1` opacity of the shadow
|
||||
* or
|
||||
- dx (number) #optional horizontal shift of the shadow, in pixels
|
||||
- dy (number) #optional vertical shift of the shadow, in pixels
|
||||
- color (string) #optional color of the shadow
|
||||
- opacity (number) #optional `0..1` opacity of the shadow
|
||||
* which makes blur default to `4`. Or
|
||||
- dx (number) #optional horizontal shift of the shadow, in pixels
|
||||
- dy (number) #optional vertical shift of the shadow, in pixels
|
||||
- opacity (number) #optional `0..1` opacity of the shadow
|
||||
= (string) filter representation
|
||||
> Usage
|
||||
| var f = paper.filter(Snap.filter.shadow(0, 2, 3)),
|
||||
|
@ -122,14 +132,22 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
| filter: f
|
||||
| });
|
||||
\*/
|
||||
Snap.filter.shadow = function (dx, dy, blur, color) {
|
||||
Snap.filter.shadow = function (dx, dy, blur, color, opacity) {
|
||||
if (typeof blur == "string") {
|
||||
color = blur;
|
||||
opacity = color;
|
||||
blur = 4;
|
||||
}
|
||||
if (typeof color != "string") {
|
||||
opacity = color;
|
||||
color = "#000";
|
||||
}
|
||||
color = color || "#000";
|
||||
if (blur == null) {
|
||||
blur = 4;
|
||||
}
|
||||
if (typeof blur == "string") {
|
||||
color = blur;
|
||||
blur = 4;
|
||||
if (opacity == null) {
|
||||
opacity = 1;
|
||||
}
|
||||
if (dx == null) {
|
||||
dx = 0;
|
||||
|
@ -139,11 +157,12 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
dy = dx;
|
||||
}
|
||||
color = Snap.color(color);
|
||||
return Snap.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 Snap.format('<feGaussianBlur in="SourceAlpha" stdDeviation="{blur}"/><feOffset dx="{dx}" dy="{dy}" result="offsetblur"/><feFlood flood-color="{color}"/><feComposite in2="offsetblur" operator="in"/><feComponentTransfer><feFuncA type="linear" slope="{opacity}"/></feComponentTransfer><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>', {
|
||||
color: color,
|
||||
dx: dx,
|
||||
dy: dy,
|
||||
blur: blur
|
||||
blur: blur,
|
||||
opacity: opacity
|
||||
});
|
||||
};
|
||||
Snap.filter.shadow.toString = function () {
|
||||
|
|
|
@ -0,0 +1,309 @@
|
|||
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
Snap.plugin(function (Snap, Element, Paper, glob, Fragment) {
|
||||
var objectToString = Object.prototype.toString,
|
||||
Str = String,
|
||||
math = Math,
|
||||
E = "";
|
||||
function Matrix(a, b, c, d, e, f) {
|
||||
if (b == null && objectToString.call(a) == "[object SVGMatrix]") {
|
||||
this.a = a.a;
|
||||
this.b = a.b;
|
||||
this.c = a.c;
|
||||
this.d = a.d;
|
||||
this.e = a.e;
|
||||
this.f = a.f;
|
||||
return;
|
||||
}
|
||||
if (a != null) {
|
||||
this.a = +a;
|
||||
this.b = +b;
|
||||
this.c = +c;
|
||||
this.d = +d;
|
||||
this.e = +e;
|
||||
this.f = +f;
|
||||
} else {
|
||||
this.a = 1;
|
||||
this.b = 0;
|
||||
this.c = 0;
|
||||
this.d = 1;
|
||||
this.e = 0;
|
||||
this.f = 0;
|
||||
}
|
||||
}
|
||||
(function (matrixproto) {
|
||||
/*\
|
||||
* Matrix.add
|
||||
[ method ]
|
||||
**
|
||||
* Adds the given matrix to existing one
|
||||
- a (number)
|
||||
- b (number)
|
||||
- c (number)
|
||||
- d (number)
|
||||
- e (number)
|
||||
- f (number)
|
||||
* or
|
||||
- matrix (object) @Matrix
|
||||
\*/
|
||||
matrixproto.add = function (a, b, c, d, e, f) {
|
||||
var out = [[], [], []],
|
||||
m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]],
|
||||
matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
|
||||
x, y, z, res;
|
||||
|
||||
if (a && a instanceof Matrix) {
|
||||
matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]];
|
||||
}
|
||||
|
||||
for (x = 0; x < 3; x++) {
|
||||
for (y = 0; y < 3; y++) {
|
||||
res = 0;
|
||||
for (z = 0; z < 3; z++) {
|
||||
res += m[x][z] * matrix[z][y];
|
||||
}
|
||||
out[x][y] = res;
|
||||
}
|
||||
}
|
||||
this.a = out[0][0];
|
||||
this.b = out[1][0];
|
||||
this.c = out[0][1];
|
||||
this.d = out[1][1];
|
||||
this.e = out[0][2];
|
||||
this.f = out[1][2];
|
||||
return this;
|
||||
};
|
||||
/*\
|
||||
* Matrix.invert
|
||||
[ method ]
|
||||
**
|
||||
* Returns an inverted version of the matrix
|
||||
= (object) @Matrix
|
||||
\*/
|
||||
matrixproto.invert = function () {
|
||||
var me = this,
|
||||
x = me.a * me.d - me.b * me.c;
|
||||
return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x);
|
||||
};
|
||||
/*\
|
||||
* Matrix.clone
|
||||
[ method ]
|
||||
**
|
||||
* Returns a copy of the matrix
|
||||
= (object) @Matrix
|
||||
\*/
|
||||
matrixproto.clone = function () {
|
||||
return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f);
|
||||
};
|
||||
/*\
|
||||
* Matrix.translate
|
||||
[ method ]
|
||||
**
|
||||
* Translate the matrix
|
||||
- x (number) horizontal offset distance
|
||||
- y (number) vertical offset distance
|
||||
\*/
|
||||
matrixproto.translate = function (x, y) {
|
||||
return this.add(1, 0, 0, 1, x, y);
|
||||
};
|
||||
/*\
|
||||
* Matrix.scale
|
||||
[ method ]
|
||||
**
|
||||
* Scales the matrix
|
||||
- x (number) amount to be scaled, with `1` resulting in no change
|
||||
- y (number) #optional amount to scale along the vertical axis. (Otherwise `x` applies to both axes.)
|
||||
- cx (number) #optional horizontal origin point from which to scale
|
||||
- cy (number) #optional vertical origin point from which to scale
|
||||
* Default cx, cy is the middle point of the element.
|
||||
\*/
|
||||
matrixproto.scale = function (x, y, cx, cy) {
|
||||
y == null && (y = x);
|
||||
(cx || cy) && this.add(1, 0, 0, 1, cx, cy);
|
||||
this.add(x, 0, 0, y, 0, 0);
|
||||
(cx || cy) && this.add(1, 0, 0, 1, -cx, -cy);
|
||||
return this;
|
||||
};
|
||||
/*\
|
||||
* Matrix.rotate
|
||||
[ method ]
|
||||
**
|
||||
* Rotates the matrix
|
||||
- a (number) angle of rotation, in degrees
|
||||
- x (number) horizontal origin point from which to rotate
|
||||
- y (number) vertical origin point from which to rotate
|
||||
\*/
|
||||
matrixproto.rotate = function (a, x, y) {
|
||||
a = Snap.rad(a);
|
||||
x = x || 0;
|
||||
y = y || 0;
|
||||
var cos = +math.cos(a).toFixed(9),
|
||||
sin = +math.sin(a).toFixed(9);
|
||||
this.add(cos, sin, -sin, cos, x, y);
|
||||
return this.add(1, 0, 0, 1, -x, -y);
|
||||
};
|
||||
/*\
|
||||
* Matrix.x
|
||||
[ method ]
|
||||
**
|
||||
* Returns x coordinate for given point after transformation described by the matrix. See also @Matrix.y
|
||||
- x (number)
|
||||
- y (number)
|
||||
= (number) x
|
||||
\*/
|
||||
matrixproto.x = function (x, y) {
|
||||
return x * this.a + y * this.c + this.e;
|
||||
};
|
||||
/*\
|
||||
* Matrix.y
|
||||
[ method ]
|
||||
**
|
||||
* Returns y coordinate for given point after transformation described by the matrix. See also @Matrix.x
|
||||
- x (number)
|
||||
- y (number)
|
||||
= (number) y
|
||||
\*/
|
||||
matrixproto.y = function (x, y) {
|
||||
return x * this.b + y * this.d + this.f;
|
||||
};
|
||||
matrixproto.get = function (i) {
|
||||
return +this[Str.fromCharCode(97 + i)].toFixed(4);
|
||||
};
|
||||
matrixproto.toString = function () {
|
||||
return "matrix(" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + ")";
|
||||
};
|
||||
matrixproto.offset = function () {
|
||||
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] && (a[0] /= mag);
|
||||
a[1] && (a[1] /= mag);
|
||||
}
|
||||
/*\
|
||||
* Matrix.determinant
|
||||
[ method ]
|
||||
**
|
||||
* Finds determinant of the given matrix.
|
||||
= (number) determinant
|
||||
\*/
|
||||
matrixproto.determinant = function () {
|
||||
return this.a * this.d - this.b * this.c;
|
||||
};
|
||||
/*\
|
||||
* Matrix.split
|
||||
[ method ]
|
||||
**
|
||||
* Splits matrix into primitive transformations
|
||||
= (object) in format:
|
||||
o dx (number) translation by x
|
||||
o dy (number) translation by y
|
||||
o scalex (number) scale by x
|
||||
o scaley (number) scale by y
|
||||
o shear (number) shear
|
||||
o rotate (number) rotation in deg
|
||||
o isSimple (boolean) could it be represented via simple transformations
|
||||
\*/
|
||||
matrixproto.split = function () {
|
||||
var out = {};
|
||||
// translation
|
||||
out.dx = this.e;
|
||||
out.dy = this.f;
|
||||
|
||||
// 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;
|
||||
|
||||
if (this.determinant() < 0) {
|
||||
out.scalex = -out.scalex;
|
||||
}
|
||||
|
||||
// rotation
|
||||
var sin = -row[0][1],
|
||||
cos = row[1][1];
|
||||
if (cos < 0) {
|
||||
out.rotate = Snap.deg(math.acos(cos));
|
||||
if (sin < 0) {
|
||||
out.rotate = 360 - out.rotate;
|
||||
}
|
||||
} else {
|
||||
out.rotate = Snap.deg(math.asin(sin));
|
||||
}
|
||||
|
||||
out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate);
|
||||
out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate;
|
||||
out.noRotation = !+out.shear.toFixed(9) && !out.rotate;
|
||||
return out;
|
||||
};
|
||||
/*\
|
||||
* Matrix.toTransformString
|
||||
[ method ]
|
||||
**
|
||||
* Returns transform string that represents given matrix
|
||||
= (string) transform string
|
||||
\*/
|
||||
matrixproto.toTransformString = function (shorter) {
|
||||
var s = shorter || this.split();
|
||||
if (!+s.shear.toFixed(9)) {
|
||||
s.scalex = +s.scalex.toFixed(4);
|
||||
s.scaley = +s.scaley.toFixed(4);
|
||||
s.rotate = +s.rotate.toFixed(4);
|
||||
return (s.dx || s.dy ? "t" + [+s.dx.toFixed(4), +s.dy.toFixed(4)] : E) +
|
||||
(s.scalex != 1 || s.scaley != 1 ? "s" + [s.scalex, s.scaley, 0, 0] : E) +
|
||||
(s.rotate ? "r" + [+s.rotate.toFixed(4), 0, 0] : E);
|
||||
} else {
|
||||
return "m" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)];
|
||||
}
|
||||
};
|
||||
})(Matrix.prototype);
|
||||
/*\
|
||||
* Snap.Matrix
|
||||
[ method ]
|
||||
**
|
||||
* Matrix constructor, extend on your own risk.
|
||||
* To create matrices use @Snap.matrix.
|
||||
\*/
|
||||
Snap.Matrix = Matrix;
|
||||
/*\
|
||||
* Snap.matrix
|
||||
[ method ]
|
||||
**
|
||||
* Utility method
|
||||
**
|
||||
* Returns a matrix based on the given parameters
|
||||
- a (number)
|
||||
- b (number)
|
||||
- c (number)
|
||||
- d (number)
|
||||
- e (number)
|
||||
- f (number)
|
||||
* or
|
||||
- svgMatrix (SVGMatrix)
|
||||
= (object) @Matrix
|
||||
\*/
|
||||
Snap.matrix = function (a, b, c, d, e, f) {
|
||||
return new Matrix(a, b, c, d, e, f);
|
||||
};
|
||||
});
|
34
src/mina.js
34
src/mina.js
|
@ -74,6 +74,7 @@ var mina = (function (eve) {
|
|||
stopit = function () {
|
||||
var a = this;
|
||||
delete animations[a.id];
|
||||
a.update();
|
||||
eve("mina.stop." + a.id, a);
|
||||
},
|
||||
pause = function () {
|
||||
|
@ -82,6 +83,7 @@ var mina = (function (eve) {
|
|||
return;
|
||||
}
|
||||
delete animations[a.id];
|
||||
a.update();
|
||||
a.pdif = a.get() - a.b;
|
||||
},
|
||||
resume = function () {
|
||||
|
@ -93,6 +95,20 @@ var mina = (function (eve) {
|
|||
delete a.pdif;
|
||||
animations[a.id] = a;
|
||||
},
|
||||
update = function () {
|
||||
var a = this,
|
||||
res;
|
||||
if (isArray(a.start)) {
|
||||
res = [];
|
||||
for (var j = 0, jj = a.start.length; j < jj; j++) {
|
||||
res[j] = +a.start[j] +
|
||||
(a.end[j] - a.start[j]) * a.easing(a.s);
|
||||
}
|
||||
} else {
|
||||
res = +a.start + (a.end - a.start) * a.easing(a.s);
|
||||
}
|
||||
a.set(res);
|
||||
},
|
||||
frame = function () {
|
||||
var len = 0;
|
||||
for (var i in animations) if (animations.hasOwnProperty(i)) {
|
||||
|
@ -111,20 +127,10 @@ var mina = (function (eve) {
|
|||
});
|
||||
}(a));
|
||||
}
|
||||
if (isArray(a.start)) {
|
||||
res = [];
|
||||
for (var j = 0, jj = a.start.length; j < jj; j++) {
|
||||
res[j] = +a.start[j] +
|
||||
(a.end[j] - a.start[j]) * a.easing(a.s);
|
||||
}
|
||||
} else {
|
||||
res = +a.start + (a.end - a.start) * a.easing(a.s);
|
||||
}
|
||||
a.set(res);
|
||||
a.update();
|
||||
}
|
||||
len && requestAnimFrame(frame);
|
||||
},
|
||||
// SIERRA Unfamiliar with the word _slave_ in this context. Also, I don't know what _gereal_ means. Do you mean _general_?
|
||||
/*\
|
||||
* mina
|
||||
[ method ]
|
||||
|
@ -154,6 +160,9 @@ var mina = (function (eve) {
|
|||
o speed (function) speed getter/setter,
|
||||
o duration (function) duration getter/setter,
|
||||
o stop (function) animation stopper
|
||||
o pause (function) pauses the animation
|
||||
o resume (function) resumes the animation
|
||||
o update (function) calles setter with the right value of the animation
|
||||
o }
|
||||
\*/
|
||||
mina = function (a, A, b, B, get, set, easing) {
|
||||
|
@ -173,7 +182,8 @@ var mina = (function (eve) {
|
|||
duration: duration,
|
||||
stop: stopit,
|
||||
pause: pause,
|
||||
resume: resume
|
||||
resume: resume,
|
||||
update: update
|
||||
};
|
||||
animations[anim.id] = anim;
|
||||
var len = 0, i;
|
||||
|
|
20
src/mouse.js
20
src/mouse.js
|
@ -25,9 +25,10 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
mousemove: "touchmove",
|
||||
mouseup: "touchend"
|
||||
},
|
||||
getScroll = function (xy) {
|
||||
var name = xy == "y" ? "scrollTop" : "scrollLeft";
|
||||
return glob.doc.documentElement[name] || glob.doc.body[name];
|
||||
getScroll = function (xy, el) {
|
||||
var name = xy == "y" ? "scrollTop" : "scrollLeft",
|
||||
doc = el && el.node ? el.node.ownerDocument : glob.doc;
|
||||
return doc[name in doc.documentElement ? "documentElement" : "body"][name];
|
||||
},
|
||||
preventDefault = function () {
|
||||
this.returnValue = false;
|
||||
|
@ -46,8 +47,8 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
return function (obj, type, fn, element) {
|
||||
var realName = supportsTouch && touchMap[type] ? touchMap[type] : type,
|
||||
f = function (e) {
|
||||
var scrollY = getScroll("y"),
|
||||
scrollX = getScroll("x");
|
||||
var scrollY = getScroll("y", element),
|
||||
scrollX = getScroll("x", element);
|
||||
if (supportsTouch && touchMap[has](type)) {
|
||||
for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) {
|
||||
if (e.targetTouches[i].target == obj || obj.contains(e.targetTouches[i].target)) {
|
||||
|
@ -83,9 +84,9 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
} else if (glob.doc.attachEvent) {
|
||||
return function (obj, type, fn, element) {
|
||||
var f = function (e) {
|
||||
e = e || glob.win.event;
|
||||
var scrollY = getScroll("y"),
|
||||
scrollX = getScroll("x"),
|
||||
e = e || element.node.ownerDocument.window.event;
|
||||
var scrollY = getScroll("y", element),
|
||||
scrollX = getScroll("x", element),
|
||||
x = e.clientX + scrollX,
|
||||
y = e.clientY + scrollY;
|
||||
e.preventDefault = e.preventDefault || preventDefault;
|
||||
|
@ -128,7 +129,6 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
}
|
||||
var node = dragi.el.node,
|
||||
o,
|
||||
glob = Snap._.glob,
|
||||
next = node.nextSibling,
|
||||
parent = node.parentNode,
|
||||
display = node.style.display;
|
||||
|
@ -348,7 +348,7 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
this.events.push({
|
||||
name: eventName,
|
||||
f: fn,
|
||||
unbind: addEvent(this.shape || this.node || glob.doc, eventName, fn, scope || this)
|
||||
unbind: addEvent(this.node || document, eventName, fn, scope || this)
|
||||
});
|
||||
}
|
||||
return this;
|
||||
|
|
|
@ -0,0 +1,686 @@
|
|||
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
Snap.plugin(function (Snap, Element, Paper, glob, Fragment) {
|
||||
var proto = Paper.prototype,
|
||||
is = Snap.is;
|
||||
/*\
|
||||
* Paper.rect
|
||||
[ method ]
|
||||
*
|
||||
* Draws a rectangle
|
||||
**
|
||||
- x (number) x coordinate of the top left corner
|
||||
- y (number) y coordinate of the top left corner
|
||||
- width (number) width
|
||||
- height (number) height
|
||||
- rx (number) #optional horizontal radius for rounded corners, default is 0
|
||||
- ry (number) #optional vertical radius for rounded corners, default is rx or 0
|
||||
= (object) the `rect` element
|
||||
**
|
||||
> Usage
|
||||
| // regular rectangle
|
||||
| var c = paper.rect(10, 10, 50, 50);
|
||||
| // rectangle with rounded corners
|
||||
| var c = paper.rect(40, 40, 50, 50, 10);
|
||||
\*/
|
||||
proto.rect = function (x, y, w, h, rx, ry) {
|
||||
var attr;
|
||||
if (ry == null) {
|
||||
ry = rx;
|
||||
}
|
||||
if (is(x, "object") && x == "[object Object]") {
|
||||
attr = x;
|
||||
} else if (x != null) {
|
||||
attr = {
|
||||
x: x,
|
||||
y: y,
|
||||
width: w,
|
||||
height: h
|
||||
};
|
||||
if (rx != null) {
|
||||
attr.rx = rx;
|
||||
attr.ry = ry;
|
||||
}
|
||||
}
|
||||
return this.el("rect", attr);
|
||||
};
|
||||
/*\
|
||||
* Paper.circle
|
||||
[ method ]
|
||||
**
|
||||
* Draws a circle
|
||||
**
|
||||
- x (number) x coordinate of the centre
|
||||
- y (number) y coordinate of the centre
|
||||
- r (number) radius
|
||||
= (object) the `circle` element
|
||||
**
|
||||
> Usage
|
||||
| var c = paper.circle(50, 50, 40);
|
||||
\*/
|
||||
proto.circle = function (cx, cy, r) {
|
||||
var attr;
|
||||
if (is(cx, "object") && cx == "[object Object]") {
|
||||
attr = cx;
|
||||
} else if (cx != null) {
|
||||
attr = {
|
||||
cx: cx,
|
||||
cy: cy,
|
||||
r: r
|
||||
};
|
||||
}
|
||||
return this.el("circle", attr);
|
||||
};
|
||||
|
||||
var preload = (function () {
|
||||
function onerror() {
|
||||
this.parentNode.removeChild(this);
|
||||
}
|
||||
return function (src, f) {
|
||||
var img = glob.doc.createElement("img"),
|
||||
body = glob.doc.body;
|
||||
img.style.cssText = "position:absolute;left:-9999em;top:-9999em";
|
||||
img.onload = function () {
|
||||
f.call(img);
|
||||
img.onload = img.onerror = null;
|
||||
body.removeChild(img);
|
||||
};
|
||||
img.onerror = onerror;
|
||||
body.appendChild(img);
|
||||
img.src = src;
|
||||
};
|
||||
}());
|
||||
|
||||
/*\
|
||||
* Paper.image
|
||||
[ method ]
|
||||
**
|
||||
* Places an image on the surface
|
||||
**
|
||||
- src (string) URI of the source image
|
||||
- x (number) x offset position
|
||||
- y (number) y offset position
|
||||
- width (number) width of the image
|
||||
- height (number) height of the image
|
||||
= (object) the `image` element
|
||||
* or
|
||||
= (object) Snap element object with type `image`
|
||||
**
|
||||
> Usage
|
||||
| var c = paper.image("apple.png", 10, 10, 80, 80);
|
||||
\*/
|
||||
proto.image = function (src, x, y, width, height) {
|
||||
var el = this.el("image");
|
||||
if (is(src, "object") && "src" in src) {
|
||||
el.attr(src);
|
||||
} else if (src != null) {
|
||||
var set = {
|
||||
"xlink:href": src,
|
||||
preserveAspectRatio: "none"
|
||||
};
|
||||
if (x != null && y != null) {
|
||||
set.x = x;
|
||||
set.y = y;
|
||||
}
|
||||
if (width != null && height != null) {
|
||||
set.width = width;
|
||||
set.height = height;
|
||||
} else {
|
||||
preload(src, function () {
|
||||
Snap._.$(el.node, {
|
||||
width: this.offsetWidth,
|
||||
height: this.offsetHeight
|
||||
});
|
||||
});
|
||||
}
|
||||
Snap._.$(el.node, set);
|
||||
}
|
||||
return el;
|
||||
};
|
||||
/*\
|
||||
* Paper.ellipse
|
||||
[ method ]
|
||||
**
|
||||
* Draws an ellipse
|
||||
**
|
||||
- x (number) x coordinate of the centre
|
||||
- y (number) y coordinate of the centre
|
||||
- rx (number) horizontal radius
|
||||
- ry (number) vertical radius
|
||||
= (object) the `ellipse` element
|
||||
**
|
||||
> Usage
|
||||
| var c = paper.ellipse(50, 50, 40, 20);
|
||||
\*/
|
||||
proto.ellipse = function (cx, cy, rx, ry) {
|
||||
var attr;
|
||||
if (is(cx, "object") && cx == "[object Object]") {
|
||||
attr = cx;
|
||||
} else if (cx != null) {
|
||||
attr ={
|
||||
cx: cx,
|
||||
cy: cy,
|
||||
rx: rx,
|
||||
ry: ry
|
||||
};
|
||||
}
|
||||
return this.el("ellipse", attr);
|
||||
};
|
||||
// SIERRA Paper.path(): Unclear from the link what a Catmull-Rom curveto is, and why it would make life any easier.
|
||||
/*\
|
||||
* Paper.path
|
||||
[ method ]
|
||||
**
|
||||
* Creates a `<path>` element using the given string as the path's definition
|
||||
- pathString (string) #optional path string in SVG format
|
||||
* Path string consists of one-letter commands, followed by comma seprarated arguments in numerical form. Example:
|
||||
| "M10,20L30,40"
|
||||
* This example features two commands: `M`, with arguments `(10, 20)` and `L` with arguments `(30, 40)`. Uppercase letter commands express coordinates in absolute terms, while lowercase commands express them in relative terms from the most recently declared coordinates.
|
||||
*
|
||||
# <p>Here is short list of commands available, for more details see <a href="http://www.w3.org/TR/SVG/paths.html#PathData" title="Details of a path's data attribute's format are described in the SVG specification.">SVG path string format</a> or <a href="https://developer.mozilla.org/en/SVG/Tutorial/Paths">article about path strings at MDN</a>.</p>
|
||||
# <table><thead><tr><th>Command</th><th>Name</th><th>Parameters</th></tr></thead><tbody>
|
||||
# <tr><td>M</td><td>moveto</td><td>(x y)+</td></tr>
|
||||
# <tr><td>Z</td><td>closepath</td><td>(none)</td></tr>
|
||||
# <tr><td>L</td><td>lineto</td><td>(x y)+</td></tr>
|
||||
# <tr><td>H</td><td>horizontal lineto</td><td>x+</td></tr>
|
||||
# <tr><td>V</td><td>vertical lineto</td><td>y+</td></tr>
|
||||
# <tr><td>C</td><td>curveto</td><td>(x1 y1 x2 y2 x y)+</td></tr>
|
||||
# <tr><td>S</td><td>smooth curveto</td><td>(x2 y2 x y)+</td></tr>
|
||||
# <tr><td>Q</td><td>quadratic Bézier curveto</td><td>(x1 y1 x y)+</td></tr>
|
||||
# <tr><td>T</td><td>smooth quadratic Bézier curveto</td><td>(x y)+</td></tr>
|
||||
# <tr><td>A</td><td>elliptical arc</td><td>(rx ry x-axis-rotation large-arc-flag sweep-flag x y)+</td></tr>
|
||||
# <tr><td>R</td><td><a href="http://en.wikipedia.org/wiki/Catmull–Rom_spline#Catmull.E2.80.93Rom_spline">Catmull-Rom curveto</a>*</td><td>x1 y1 (x y)+</td></tr></tbody></table>
|
||||
* * _Catmull-Rom curveto_ is a not standard SVG command and added to make life easier.
|
||||
* Note: there is a special case when a path consists of only three commands: `M10,10R…z`. In this case the path connects back to its starting point.
|
||||
> Usage
|
||||
| var c = paper.path("M10 10L90 90");
|
||||
| // draw a diagonal line:
|
||||
| // move to 10,10, line to 90,90
|
||||
\*/
|
||||
proto.path = function (d) {
|
||||
var attr;
|
||||
if (is(d, "object") && !is(d, "array")) {
|
||||
attr = d;
|
||||
} else if (d) {
|
||||
attr = {d: d};
|
||||
}
|
||||
return this.el("path", attr);
|
||||
};
|
||||
/*\
|
||||
* Paper.g
|
||||
[ method ]
|
||||
**
|
||||
* Creates a group element
|
||||
**
|
||||
- varargs (…) #optional elements to nest within the group
|
||||
= (object) the `g` element
|
||||
**
|
||||
> Usage
|
||||
| var c1 = paper.circle(),
|
||||
| c2 = paper.rect(),
|
||||
| g = paper.g(c2, c1); // note that the order of elements is different
|
||||
* or
|
||||
| var c1 = paper.circle(),
|
||||
| c2 = paper.rect(),
|
||||
| g = paper.g();
|
||||
| g.add(c2, c1);
|
||||
\*/
|
||||
/*\
|
||||
* Paper.group
|
||||
[ method ]
|
||||
**
|
||||
* See @Paper.g
|
||||
\*/
|
||||
proto.group = proto.g = function (first) {
|
||||
var attr,
|
||||
el = this.el("g");
|
||||
if (arguments.length == 1 && first && !first.type) {
|
||||
el.attr(first);
|
||||
} else if (arguments.length) {
|
||||
el.add(Array.prototype.slice.call(arguments, 0));
|
||||
}
|
||||
return el;
|
||||
};
|
||||
/*\
|
||||
* Paper.svg
|
||||
[ method ]
|
||||
**
|
||||
* Creates a nested SVG element.
|
||||
- x (number) @optional X of the element
|
||||
- y (number) @optional Y of the element
|
||||
- width (number) @optional width of the element
|
||||
- height (number) @optional height of the element
|
||||
- vbx (number) @optional viewbox X
|
||||
- vby (number) @optional viewbox Y
|
||||
- vbw (number) @optional viewbox width
|
||||
- vbh (number) @optional viewbox height
|
||||
**
|
||||
= (object) the `svg` element
|
||||
**
|
||||
\*/
|
||||
proto.svg = function (x, y, width, height, vbx, vby, vbw, vbh) {
|
||||
var attrs = {};
|
||||
if (is(x, "object") && y == null) {
|
||||
attrs = x;
|
||||
} else {
|
||||
if (x != null) {
|
||||
attrs.x = x;
|
||||
}
|
||||
if (y != null) {
|
||||
attrs.y = y;
|
||||
}
|
||||
if (width != null) {
|
||||
attrs.width = width;
|
||||
}
|
||||
if (height != null) {
|
||||
attrs.height = height;
|
||||
}
|
||||
if (vbx != null && vby != null && vbw != null && vbh != null) {
|
||||
attrs.viewBox = [vbx, vby, vbw, vbh];
|
||||
}
|
||||
}
|
||||
return this.el("svg", attrs);
|
||||
};
|
||||
/*\
|
||||
* Paper.mask
|
||||
[ method ]
|
||||
**
|
||||
* Equivalent in behaviour to @Paper.g, except it’s a mask.
|
||||
**
|
||||
= (object) the `mask` element
|
||||
**
|
||||
\*/
|
||||
proto.mask = function (first) {
|
||||
var attr,
|
||||
el = this.el("mask");
|
||||
if (arguments.length == 1 && first && !first.type) {
|
||||
el.attr(first);
|
||||
} else if (arguments.length) {
|
||||
el.add(Array.prototype.slice.call(arguments, 0));
|
||||
}
|
||||
return el;
|
||||
};
|
||||
/*\
|
||||
* Paper.ptrn
|
||||
[ method ]
|
||||
**
|
||||
* Equivalent in behaviour to @Paper.g, except it’s a mask.
|
||||
- x (number) @optional X of the element
|
||||
- y (number) @optional Y of the element
|
||||
- width (number) @optional width of the element
|
||||
- height (number) @optional height of the element
|
||||
- vbx (number) @optional viewbox X
|
||||
- vby (number) @optional viewbox Y
|
||||
- vbw (number) @optional viewbox width
|
||||
- vbh (number) @optional viewbox height
|
||||
**
|
||||
= (object) the `mask` element
|
||||
**
|
||||
\*/
|
||||
proto.ptrn = function (x, y, width, height, vx, vy, vw, vh) {
|
||||
if (is(x, "object")) {
|
||||
var attr = x;
|
||||
} else if (!arguments.length) {
|
||||
attr = {patternUnits: "userSpaceOnUse"};
|
||||
} else {
|
||||
attr = {};
|
||||
if (x != null) {
|
||||
attr.x = x;
|
||||
}
|
||||
if (y != null) {
|
||||
attr.y = y;
|
||||
}
|
||||
if (width != null) {
|
||||
attr.width = width;
|
||||
}
|
||||
if (height != null) {
|
||||
attr.height = height;
|
||||
}
|
||||
if (vx != null && vy != null && vw != null && vh != null) {
|
||||
attr.viewBox = [vx, vy, vw, vh];
|
||||
}
|
||||
}
|
||||
return this.el("pattern", attr);
|
||||
};
|
||||
/*\
|
||||
* Paper.use
|
||||
[ method ]
|
||||
**
|
||||
* Creates a <use> element.
|
||||
- id (string) @optional id of element to link
|
||||
* or
|
||||
- id (Element) @optional element to link
|
||||
**
|
||||
= (object) the `use` element
|
||||
**
|
||||
\*/
|
||||
proto.use = function (id) {
|
||||
if (id != null) {
|
||||
var el = make("use", this.node);
|
||||
if (id instanceof Element) {
|
||||
if (!id.attr("id")) {
|
||||
id.attr({id: ID()});
|
||||
}
|
||||
id = id.attr("id");
|
||||
}
|
||||
return this.el("use", {"xlink:href": id});
|
||||
} else {
|
||||
return Element.prototype.use.call(this);
|
||||
}
|
||||
};
|
||||
/*\
|
||||
* Paper.text
|
||||
[ method ]
|
||||
**
|
||||
* Draws a text string
|
||||
**
|
||||
- x (number) x coordinate position
|
||||
- y (number) y coordinate position
|
||||
- text (string|array) The text string to draw or array of strings to nest within separate `<tspan>` elements
|
||||
= (object) the `text` element
|
||||
**
|
||||
> Usage
|
||||
| var t1 = paper.text(50, 50, "Snap");
|
||||
| var t2 = paper.text(50, 50, ["S","n","a","p"]);
|
||||
| // Text path usage
|
||||
| t1.attr({textpath: "M10,10L100,100"});
|
||||
| // or
|
||||
| var pth = paper.path("M10,10L100,100");
|
||||
| t1.attr({textpath: pth});
|
||||
\*/
|
||||
proto.text = function (x, y, text) {
|
||||
var attr = {};
|
||||
if (is(x, "object")) {
|
||||
attr = x;
|
||||
} else if (x != null) {
|
||||
attr = {
|
||||
x: x,
|
||||
y: y,
|
||||
text: text || ""
|
||||
};
|
||||
}
|
||||
return this.el("text", attr);
|
||||
};
|
||||
/*\
|
||||
* Paper.line
|
||||
[ method ]
|
||||
**
|
||||
* Draws a line
|
||||
**
|
||||
- x1 (number) x coordinate position of the start
|
||||
- y1 (number) y coordinate position of the start
|
||||
- x2 (number) x coordinate position of the end
|
||||
- y2 (number) y coordinate position of the end
|
||||
= (object) the `line` element
|
||||
**
|
||||
> Usage
|
||||
| var t1 = paper.line(50, 50, 100, 100);
|
||||
\*/
|
||||
proto.line = function (x1, y1, x2, y2) {
|
||||
var attr = {};
|
||||
if (is(x1, "object")) {
|
||||
attr = x1;
|
||||
} else if (x1 != null) {
|
||||
attr = {
|
||||
x1: x1,
|
||||
x2: x2,
|
||||
y1: y1,
|
||||
y2: y2
|
||||
};
|
||||
}
|
||||
return this.el("line", attr);
|
||||
};
|
||||
/*\
|
||||
* Paper.polyline
|
||||
[ method ]
|
||||
**
|
||||
* Draws a polyline
|
||||
**
|
||||
- points (array) array of points
|
||||
* or
|
||||
- varargs (…) points
|
||||
= (object) the `polyline` element
|
||||
**
|
||||
> Usage
|
||||
| var p1 = paper.polyline([10, 10, 100, 100]);
|
||||
| var p2 = paper.polyline(10, 10, 100, 100);
|
||||
\*/
|
||||
proto.polyline = function (points) {
|
||||
if (arguments.length > 1) {
|
||||
points = Array.prototype.slice.call(arguments, 0);
|
||||
}
|
||||
var attr = {};
|
||||
if (is(points, "object") && !is(points, "array")) {
|
||||
attr = points;
|
||||
} else if (points != null) {
|
||||
attr = {points: points};
|
||||
}
|
||||
return this.el("polyline", attr);
|
||||
};
|
||||
/*\
|
||||
* Paper.polygon
|
||||
[ method ]
|
||||
**
|
||||
* Draws a polygon. See @Paper.polyline
|
||||
\*/
|
||||
proto.polygon = function (points) {
|
||||
if (arguments.length > 1) {
|
||||
points = Array.prototype.slice.call(arguments, 0);
|
||||
}
|
||||
var attr = {};
|
||||
if (is(points, "object") && !is(points, "array")) {
|
||||
attr = points;
|
||||
} else if (points != null) {
|
||||
attr = {points: points};
|
||||
}
|
||||
return this.el("polygon", attr);
|
||||
};
|
||||
// gradients
|
||||
(function () {
|
||||
var $ = Snap._.$;
|
||||
// gradients' helpers
|
||||
function Gstops() {
|
||||
return this.selectAll("stop");
|
||||
}
|
||||
function GaddStop(color, offset) {
|
||||
var stop = $("stop"),
|
||||
attr = {
|
||||
offset: +offset + "%"
|
||||
};
|
||||
color = Snap.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 Snap._.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 Snap._.box(cx - r, cy - r, r * 2, r * 2);
|
||||
}
|
||||
}
|
||||
function gradient(defs, str) {
|
||||
var grad = eve("snap.util.grad.parse", null, str).firstDefined(),
|
||||
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 = Snap._.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 = Snap._.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.gradient
|
||||
[ method ]
|
||||
**
|
||||
* Creates a gradient element
|
||||
**
|
||||
- gradient (string) gradient descriptor
|
||||
> Gradient Descriptor
|
||||
* The gradient descriptor is an expression formatted as
|
||||
* follows: `<type>(<coords>)<colors>`. The `<type>` can be
|
||||
* either linear or radial. The uppercase `L` or `R` letters
|
||||
* indicate absolute coordinates offset from the SVG surface.
|
||||
* Lowercase `l` or `r` letters indicate coordinates
|
||||
* calculated relative to the element to which the gradient is
|
||||
* applied. Coordinates specify a linear gradient vector as
|
||||
* `x1`, `y1`, `x2`, `y2`, or a radial gradient as `cx`, `cy`,
|
||||
* `r` and optional `fx`, `fy` specifying a focal point away
|
||||
* from the center of the circle. Specify `<colors>` as a list
|
||||
* of dash-separated CSS color values. Each color may be
|
||||
* followed by a custom offset value, separated with a colon
|
||||
* character.
|
||||
> Examples
|
||||
* Linear gradient, relative from top-left corner to bottom-right
|
||||
* corner, from black through red to white:
|
||||
| var g = paper.gradient("l(0, 0, 1, 1)#000-#f00-#fff");
|
||||
* Linear gradient, absolute from (0, 0) to (100, 100), from black
|
||||
* through red at 25% to white:
|
||||
| var g = paper.gradient("L(0, 0, 100, 100)#000-#f00:25-#fff");
|
||||
* Radial gradient, relative from the center of the element with radius
|
||||
* half the width, from black to white:
|
||||
| var g = paper.gradient("r(0.5, 0.5, 0.5)#000-#fff");
|
||||
* To apply the gradient:
|
||||
| paper.circle(50, 50, 40).attr({
|
||||
| fill: g
|
||||
| });
|
||||
= (object) the `gradient` element
|
||||
\*/
|
||||
proto.gradient = function (str) {
|
||||
return gradient(this.defs, str);
|
||||
};
|
||||
proto.gradientLinear = function (x1, y1, x2, y2) {
|
||||
return gradientLinear(this.defs, x1, y1, x2, y2);
|
||||
};
|
||||
proto.gradientRadial = function (cx, cy, r, fx, fy) {
|
||||
return gradientRadial(this.defs, cx, cy, r, fx, fy);
|
||||
};
|
||||
/*\
|
||||
* Paper.toString
|
||||
[ method ]
|
||||
**
|
||||
* Returns SVG code for the @Paper
|
||||
= (string) SVG code for the @Paper
|
||||
\*/
|
||||
proto.toString = function () {
|
||||
var doc = this.node.ownerDocument,
|
||||
f = doc.createDocumentFragment(),
|
||||
d = doc.createElement("div"),
|
||||
svg = this.node.cloneNode(true),
|
||||
res;
|
||||
f.appendChild(d);
|
||||
d.appendChild(svg);
|
||||
Snap._.$(svg, {xmlns: "http://www.w3.org/2000/svg"});
|
||||
res = d.innerHTML;
|
||||
f.removeChild(f.firstChild);
|
||||
return res;
|
||||
};
|
||||
/*\
|
||||
* Paper.clear
|
||||
[ method ]
|
||||
**
|
||||
* Removes all child nodes of the paper, except <defs>.
|
||||
\*/
|
||||
proto.clear = function () {
|
||||
var node = this.node.firstChild,
|
||||
next;
|
||||
while (node) {
|
||||
next = node.nextSibling;
|
||||
if (node.tagName != "defs") {
|
||||
node.parentNode.removeChild(node);
|
||||
} else {
|
||||
proto.clear.call({node: node});
|
||||
}
|
||||
node = next;
|
||||
}
|
||||
};
|
||||
}());
|
||||
});
|
203
src/path.js
203
src/path.js
|
@ -300,8 +300,8 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
}
|
||||
var l1 = bezlen.apply(0, bez1),
|
||||
l2 = bezlen.apply(0, bez2),
|
||||
n1 = ~~(l1 / 5),
|
||||
n2 = ~~(l2 / 5),
|
||||
n1 = ~~(l1 / 8),
|
||||
n2 = ~~(l2 / 8),
|
||||
dots1 = [],
|
||||
dots2 = [],
|
||||
xy = {},
|
||||
|
@ -451,7 +451,7 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
function rectPath(x, y, w, h, r) {
|
||||
if (r) {
|
||||
return [
|
||||
["M", x + r, y],
|
||||
["M", +x + (+r), y],
|
||||
["l", w - r * 2, 0],
|
||||
["a", r, r, 0, 0, 1, r, r],
|
||||
["l", 0, h - r * 2],
|
||||
|
@ -471,6 +471,10 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
if (a == null && ry == null) {
|
||||
ry = rx;
|
||||
}
|
||||
x = +x;
|
||||
y = +y;
|
||||
rx = +rx;
|
||||
ry = +ry;
|
||||
if (a != null) {
|
||||
var rad = Math.PI / 180,
|
||||
x1 = x + rx * Math.cos(-ry * rad),
|
||||
|
@ -501,30 +505,18 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
},
|
||||
ellipse: function (el) {
|
||||
var attr = unit2px(el);
|
||||
return ellipsePath(attr.cx, attr.cy, attr.rx, attr.ry);
|
||||
return ellipsePath(attr.cx || 0, attr.cy || 0, attr.rx, attr.ry);
|
||||
},
|
||||
rect: function (el) {
|
||||
var attr = unit2px(el);
|
||||
return rectPath(attr.x, attr.y, attr.width, attr.height, attr.rx, attr.ry);
|
||||
return rectPath(attr.x || 0, attr.y || 0, attr.width, attr.height, attr.rx, attr.ry);
|
||||
},
|
||||
image: function (el) {
|
||||
var attr = unit2px(el);
|
||||
return rectPath(attr.x, attr.y, attr.width, attr.height);
|
||||
},
|
||||
text: function (el) {
|
||||
var bbox = el.node.getBBox();
|
||||
return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
|
||||
},
|
||||
g: function (el) {
|
||||
var bbox = el.node.getBBox();
|
||||
return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
|
||||
},
|
||||
symbol: function (el) {
|
||||
var bbox = el.getBBox();
|
||||
return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
|
||||
return rectPath(attr.x || 0, attr.y || 0, attr.width, attr.height);
|
||||
},
|
||||
line: function (el) {
|
||||
return "M" + [el.attr("x1"), el.attr("y1"), el.attr("x2"), el.attr("y2")];
|
||||
return "M" + [el.attr("x1") || 0, el.attr("y1") || 0, el.attr("x2"), el.attr("y2")];
|
||||
},
|
||||
polyline: function (el) {
|
||||
return "M" + el.attr("points");
|
||||
|
@ -532,10 +524,6 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
polygon: function (el) {
|
||||
return "M" + el.attr("points") + "z";
|
||||
},
|
||||
svg: function (el) {
|
||||
var bbox = el.node.getBBox();
|
||||
return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
|
||||
},
|
||||
deflt: function (el) {
|
||||
var bbox = el.node.getBBox();
|
||||
return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
|
||||
|
@ -664,8 +652,8 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
r[3] = pa[3];
|
||||
r[4] = pa[4];
|
||||
r[5] = pa[5];
|
||||
r[6] = +(pa[6] + x);
|
||||
r[7] = +(pa[7] + y);
|
||||
r[6] = +pa[6] + x;
|
||||
r[7] = +pa[7] + y;
|
||||
break;
|
||||
case "V":
|
||||
r[1] = +pa[1] + y;
|
||||
|
@ -724,8 +712,8 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
if (pa0 != "O") {
|
||||
switch (r[0]) {
|
||||
case "Z":
|
||||
x = mx;
|
||||
y = my;
|
||||
x = +mx;
|
||||
y = +my;
|
||||
break;
|
||||
case "H":
|
||||
x = r[1];
|
||||
|
@ -857,49 +845,73 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y
|
||||
};
|
||||
}
|
||||
function curveDim(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
|
||||
var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
|
||||
b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
|
||||
c = p1x - c1x,
|
||||
t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a,
|
||||
t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a,
|
||||
y = [p1y, p2y],
|
||||
x = [p1x, p2x],
|
||||
dot;
|
||||
abs(t1) > "1e12" && (t1 = .5);
|
||||
abs(t2) > "1e12" && (t2 = .5);
|
||||
if (t1 > 0 && t1 < 1) {
|
||||
dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
|
||||
x.push(dot.x);
|
||||
y.push(dot.y);
|
||||
|
||||
// Returns bounding box of cubic bezier curve.
|
||||
// Source: http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
|
||||
// Original version: NISHIO Hirokazu
|
||||
// Modifications: https://github.com/timo22345
|
||||
function curveDim(x0, y0, x1, y1, x2, y2, x3, y3) {
|
||||
var tvalues = [],
|
||||
bounds = [[], []],
|
||||
a, b, c, t, t1, t2, b2ac, sqrtb2ac;
|
||||
for (var i = 0; i < 2; ++i) {
|
||||
if (i == 0) {
|
||||
b = 6 * x0 - 12 * x1 + 6 * x2;
|
||||
a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;
|
||||
c = 3 * x1 - 3 * x0;
|
||||
} else {
|
||||
b = 6 * y0 - 12 * y1 + 6 * y2;
|
||||
a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;
|
||||
c = 3 * y1 - 3 * y0;
|
||||
}
|
||||
if (t2 > 0 && t2 < 1) {
|
||||
dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
|
||||
x.push(dot.x);
|
||||
y.push(dot.y);
|
||||
if (abs(a) < 1e-12) {
|
||||
if (abs(b) < 1e-12) {
|
||||
continue;
|
||||
}
|
||||
a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
|
||||
b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
|
||||
c = p1y - c1y;
|
||||
t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a;
|
||||
t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a;
|
||||
abs(t1) > "1e12" && (t1 = .5);
|
||||
abs(t2) > "1e12" && (t2 = .5);
|
||||
if (t1 > 0 && t1 < 1) {
|
||||
dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
|
||||
x.push(dot.x);
|
||||
y.push(dot.y);
|
||||
t = -c / b;
|
||||
if (0 < t && t < 1) {
|
||||
tvalues.push(t);
|
||||
}
|
||||
if (t2 > 0 && t2 < 1) {
|
||||
dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
|
||||
x.push(dot.x);
|
||||
y.push(dot.y);
|
||||
continue;
|
||||
}
|
||||
b2ac = b * b - 4 * c * a;
|
||||
sqrtb2ac = math.sqrt(b2ac);
|
||||
if (b2ac < 0) {
|
||||
continue;
|
||||
}
|
||||
t1 = (-b + sqrtb2ac) / (2 * a);
|
||||
if (0 < t1 && t1 < 1) {
|
||||
tvalues.push(t1);
|
||||
}
|
||||
t2 = (-b - sqrtb2ac) / (2 * a);
|
||||
if (0 < t2 && t2 < 1) {
|
||||
tvalues.push(t2);
|
||||
}
|
||||
}
|
||||
|
||||
var x, y, j = tvalues.length,
|
||||
jlen = j,
|
||||
mt;
|
||||
while (j--) {
|
||||
t = tvalues[j];
|
||||
mt = 1 - t;
|
||||
bounds[0][j] = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (3 * mt * t * t * x2) + (t * t * t * x3);
|
||||
bounds[1][j] = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (3 * mt * t * t * y2) + (t * t * t * y3);
|
||||
}
|
||||
|
||||
bounds[0][jlen] = x0;
|
||||
bounds[1][jlen] = y0;
|
||||
bounds[0][jlen + 1] = x3;
|
||||
bounds[1][jlen + 1] = y3;
|
||||
bounds[0].length = bounds[1].length = jlen + 2;
|
||||
|
||||
|
||||
return {
|
||||
min: {x: mmin.apply(0, x), y: mmin.apply(0, y)},
|
||||
max: {x: mmax.apply(0, x), y: mmax.apply(0, y)}
|
||||
min: {x: mmin.apply(0, bounds[0]), y: mmin.apply(0, bounds[1])},
|
||||
max: {x: mmax.apply(0, bounds[0]), y: mmax.apply(0, bounds[1])}
|
||||
};
|
||||
}
|
||||
|
||||
function path2curve(path, path2) {
|
||||
var pth = !path2 && paths(path);
|
||||
if (!path2 && pth.curve) {
|
||||
|
@ -909,12 +921,12 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
p2 = path2 && pathToAbsolute(path2),
|
||||
attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
|
||||
attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
|
||||
processPath = function (path, d) {
|
||||
processPath = function (path, d, pcom) {
|
||||
var nx, ny;
|
||||
if (!path) {
|
||||
return ["C", d.x, d.y, d.x, d.y, d.x, d.y];
|
||||
}
|
||||
!(path[0] in {T:1, Q:1}) && (d.qx = d.qy = null);
|
||||
!(path[0] in {T: 1, Q: 1}) && (d.qx = d.qy = null);
|
||||
switch (path[0]) {
|
||||
case "M":
|
||||
d.X = path[1];
|
||||
|
@ -924,13 +936,25 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
path = ["C"].concat(a2c.apply(0, [d.x, d.y].concat(path.slice(1))));
|
||||
break;
|
||||
case "S":
|
||||
nx = d.x + (d.x - (d.bx || d.x));
|
||||
ny = d.y + (d.y - (d.by || d.y));
|
||||
if (pcom == "C" || pcom == "S") { // In "S" case we have to take into account, if the previous command is C/S.
|
||||
nx = d.x * 2 - d.bx; // And reflect the previous
|
||||
ny = d.y * 2 - d.by; // command's control point relative to the current point.
|
||||
}
|
||||
else { // or some else or nothing
|
||||
nx = d.x;
|
||||
ny = d.y;
|
||||
}
|
||||
path = ["C", nx, ny].concat(path.slice(1));
|
||||
break;
|
||||
case "T":
|
||||
d.qx = d.x + (d.x - (d.qx || d.x));
|
||||
d.qy = d.y + (d.y - (d.qy || d.y));
|
||||
if (pcom == "Q" || pcom == "T") { // In "T" case we have to take into account, if the previous command is Q/T.
|
||||
d.qx = d.x * 2 - d.qx; // And make a reflection similar
|
||||
d.qy = d.y * 2 - d.qy; // to case "S".
|
||||
}
|
||||
else { // or something else or nothing
|
||||
d.qx = d.x;
|
||||
d.qy = d.y;
|
||||
}
|
||||
path = ["C"].concat(q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
|
||||
break;
|
||||
case "Q":
|
||||
|
@ -958,6 +982,8 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
pp[i].shift();
|
||||
var pi = pp[i];
|
||||
while (pi.length) {
|
||||
pcoms1[i] = "A"; // if created multiple C:s, their original seg is saved
|
||||
p2 && (pcoms2[i] = "A"); // the same as above
|
||||
pp.splice(i++, 0, ["C"].concat(pi.splice(0, 6)));
|
||||
}
|
||||
pp.splice(i, 1);
|
||||
|
@ -973,12 +999,41 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
a1.y = path1[i][2];
|
||||
ii = mmax(p.length, p2 && p2.length || 0);
|
||||
}
|
||||
};
|
||||
},
|
||||
pcoms1 = [], // path commands of original path p
|
||||
pcoms2 = [], // path commands of original path p2
|
||||
pfirst = "", // temporary holder for original path command
|
||||
pcom = ""; // holder for previous path command of original path
|
||||
for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) {
|
||||
p[i] = processPath(p[i], attrs);
|
||||
fixArc(p, i);
|
||||
p2 && (p2[i] = processPath(p2[i], attrs2));
|
||||
p2 && fixArc(p2, i);
|
||||
p[i] && (pfirst = p[i][0]); // save current path command
|
||||
|
||||
if (pfirst != "C") // C is not saved yet, because it may be result of conversion
|
||||
{
|
||||
pcoms1[i] = pfirst; // Save current path command
|
||||
i && ( pcom = pcoms1[i - 1]); // Get previous path command pcom
|
||||
}
|
||||
p[i] = processPath(p[i], attrs, pcom); // Previous path command is inputted to processPath
|
||||
|
||||
if (pcoms1[i] != "A" && pfirst == "C") pcoms1[i] = "C"; // A is the only command
|
||||
// which may produce multiple C:s
|
||||
// so we have to make sure that C is also C in original path
|
||||
|
||||
fixArc(p, i); // fixArc adds also the right amount of A:s to pcoms1
|
||||
|
||||
if (p2) { // the same procedures is done to p2
|
||||
p2[i] && (pfirst = p2[i][0]);
|
||||
if (pfirst != "C") {
|
||||
pcoms2[i] = pfirst;
|
||||
i && (pcom = pcoms2[i - 1]);
|
||||
}
|
||||
p2[i] = processPath(p2[i], attrs2, pcom);
|
||||
|
||||
if (pcoms2[i] != "A" && pfirst == "C") {
|
||||
pcoms2[i] = "C";
|
||||
}
|
||||
|
||||
fixArc(p2, i);
|
||||
}
|
||||
fixM(p, p2, attrs, attrs2, i);
|
||||
fixM(p2, p, attrs2, attrs, i);
|
||||
var seg = p[i],
|
||||
|
|
102
src/set.js
102
src/set.js
|
@ -18,6 +18,7 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
// Set
|
||||
var Set = function (items) {
|
||||
this.items = [];
|
||||
this.bindings = {};
|
||||
this.length = 0;
|
||||
this.type = "set";
|
||||
if (items) {
|
||||
|
@ -81,15 +82,114 @@ Snap.plugin(function (Snap, Element, Paper, glob) {
|
|||
}
|
||||
return this;
|
||||
};
|
||||
/*\
|
||||
* Set.animate
|
||||
[ method ]
|
||||
**
|
||||
* Animates each element in set in sync.
|
||||
*
|
||||
**
|
||||
- attrs (object) key-value pairs of destination attributes
|
||||
- duration (number) duration of the animation in milliseconds
|
||||
- easing (function) #optional easing function from @mina or custom
|
||||
- callback (function) #optional callback function that executes when the animation ends
|
||||
* or
|
||||
- animation (array) array of animation parameter for each element in set in format `[attrs, duration, easing, callback]`
|
||||
> Usage
|
||||
| // animate all elements in set to radius 10
|
||||
| set.animate({r: 10}, 500, mina.easein);
|
||||
| // or
|
||||
| // animate first element to radius 10, but second to radius 20 and in different time
|
||||
| set.animate([{r: 10}, 500, mina.easein], [{r: 20}, 1500, mina.easein]);
|
||||
= (Element) the current element
|
||||
\*/
|
||||
setproto.animate = function (attrs, ms, easing, callback) {
|
||||
if (typeof easing == "function" && !easing.length) {
|
||||
callback = easing;
|
||||
easing = mina.linear;
|
||||
}
|
||||
if (attrs instanceof Snap._.Animation) {
|
||||
callback = attrs.callback;
|
||||
easing = attrs.easing;
|
||||
ms = easing.dur;
|
||||
attrs = attrs.attr;
|
||||
}
|
||||
var args = arguments;
|
||||
if (Snap.is(attrs, "array") && Snap.is(args[args.length - 1], "array")) {
|
||||
var each = true;
|
||||
}
|
||||
var begin,
|
||||
handler = function () {
|
||||
if (begin) {
|
||||
this.b = begin;
|
||||
} else {
|
||||
begin = this.b;
|
||||
}
|
||||
},
|
||||
cb = 0,
|
||||
callbacker = callback && function () {
|
||||
if (cb++ == this.length) {
|
||||
callback.call(this);
|
||||
}
|
||||
};
|
||||
return this.forEach(function (el, i) {
|
||||
eve.once("snap.animcreated." + el.id, handler);
|
||||
if (each) {
|
||||
args[i] && el.animate.apply(el, args[i]);
|
||||
} else {
|
||||
el.animate(attrs, ms, easing, callbacker);
|
||||
}
|
||||
});
|
||||
};
|
||||
setproto.remove = function () {
|
||||
while (this.length) {
|
||||
this.pop().remove();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
/*\
|
||||
* Set.bind
|
||||
[ method ]
|
||||
**
|
||||
* Specifies how to handle a specific attribute when applied
|
||||
* to a set.
|
||||
*
|
||||
**
|
||||
- attr (string) attribute name
|
||||
- callback (function) function to run
|
||||
* or
|
||||
- attr (string) attribute name
|
||||
- element (Element) specific element in the set to apply the attribute to
|
||||
* or
|
||||
- attr (string) attribute name
|
||||
- element (Element) specific element in the set to apply the attribute to
|
||||
- eattr (string) attribute on the element to bind the attribute to
|
||||
= (object) Set object
|
||||
\*/
|
||||
setproto.bind = function (attr, a, b) {
|
||||
var data = {};
|
||||
if (typeof a == "function") {
|
||||
this.bindings[attr] = a;
|
||||
} else {
|
||||
var aname = b || attr;
|
||||
this.bindings[attr] = function (v) {
|
||||
data[aname] = v;
|
||||
a.attr(data);
|
||||
};
|
||||
}
|
||||
return this;
|
||||
};
|
||||
setproto.attr = function (value) {
|
||||
var unbound = {};
|
||||
for (var k in value) {
|
||||
if (this.bindings[k]) {
|
||||
this.bindings[k](value[k]);
|
||||
} else {
|
||||
unbound[k] = value[k];
|
||||
}
|
||||
}
|
||||
for (var i = 0, ii = this.items.length; i < ii; i++) {
|
||||
this.items[i].attr(value);
|
||||
this.items[i].attr(unbound);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
|
1648
src/svg.js
1648
src/svg.js
File diff suppressed because it is too large
Load Diff
|
@ -80,7 +80,7 @@
|
|||
{{~it.out :item:index}}
|
||||
<article id="{{=item[0].title}}">
|
||||
<header>
|
||||
<h3 class="{{=item[0].clas}}">{{=item[0].name}}<a href="#{{=item[0].title}}" title="Link to this section" class="dr-hash">⚓</a><a class="dr-sourceline" title="Go to line {{=item[0].line}} in the source" href="https://github.com/adobe-webplatform/savage/blob/master/src/svg.js#{{=item[0].line}}">➭</a></h3>
|
||||
<h3 class="{{=item[0].clas}}">{{=item[0].name}}<a href="#{{=item[0].title}}" title="Link to this section" class="dr-hash">⚓</a><a class="dr-sourceline" title="Go to line {{=item[0].line}} in the source" href="https://github.com/adobe-webplatform/Snap.svg/blob/master/src/svg.js#L{{=item[0].line}}">➭</a></h3>
|
||||
</header>
|
||||
<section>
|
||||
<div class="extra" id="{{=item[0].title}}-extra"></div>
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 181.4199981689453 189.9199981689453">
|
||||
<desc>Created with Snap</desc>
|
||||
<defs>
|
||||
<rect width="10" height="10" class="svg---mgr"/>
|
||||
</defs>
|
||||
<g>
|
||||
<image xlink:href="http://labels.labellogiclive.com/picnic_12_p1_pic001_uk__v0.svg" preserveAspectRatio="none" x="0" y="0" width="181.42" height="189.92"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,9.5963,8.3968)">
|
||||
<g style="cursor: auto;">
|
||||
<text x="80.28845687866212" y="1.1127823638916006" style="font-family: Helvetica; font-size: 41px; font-style: normal; font-weight: normal; text-decoration: none; text-anchor: middle;">
|
||||
<tspan space="preserve" x="80.28845687866212" dy="1em"><<title>></tspan>
|
||||
</text>
|
||||
<rect x="0" y="0" width="160.57691375732423" height="49.3193147277832" fill="#ffffff" stroke="#000000" style="fill-opacity: 0; stroke-width: 0.5px; stroke-dasharray: 5px, 2px;"/>
|
||||
</g>
|
||||
<line x1="80.28845687866212" x2="80.28845687866212" y1="0" y2="-10" fill="none" stroke="#eeeeee" style="stroke-dasharray: 2px, 2px; stroke-width: 0.7px; visibility: hidden;"/>
|
||||
<circle cx="80.28845687866212" cy="-10" r="2" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; visibility: hidden;"/>
|
||||
<rect x="78.28845687866212" y="-2" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: n-resize; visibility: hidden;"/>
|
||||
<rect x="158.57691375732423" y="22.6596573638916" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: e-resize; visibility: hidden;"/>
|
||||
<rect x="78.28845687866212" y="47.3193147277832" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: s-resize; visibility: hidden;"/>
|
||||
<rect x="-2" y="22.6596573638916" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: w-resize; visibility: hidden;"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,9.5963,59.6773)">
|
||||
<g style="cursor: auto;">
|
||||
<text x="80.43839973449704" y="1.263066406250001" style="font-family: Helvetica; font-size: 18px; font-style: normal; font-weight: normal; text-decoration: none; text-anchor: middle;">
|
||||
<tspan space="preserve" x="80.43839973449704" dy="1em"><<description>></tspan>
|
||||
</text>
|
||||
<rect x="0" y="0" width="160.87679946899408" height="23.229257812500002" fill="#ffffff" stroke="#000000" style="fill-opacity: 0; stroke-width: 0.5px; stroke-dasharray: 5px, 2px;"/>
|
||||
</g>
|
||||
<line x1="80.43839973449704" x2="80.43839973449704" y1="0" y2="-10" fill="none" stroke="#eeeeee" style="stroke-dasharray: 2px, 2px; stroke-width: 0.7px; visibility: hidden;"/>
|
||||
<circle cx="80.43839973449704" cy="-10" r="2" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; visibility: hidden;"/>
|
||||
<rect x="78.43839973449704" y="-2" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: n-resize; visibility: hidden;"/>
|
||||
<rect x="158.87679946899408" y="9.614628906250001" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: e-resize; visibility: hidden;"/>
|
||||
<rect x="78.43839973449704" y="21.229257812500002" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: s-resize; visibility: hidden;"/>
|
||||
<rect x="-2" y="9.614628906250001" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: w-resize; visibility: hidden;"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,55.179,84.8677)">
|
||||
<g style="cursor: auto;">
|
||||
<text x="24.509714508056643" y="4.783778915405273" style="font-family: Helvetica; font-size: 10px; font-style: normal; font-weight: normal; text-decoration: none; text-anchor: middle;">
|
||||
<tspan space="preserve" x="24.509714508056643" dy="1em"><<price>></tspan>
|
||||
</text>
|
||||
<rect x="0" y="0" width="49.019429016113286" height="21.130057830810546" fill="#ffffff" stroke="#000000" style="fill-opacity: 0; stroke-width: 0.5px; stroke-dasharray: 5px, 2px;"/>
|
||||
</g>
|
||||
<line x1="24.509714508056643" x2="24.509714508056643" y1="0" y2="-10" fill="none" stroke="#eeeeee" style="stroke-dasharray: 2px, 2px; stroke-width: 0.7px; visibility: hidden;"/>
|
||||
<circle cx="24.509714508056643" cy="-10" r="2" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; visibility: hidden;"/>
|
||||
<rect x="22.509714508056643" y="-2" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: n-resize; visibility: hidden;"/>
|
||||
<rect x="47.019429016113286" y="8.565028915405273" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: e-resize; visibility: hidden;"/>
|
||||
<rect x="22.509714508056643" y="19.130057830810546" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: s-resize; visibility: hidden;"/>
|
||||
<rect x="-2" y="8.565028915405273" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: w-resize; visibility: hidden;"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,9.5963,85.1675)">
|
||||
<g style="cursor: move;">
|
||||
<text x="21.660800247192384" y="2.757330703735356" style="font-family: Helvetica; font-size: 13px; font-style: normal; font-weight: normal; text-decoration: none; text-anchor: middle;">
|
||||
<tspan space="preserve" x="21.660800247192384" dy="1em">Use By:</tspan>
|
||||
</text>
|
||||
<rect x="0" y="0" width="43.32160049438477" height="20.53028640747071" fill="#ffffff" stroke="#000000" style="fill-opacity: 0; stroke-width: 0.5px; stroke-dasharray: 5px, 2px;"/>
|
||||
</g>
|
||||
<line x1="21.660800247192384" x2="21.660800247192384" y1="0" y2="-10" fill="none" stroke="#eeeeee" style="stroke-dasharray: 2px, 2px; stroke-width: 0.7px; visibility: visible;"/>
|
||||
<circle cx="21.660800247192384" cy="-10" r="2" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; visibility: visible;"/>
|
||||
<rect x="19.660800247192384" y="-2" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: n-resize; visibility: visible;"/>
|
||||
<rect x="41.32160049438477" y="8.265143203735356" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: e-resize; visibility: visible;"/>
|
||||
<rect x="19.660800247192384" y="18.53028640747071" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: s-resize; visibility: visible;"/>
|
||||
<rect x="-2" y="8.265143203735356" width="4" height="4" fill="#000000" stroke="#eeeeee" style="stroke-width: 0.4px; cursor: w-resize; visibility: visible;"/>
|
||||
</g>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,38 @@
|
|||
describe("Attributes += methods", function () {
|
||||
var s, r;
|
||||
beforeEach(function () {
|
||||
s = Snap(100, 100);
|
||||
r = s.rect(10, 10, 50, 50);
|
||||
});
|
||||
afterEach(function () {
|
||||
s.remove();
|
||||
});
|
||||
it("+=10", function () {
|
||||
r.attr({x: "+=10"});
|
||||
expect(r.node.getAttribute("x")).to.be("20");
|
||||
});
|
||||
it("-=10", function () {
|
||||
r.attr({x: "-=10"});
|
||||
expect(r.node.getAttribute("x")).to.be("0");
|
||||
});
|
||||
it("*=2", function () {
|
||||
r.attr({x: "*=2"});
|
||||
expect(r.node.getAttribute("x")).to.be("20");
|
||||
});
|
||||
it("/=2", function () {
|
||||
r.attr({x: "/=2"});
|
||||
expect(r.node.getAttribute("x")).to.be("5");
|
||||
});
|
||||
it("+=1em", function () {
|
||||
var em = s.rect(0, 0, "1em", "1em");
|
||||
em = em.getBBox().w;
|
||||
r.attr({x: "+=1em"});
|
||||
expect(r.node.getAttribute("x")).to.eql(10 + em);
|
||||
});
|
||||
it("-=.3em", function () {
|
||||
var em = s.rect(0, 0, "1em", "1em");
|
||||
em = em.getBBox().w;
|
||||
r.attr({x: "-=.3em"});
|
||||
expect((+r.node.getAttribute("x")).toFixed(2)).to.eql((10 - em * .3).toFixed(2));
|
||||
});
|
||||
});
|
|
@ -0,0 +1,55 @@
|
|||
describe("Class methods", function () {
|
||||
var s, r;
|
||||
beforeEach(function () {
|
||||
s = Snap(100, 100);
|
||||
r = s.rect(10, 10, 50, 50);
|
||||
});
|
||||
afterEach(function () {
|
||||
s.remove();
|
||||
});
|
||||
it("elproto.addClass one", function() {
|
||||
r.addClass("one");
|
||||
expect(r.node.className.baseVal).to.be("one");
|
||||
});
|
||||
it("elproto.addClass two", function() {
|
||||
r.addClass("one two");
|
||||
expect(r.node.className.baseVal).to.be("one two");
|
||||
});
|
||||
it("elproto.addClass two (spacing)", function() {
|
||||
r.addClass("\tone two ");
|
||||
expect(r.node.className.baseVal).to.be("one two");
|
||||
});
|
||||
it("elproto.addClass three", function() {
|
||||
r.addClass("one two three");
|
||||
expect(r.node.className.baseVal).to.be("one two three");
|
||||
});
|
||||
it("elproto.removeClass 1", function() {
|
||||
r.addClass("one two three");
|
||||
r.removeClass("two");
|
||||
expect(r.node.className.baseVal).to.be("one three");
|
||||
});
|
||||
it("elproto.removeClass 2", function() {
|
||||
r.addClass("one two three");
|
||||
r.removeClass("two one");
|
||||
expect(r.node.className.baseVal).to.be("three");
|
||||
});
|
||||
it("elproto.hasClass", function() {
|
||||
r.addClass("one two three");
|
||||
expect(r.hasClass("two")).to.be(true);
|
||||
});
|
||||
it("elproto.toggleClass 1", function() {
|
||||
r.addClass("one two three");
|
||||
r.toggleClass("two one");
|
||||
expect(r.node.className.baseVal).to.be("three");
|
||||
});
|
||||
it("elproto.toggleClass 2", function() {
|
||||
r.addClass("one three");
|
||||
r.toggleClass("two one", false);
|
||||
expect(r.node.className.baseVal).to.be("three");
|
||||
});
|
||||
it("elproto.toggleClass 3", function() {
|
||||
r.addClass("one three");
|
||||
r.toggleClass("two one", true);
|
||||
expect(r.node.className.baseVal).to.be("one three two");
|
||||
});
|
||||
});
|
|
@ -55,28 +55,28 @@ describe("Filter methods", function () {
|
|||
});
|
||||
it("Snap.filter.shadow - dx & dy", function() {
|
||||
var str = Snap.filter.shadow(5, 5);
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="4"/><feOffset dx="5" dy="5" result="offsetblur"/><feFlood flood-color="#000000"/><feComposite in2="offsetblur" operator="in"/><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="4"/><feOffset dx="5" dy="5" result="offsetblur"/><feFlood flood-color="#000000"/><feComposite in2="offsetblur" operator="in"/><feComponentTransfer><feFuncA type="linear" slope="1"/></feComponentTransfer><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
str = Snap.filter.shadow(-1, 3);
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="4"/><feOffset dx="-1" dy="3" result="offsetblur"/><feFlood flood-color="#000000"/><feComposite in2="offsetblur" operator="in"/><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="4"/><feOffset dx="-1" dy="3" result="offsetblur"/><feFlood flood-color="#000000"/><feComposite in2="offsetblur" operator="in"/><feComponentTransfer><feFuncA type="linear" slope="1"/></feComponentTransfer><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
});
|
||||
it("Snap.filter.shadow - dx & dy, blur", function() {
|
||||
var str = Snap.filter.shadow(5, 5, 5);
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="5"/><feOffset dx="5" dy="5" result="offsetblur"/><feFlood flood-color="#000000"/><feComposite in2="offsetblur" operator="in"/><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="5"/><feOffset dx="5" dy="5" result="offsetblur"/><feFlood flood-color="#000000"/><feComposite in2="offsetblur" operator="in"/><feComponentTransfer><feFuncA type="linear" slope="1"/></feComponentTransfer><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
str = Snap.filter.shadow(-1, 3, 10);
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="10"/><feOffset dx="-1" dy="3" result="offsetblur"/><feFlood flood-color="#000000"/><feComposite in2="offsetblur" operator="in"/><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="10"/><feOffset dx="-1" dy="3" result="offsetblur"/><feFlood flood-color="#000000"/><feComposite in2="offsetblur" operator="in"/><feComponentTransfer><feFuncA type="linear" slope="1"/></feComponentTransfer><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
});
|
||||
it("Snap.filter.shadow - dx & dy, color", function() {
|
||||
var str = Snap.filter.shadow(5, 5, '#F00');
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="4"/><feOffset dx="5" dy="5" result="offsetblur"/><feFlood flood-color="#ff0000"/><feComposite in2="offsetblur" operator="in"/><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="4"/><feOffset dx="5" dy="5" result="offsetblur"/><feFlood flood-color="#ff0000"/><feComposite in2="offsetblur" operator="in"/><feComponentTransfer><feFuncA type="linear" slope="#F00"/></feComponentTransfer><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
str = Snap.filter.shadow(-1, 3, 'hsla(128deg, 50%, 50%, 0.8)');
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="4"/><feOffset dx="-1" dy="3" result="offsetblur"/><feFlood flood-color="rgba(64,191,81,0.8)"/><feComposite in2="offsetblur" operator="in"/><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="4"/><feOffset dx="-1" dy="3" result="offsetblur"/><feFlood flood-color="rgba(64,191,81,0.8)"/><feComposite in2="offsetblur" operator="in"/><feComponentTransfer><feFuncA type="linear" slope="hsla(128deg, 50%, 50%, 0.8)"/></feComponentTransfer><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
});
|
||||
|
||||
it("Snap.filter.shadow - dx & dy, blur & color", function() {
|
||||
var str = Snap.filter.shadow(5, 5, 5, '#F00');
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="5"/><feOffset dx="5" dy="5" result="offsetblur"/><feFlood flood-color="#ff0000"/><feComposite in2="offsetblur" operator="in"/><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="5"/><feOffset dx="5" dy="5" result="offsetblur"/><feFlood flood-color="#ff0000"/><feComposite in2="offsetblur" operator="in"/><feComponentTransfer><feFuncA type="linear" slope="1"/></feComponentTransfer><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
str = Snap.filter.shadow(-1, 3, 10, 'hsla(128deg, 50%, 50%, 0.8)');
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="10"/><feOffset dx="-1" dy="3" result="offsetblur"/><feFlood flood-color="rgba(64,191,81,0.8)"/><feComposite in2="offsetblur" operator="in"/><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
expect(str).to.be('<feGaussianBlur in="SourceAlpha" stdDeviation="10"/><feOffset dx="-1" dy="3" result="offsetblur"/><feFlood flood-color="rgba(64,191,81,0.8)"/><feComposite in2="offsetblur" operator="in"/><feComponentTransfer><feFuncA type="linear" slope="1"/></feComponentTransfer><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>');
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -57,6 +57,28 @@ describe("Paper methods", function () {
|
|||
paper.remove();
|
||||
});
|
||||
|
||||
it("Paper.svg", function() {
|
||||
var c = paper.svg();
|
||||
expect(c.node.nodeName).to.be("svg");
|
||||
expect(c.node.parentNode).to.be(paper.node);
|
||||
});
|
||||
it("Paper.svg(x, y)", function() {
|
||||
var c = paper.svg(100, 200);
|
||||
expect(c.node.nodeName).to.be("svg");
|
||||
expect(c.node.x.baseVal.value).to.be(100);
|
||||
expect(c.node.y.baseVal.value).to.be(200);
|
||||
expect(c.node.parentNode).to.be(paper.node);
|
||||
});
|
||||
it("Paper.svg(x, y, w, h, viewbox)", function() {
|
||||
var c = paper.svg(100, 200, 300, 400, 10, 20, 30, 40);
|
||||
expect(c.node.nodeName).to.be("svg");
|
||||
expect(c.node.x.baseVal.value).to.be(100);
|
||||
expect(c.node.y.baseVal.value).to.be(200);
|
||||
expect(c.node.width.baseVal.value).to.be(300);
|
||||
expect(c.node.height.baseVal.value).to.be(400);
|
||||
expect(c.node.getAttribute("viewBox")).to.be("10 20 30 40");
|
||||
expect(c.node.parentNode).to.be(paper.node);
|
||||
});
|
||||
it("Paper.el", function() {
|
||||
var c = paper.el("circle");
|
||||
expect(c.node.nodeName).to.be("circle");
|
||||
|
|
15
test/path.js
15
test/path.js
|
@ -343,6 +343,9 @@ describe("Path methods", function () {
|
|||
expect(Snap.path.isPointInside(path, 100, 70)).to.be(false);
|
||||
expect(Snap.path.isPointInside(path, 115, 96)).to.be(false);
|
||||
expect(Snap.path.isPointInside(path, 85, 96)).to.be(false);
|
||||
|
||||
// bug #248
|
||||
expect(Snap.path.isPointInside("M1.4315332974182866,4.405806462382467 L57.26133189673147,176.23225849529868 A185.30156250000002,185.30156250000002 0 0 1 -172.2890356108522,-68.21405480708441 L-4.307225890271305,-1.7053513701771101 A4.6325390625,4.6325390625 0 0 0 1.4315332974182866,4.405806462382467 Z", -58.296875, 70.96875)).to.be(true);
|
||||
});
|
||||
|
||||
it("Snap.path.intersection", function () {
|
||||
|
@ -379,19 +382,19 @@ describe("Path methods", function () {
|
|||
checkXY(5, 27.5, 50);
|
||||
checkXY(6, 40, 85.71);
|
||||
checkXY(7, 25.5, 90);
|
||||
checkXY(8, 48.08, 108.79);
|
||||
checkXY(9, 24.45, 110.99);
|
||||
checkXY(8, 48.06, 108.75);
|
||||
checkXY(9, 24.46, 110.77);
|
||||
checkXY(10, 45, 100);
|
||||
checkXY(11, 25, 100);
|
||||
checkXY(12, 23.92, 121.52);
|
||||
checkXY(13, 59.46, 141.32);
|
||||
checkXY(12, 23.91, 121.7);
|
||||
checkXY(13, 59.46, 141.31);
|
||||
checkXY(14, 59, 140);
|
||||
checkXY(15, 23, 140);
|
||||
checkXY(16, 108.53, 24.91);
|
||||
checkXY(16, 108.55, 24.82);
|
||||
checkXY(17, 83.33, 10);
|
||||
checkXY(18, 106, 42);
|
||||
checkXY(19, 104.81, 50);
|
||||
checkXY(20, 97.45, 99.7);
|
||||
checkXY(20, 97.49, 99.44);
|
||||
checkXY(21, 100.37, 80);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -109,4 +109,33 @@ describe("Primitives creation", function () {
|
|||
expect(C.getAttribute("x")).to.be("10");
|
||||
expect(C.textContent).to.be("test");
|
||||
});
|
||||
it("creates a mask", function () {
|
||||
var c = s.mask();
|
||||
var C = document.querySelector("mask");
|
||||
expect(C).to.not.be(null);
|
||||
expect(C).to.be(c.node);
|
||||
});
|
||||
it("creates a pattern", function () {
|
||||
var c = s.ptrn();
|
||||
var C = document.querySelector("pattern");
|
||||
expect(C).to.not.be(null);
|
||||
expect(C).to.be(c.node);
|
||||
});
|
||||
it("creates a pattern(x, y)", function() {
|
||||
var c = s.ptrn(100, 200);
|
||||
expect(c.node.nodeName).to.be("pattern");
|
||||
expect(c.node.x.baseVal.value).to.be(100);
|
||||
expect(c.node.y.baseVal.value).to.be(200);
|
||||
expect(c.node.parentNode).to.be(s.node);
|
||||
});
|
||||
it("creates a pattern(x, y, w, h, viewbox)", function() {
|
||||
var c = s.ptrn(100, 200, 300, 400, 10, 20, 30, 40);
|
||||
expect(c.node.nodeName).to.be("pattern");
|
||||
expect(c.node.x.baseVal.value).to.be(100);
|
||||
expect(c.node.y.baseVal.value).to.be(200);
|
||||
expect(c.node.width.baseVal.value).to.be(300);
|
||||
expect(c.node.height.baseVal.value).to.be(400);
|
||||
expect(c.node.getAttribute("viewBox")).to.be("10 20 30 40");
|
||||
expect(c.node.parentNode).to.be(s.node);
|
||||
});
|
||||
});
|
||||
|
|
45
test/set.js
45
test/set.js
|
@ -82,6 +82,51 @@ describe("Set methods", function () {
|
|||
expect(set[1]).to.be(rect2);
|
||||
expect(set[2]).to.be(rect3);
|
||||
});
|
||||
it("Set.attr", function() {
|
||||
var rect1 = s.rect(10, 20, 30, 40);
|
||||
var rect2 = s.rect(10, 20, 30, 40);
|
||||
var set = Snap.set(rect1, rect2);
|
||||
set.attr({"fill": "#ff0000"});
|
||||
expect(rect1.node.getAttribute("fill")).to.be("#ff0000");
|
||||
expect(rect2.node.getAttribute("fill")).to.be("#ff0000");
|
||||
set.attr({"stroke": "#0000ff"});
|
||||
expect(rect1.node.getAttribute("stroke")).to.be("#0000ff");
|
||||
expect(rect2.node.getAttribute("stroke")).to.be("#0000ff");
|
||||
});
|
||||
it("Set.bind", function() {
|
||||
var rect1 = s.rect(10, 20, 30, 40);
|
||||
var rect2 = s.rect(10, 20, 30, 40);
|
||||
var set = Snap.set(rect1, rect2);
|
||||
|
||||
// Setting "stroke" on set only applies it to rect1
|
||||
set.bind("stroke", rect1);
|
||||
// Setting "fill1" on set maps to fill attribute on rect1
|
||||
set.bind("fill1", rect1, "fill");
|
||||
// Setting "fill2" on set maps to fill attribute on rect2
|
||||
set.bind("fill2", function(v) { rect2.attr({"fill": v}); });
|
||||
|
||||
// Set everything to black
|
||||
rect1.attr({"fill": "#000000", "stroke": "#000000"});
|
||||
rect2.attr({"fill": "#000000", "stroke": "#000000"});
|
||||
|
||||
set.attr({"fill1": "#00ff00"});
|
||||
expect(rect1.node.getAttribute("fill")).to.be("#00ff00");
|
||||
expect(rect2.node.getAttribute("fill")).to.be("#000000");
|
||||
|
||||
// Will trigger the fallback implementation of attr which is
|
||||
// to set that attribute on all elements in the set.
|
||||
set.attr({"fill": "#ff0000"});
|
||||
expect(rect1.node.getAttribute("fill")).to.be("#ff0000");
|
||||
expect(rect2.node.getAttribute("fill")).to.be("#ff0000");
|
||||
|
||||
set.attr({"fill2": "#00ff00"});
|
||||
expect(rect1.node.getAttribute("fill")).to.be("#ff0000");
|
||||
expect(rect2.node.getAttribute("fill")).to.be("#00ff00");
|
||||
|
||||
set.attr({"stroke": "#0000ff"});
|
||||
expect(rect1.node.getAttribute("stroke")).to.be("#0000ff");
|
||||
expect(rect2.node.getAttribute("stroke")).to.be("#000000");
|
||||
});
|
||||
it("Set.splice - remove only", function() {
|
||||
var rect1 = s.rect(10, 20, 30, 40);
|
||||
var rect2 = s.rect(10, 20, 30, 40);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.">
|
||||
<title>Savage Tests</title>
|
||||
<title>Snap Tests</title>
|
||||
<style media="screen">
|
||||
svg {
|
||||
position: absolute;
|
||||
|
@ -28,15 +28,17 @@
|
|||
</head>
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
<script src="../node_modules/expect.js/expect.js"></script>
|
||||
<script src="../node_modules/expect.js/index.js"></script>
|
||||
<script src="../node_modules/mocha/mocha.js"></script>
|
||||
<script>mocha.setup("bdd");</script>
|
||||
<script src="system.js"></script>
|
||||
<script src="paper.js"></script>
|
||||
<script src="snap-tests.js"></script>
|
||||
<script src="class.js"></script>
|
||||
<script src="primitives.js"></script>
|
||||
<script src="colors.js"></script>
|
||||
<script src="attrs.js"></script>
|
||||
<script src="attradd.js"></script>
|
||||
<script src="path.js"></script>
|
||||
<script src="element.js"></script>
|
||||
<script src="set.js"></script>
|
||||
|
|
Loading…
Reference in New Issue