Browse Source

fix a few mistakes. Make sugar work. Roll back to childNodes because children is 10x slower

tags/3.0.0
Ulrich-Matthias Schäfer 5 years ago
parent
commit
c40d7ffdfb
10 changed files with 441 additions and 214 deletions
  1. 4
    11
      bench/runner.html
  2. 92
    99
      bench/tests/10000-rects.js
  3. 263
    74
      dist/svg.js
  4. 1
    1
      dist/svg.min.js
  5. 1
    1
      src/Element.js
  6. 8
    6
      src/Parent.js
  7. 47
    14
      src/elemnts-svg.js
  8. 10
    2
      src/methods.js
  9. 7
    6
      src/sugar.js
  10. 8
    0
      src/svg.js

+ 4
- 11
bench/runner.html View File

<div id="draw"></div> <div id="draw"></div>
<svg id="native" width="100" height="100" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs"></svg> <svg id="native" width="100" height="100" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs"></svg>
<script src="../dist/svg.js"></script> <script src="../dist/svg.js"></script>
<script type="text/javascript" src="../src/helpers.js"></script>
<script type="text/javascript" src="../src/transform.js"></script>
<script type="text/javascript" src="../src/matrix.js"></script>
<script type="text/javascript" src="../src/morph.js"></script>
<script type="text/javascript" src="../src/runner.js"></script>
<script type="text/javascript" src="../src/timeline.js"></script>
<script type="text/javascript" src="../src/controller.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script>
<script src="svg.bench.js"></script> <script src="svg.bench.js"></script>
<!--<script src="tests/10000-each.js"></script> --> <!--<script src="tests/10000-each.js"></script> -->
<!-- <script src="tests/10000-rects.js"></script>
<script src="tests/10000-circles.js"></script>
<script src="tests/10000-rects.js"></script>
<!-- <script src="tests/10000-circles.js"></script>
<script src="tests/10000-paths.js"></script> <script src="tests/10000-paths.js"></script>
<script src="tests/10000-boxes.js"></script> <script src="tests/10000-boxes.js"></script>
<script src="tests/10000-pointArray-bbox.js"></script> <script src="tests/10000-pointArray-bbox.js"></script>
<script src="tests/10000-accesses.js"></script> -->
<script src="tests/10000-transform.js"></script>
<script src="tests/10000-accesses.js"></script>
<script src="tests/10000-transform.js"></script> -->
<script> <script>
SVG.bench.run() SVG.bench.run()
</script> </script>

+ 92
- 99
bench/tests/10000-rects.js View File

}) })
}) })



SVG.bench.describe('Generate 10000 rects with fill', function(bench) {
bench.test('using SVG.js v2.5.3', function() {
for (var i = 0; i < 10000; i++)
bench.draw.rect(100,100).fill('#f06')
})
bench.test('using vanilla js', function() {
for (var i = 0; i < 10000; i++) {
var rect = document.createElementNS(SVG.ns, 'rect')
rect.setAttributeNS(null, 'height', 100)
rect.setAttributeNS(null, 'width', 100)
rect.setAttributeNS(null, 'fill', '#f06')
bench.raw.appendChild(rect)
}
})
bench.test('using Snap.svg v0.5.1', function() {
for (var i = 0; i < 10000; i++)
bench.snap.rect(50, 50, 100, 100).attr('fill', '#f06')
})
})


SVG.bench.describe('Generate 10000 rects with position and fill', function(bench) {
bench.test('using SVG.js v2.5.3', function() {
for (var i = 0; i < 10000; i++)
bench.draw.rect(100,100).move(50,50).fill('#f06')
})
bench.test('using vanilla js', function() {
for (var i = 0; i < 10000; i++) {
var rect = document.createElementNS(SVG.ns, 'rect')
rect.setAttributeNS(null, 'height', 100)
rect.setAttributeNS(null, 'width', 100)
rect.setAttributeNS(null, 'fill', '#f06')
rect.setAttributeNS(null, 'x', 50)
rect.setAttributeNS(null, 'y', 50)
bench.raw.appendChild(rect)
}
})
bench.test('using Snap.svg v0.5.1', function() {
for (var i = 0; i < 10000; i++)
bench.snap.rect(50, 50, 100, 100).attr('fill', '#f06')
})
})


SVG.bench.describe('Generate 10000 rects with gradient fill', function(bench) {
bench.test('using SVG.js v2.5.3', function() {
for (var i = 0; i < 10000; i++) {
var g = bench.draw.gradient('linear', function(add) {
add.stop(0, '#000')
add.stop(0.25, '#f00')
add.stop(1, '#fff')
})

bench.draw.rect(100,100).fill(g)
}
})
bench.test('using vanilla js', function() {
for (var i = 0; i < 10000; i++) {
var g = document.createElementNS(SVG.ns, 'linearGradient')
var stop = document.createElementNS(SVG.ns, 'stop')
stop.setAttributeNS(null, 'offset', '0%')
stop.setAttributeNS(null, 'color', '#000')
g.appendChild(stop)
stop = document.createElementNS(SVG.ns, 'stop')
stop.setAttributeNS(null, 'offset', '25%')
stop.setAttributeNS(null, 'color', '#f00')
g.appendChild(stop)
stop = document.createElementNS(SVG.ns, 'stop')
stop.setAttributeNS(null, 'offset', '100%')
stop.setAttributeNS(null, 'color', '#fff')
g.appendChild(stop)
bench.raw.appendChild(g)

var rect = document.createElementNS(SVG.ns, 'rect')
rect.setAttributeNS(null, 'height', 100)
rect.setAttributeNS(null, 'width', 100)
rect.setAttributeNS(null, 'fill', '#f06')
bench.raw.appendChild(rect)
}
})
bench.test('using Snap.svg v0.5.1', function() {
for (var i = 0; i < 10000; i++) {
var g = bench.snap.gradient("L(0, 0, 100, 100)#000-#f00:25%-#fff")

bench.snap.rect(50, 50, 100, 100).attr({
fill: g
})
}
})
})








//
// SVG.bench.describe('Generate 10000 rects with fill', function(bench) {
// bench.test('using SVG.js v2.5.3', function() {
// for (var i = 0; i < 10000; i++)
// bench.draw.rect(100,100).fill('#f06')
// })
// bench.test('using vanilla js', function() {
// for (var i = 0; i < 10000; i++) {
// var rect = document.createElementNS(SVG.ns, 'rect')
// rect.setAttributeNS(null, 'height', 100)
// rect.setAttributeNS(null, 'width', 100)
// rect.setAttributeNS(null, 'fill', '#f06')
// bench.raw.appendChild(rect)
// }
// })
// bench.test('using Snap.svg v0.5.1', function() {
// for (var i = 0; i < 10000; i++)
// bench.snap.rect(50, 50, 100, 100).attr('fill', '#f06')
// })
// })
//
//
// SVG.bench.describe('Generate 10000 rects with position and fill', function(bench) {
// bench.test('using SVG.js v2.5.3', function() {
// for (var i = 0; i < 10000; i++)
// bench.draw.rect(100,100).move(50,50).fill('#f06')
// })
// bench.test('using vanilla js', function() {
// for (var i = 0; i < 10000; i++) {
// var rect = document.createElementNS(SVG.ns, 'rect')
// rect.setAttributeNS(null, 'height', 100)
// rect.setAttributeNS(null, 'width', 100)
// rect.setAttributeNS(null, 'fill', '#f06')
// rect.setAttributeNS(null, 'x', 50)
// rect.setAttributeNS(null, 'y', 50)
// bench.raw.appendChild(rect)
// }
// })
// bench.test('using Snap.svg v0.5.1', function() {
// for (var i = 0; i < 10000; i++)
// bench.snap.rect(50, 50, 100, 100).attr('fill', '#f06')
// })
// })
//
//
// SVG.bench.describe('Generate 10000 rects with gradient fill', function(bench) {
// bench.test('using SVG.js v2.5.3', function() {
// for (var i = 0; i < 10000; i++) {
// var g = bench.draw.gradient('linear', function(add) {
// add.stop(0, '#000')
// add.stop(0.25, '#f00')
// add.stop(1, '#fff')
// })
//
// bench.draw.rect(100,100).fill(g)
// }
// })
// bench.test('using vanilla js', function() {
// for (var i = 0; i < 10000; i++) {
// var g = document.createElementNS(SVG.ns, 'linearGradient')
// var stop = document.createElementNS(SVG.ns, 'stop')
// stop.setAttributeNS(null, 'offset', '0%')
// stop.setAttributeNS(null, 'color', '#000')
// g.appendChild(stop)
// stop = document.createElementNS(SVG.ns, 'stop')
// stop.setAttributeNS(null, 'offset', '25%')
// stop.setAttributeNS(null, 'color', '#f00')
// g.appendChild(stop)
// stop = document.createElementNS(SVG.ns, 'stop')
// stop.setAttributeNS(null, 'offset', '100%')
// stop.setAttributeNS(null, 'color', '#fff')
// g.appendChild(stop)
// bench.raw.appendChild(g)
//
// var rect = document.createElementNS(SVG.ns, 'rect')
// rect.setAttributeNS(null, 'height', 100)
// rect.setAttributeNS(null, 'width', 100)
// rect.setAttributeNS(null, 'fill', '#f06')
// bench.raw.appendChild(rect)
// }
// })
// bench.test('using Snap.svg v0.5.1', function() {
// for (var i = 0; i < 10000; i++) {
// var g = bench.snap.gradient("L(0, 0, 100, 100)#000-#f00:25%-#fff")
//
// bench.snap.rect(50, 50, 100, 100).attr({
// fill: g
// })
// }
// })
// })
//

+ 263
- 74
dist/svg.js View File

var methods = {}; var methods = {};
var constructors = {}; var constructors = {};
function registerMethods(name, m) { function registerMethods(name, m) {
if (Array.isArray(name)) {
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;

try {
for (var _iterator = name[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _name = _step.value;
registerMethods(_name, m);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}

return;
}

if (_typeof(name) == 'object') { if (_typeof(name) == 'object') {
var _arr = Object.entries(name); var _arr = Object.entries(name);


for (var _i = 0; _i < _arr.length; _i++) { for (var _i = 0; _i < _arr.length; _i++) {
var _arr$_i = _slicedToArray(_arr[_i], 2), var _arr$_i = _slicedToArray(_arr[_i], 2),
_name = _arr$_i[0],
_name2 = _arr$_i[0],
_m = _arr$_i[1]; _m = _arr$_i[1];


registerMethods(_name, _m);
registerMethods(_name2, _m);
} }

return;
} }


methods[name] = Object.assign(methods[name] || {}, m); methods[name] = Object.assign(methods[name] || {}, m);
} }
function getMethodsFor(name) { function getMethodsFor(name) {
return methods[name];
return methods[name] || {};
} // FIXME: save memory? } // FIXME: save memory?
function registerConstructor(name, setup) { function registerConstructor(name, setup) {
constructors[name] = setup; constructors[name] = setup;
} }
function getConstructor(name) { function getConstructor(name) {
return {
return constructors[name] ? {
setup: constructors[name], setup: constructors[name],
name: name name: name
};
} : {};
} }


var Doc$1 = var Doc$1 =
} }
}); });


var SVGNumber =
var SVGNumber$1 =
/*#__PURE__*/ /*#__PURE__*/
function () { function () {
// Initialize // Initialize
} // Set width of element } // Set width of element


function width(width) { function width(width) {
return width == null ? this.rx() * 2 : this.rx(new SVGNumber(width).divide(2));
return width == null ? this.rx() * 2 : this.rx(new SVGNumber$1(width).divide(2));
} // Set height of element } // Set height of element


function height(height) { function height(height) {
return height == null ? this.ry() * 2 : this.ry(new SVGNumber(height).divide(2));
return height == null ? this.ry() * 2 : this.ry(new SVGNumber$1(height).divide(2));
} // Custom size function } // Custom size function


function size(width, height) { function size(width, height) {
var p = proportionalSize$1(this, width, height); var p = proportionalSize$1(this, width, height);
return this.rx(new SVGNumber(p.width).divide(2)).ry(new SVGNumber(p.height).divide(2));
return this.rx(new SVGNumber$1(p.width).divide(2)).ry(new SVGNumber$1(p.height).divide(2));
} }


var circled = /*#__PURE__*/Object.freeze({ var circled = /*#__PURE__*/Object.freeze({
Element: { Element: {
// Create circle element // Create circle element
circle: function circle(size$$1) { circle: function circle(size$$1) {
return this.put(new Circle()).radius(new SVGNumber(size$$1).divide(2)).move(0, 0);
return this.put(new Circle()).radius(new SVGNumber$1(size$$1).divide(2)).move(0, 0);
} }
} }
}); });


function size$1(width, height) { function size$1(width, height) {
var p = proportionalSize$1(this, width, height); var p = proportionalSize$1(this, width, height);
return this.width(new SVGNumber(p.width)).height(new SVGNumber(p.height));
return this.width(new SVGNumber$1(p.width)).height(new SVGNumber$1(p.height));
} // Clone element } // Clone element


function clone(parent) { function clone(parent) {
return element; return element;
} // Add element to given container and return self } // Add element to given container and return self


function addTo(parent) {
return makeInstance(parent).put(this);
} // Add element to given container and return container

function putIn(parent) { function putIn(parent) {
return makeInstance(parent).add(this); return makeInstance(parent).add(this);
} // Get / set id } // Get / set id
clone: clone, clone: clone,
remove: remove, remove: remove,
replace: replace, replace: replace,
addTo: addTo,
putIn: putIn, putIn: putIn,
id: id$1, id: id$1,
inside: inside, inside: inside,
_createClass(Stop, [{ _createClass(Stop, [{
key: "update", key: "update",
value: function update(o) { value: function update(o) {
if (typeof o === 'number' || o instanceof SVGNumber) {
if (typeof o === 'number' || o instanceof SVGNumber$1) {
o = { o = {
offset: arguments[0], offset: arguments[0],
color: arguments[1], color: arguments[1],


if (o.opacity != null) this.attr('stop-opacity', o.opacity); if (o.opacity != null) this.attr('stop-opacity', o.opacity);
if (o.color != null) this.attr('stop-color', o.color); if (o.color != null) this.attr('stop-color', o.color);
if (o.offset != null) this.attr('offset', new SVGNumber(o.offset));
if (o.offset != null) this.attr('offset', new SVGNumber$1(o.offset));
return this; return this;
} }
}]); }]);
// FIXME: add to runner // FIXME: add to runner
function from(x, y) { function from(x, y) {
return (this._element || this).type === 'radialGradient' ? this.attr({ return (this._element || this).type === 'radialGradient' ? this.attr({
fx: new SVGNumber(x),
fy: new SVGNumber(y)
fx: new SVGNumber$1(x),
fy: new SVGNumber$1(y)
}) : this.attr({ }) : this.attr({
x1: new SVGNumber(x),
y1: new SVGNumber(y)
x1: new SVGNumber$1(x),
y1: new SVGNumber$1(y)
}); });
} }
function to(x, y) { function to(x, y) {
return (this._element || this).type === 'radialGradient' ? this.attr({ return (this._element || this).type === 'radialGradient' ? this.attr({
cx: new SVGNumber(x),
cy: new SVGNumber(y)
cx: new SVGNumber$1(x),
cy: new SVGNumber$1(y)
}) : this.attr({ }) : this.attr({
x2: new SVGNumber(x),
y2: new SVGNumber(y)
x2: new SVGNumber$1(x),
y2: new SVGNumber$1(y)
}); });
} }






if (typeof val === 'number') { if (typeof val === 'number') {
val = new SVGNumber(val);
val = new SVGNumber$1(val);
} else if (Color.isColor(val)) { } else if (Color.isColor(val)) {
// ensure full hex color // ensure full hex color
val = new Color(val); val = new Color(val);
return parser.nodes; return parser.nodes;
} }


var Point =
var Point$1 =
/*#__PURE__*/ /*#__PURE__*/
function () { function () {
// Initialize // Initialize
Element: { Element: {
// Get point // Get point
point: function point(x, y) { point: function point(x, y) {
return new Point(x, y).transform(this.screenCTM().inverse());
return new Point$1(x, y).transform(this.screenCTM().inverse());
} }
} }
}); });




var result = []; var result = [];
var p = new Point();
var p0 = new Point();
var p = new Point$1();
var p0 = new Point$1();
var index = 0; var index = 0;
var len = array.length; var len = array.length;


_classCallCheck(this, Text); _classCallCheck(this, Text);


_this = _possibleConstructorReturn(this, _getPrototypeOf(Text).call(this, nodeOrNew$1('text', node), Text)); _this = _possibleConstructorReturn(this, _getPrototypeOf(Text).call(this, nodeOrNew$1('text', node), Text));
_this.dom.leading = new SVGNumber(1.3); // store leading value for rebuilding
_this.dom.leading = new SVGNumber$1(1.3); // store leading value for rebuilding


_this._rebuild = true; // enable automatic updating of dy values _this._rebuild = true; // enable automatic updating of dy values


} // act as setter } // act as setter




this.dom.leading = new SVGNumber(value);
this.dom.leading = new SVGNumber$1(value);
return this.rebuild(); return this.rebuild();
} // Rebuild appearance type } // Rebuild appearance type


if (this._rebuild) { if (this._rebuild) {
var self = this; var self = this;
var blankLineOffset = 0; var blankLineOffset = 0;
var dy = this.dom.leading * new SVGNumber(this.attr('font-size'));
var dy = this.dom.leading * new SVGNumber$1(this.attr('font-size'));
this.each(function () { this.each(function () {
if (this.dom.newLined) { if (this.dom.newLined) {
this.attr('x', self.attr('x')); this.attr('x', self.attr('x'));
key: "setData", key: "setData",
value: function setData(o) { value: function setData(o) {
this.dom = o; this.dom = o;
this.dom.leading = new SVGNumber(o.leading || 1.3);
this.dom.leading = new SVGNumber$1(o.leading || 1.3);
return this; return this;
} }
}]); }]);
}); });
register(Use); register(Use);


var Matrix =
var Matrix$1 =
/*#__PURE__*/ /*#__PURE__*/
function () { function () {
function Matrix() { function Matrix() {
var t = Matrix.formatTransforms(o); var t = Matrix.formatTransforms(o);
var current = this; var current = this;


var _transform = new Point(t.ox, t.oy).transform(current),
var _transform = new Point$1(t.ox, t.oy).transform(current),
ox = _transform.x, ox = _transform.x,
oy = _transform.y; // Construct the resulting matrix oy = _transform.y; // Construct the resulting matrix


var transformer = new Matrix().translateO(t.rx, t.ry).lmultiplyO(current).translateO(-ox, -oy).scaleO(t.scaleX, t.scaleY).skewO(t.skewX, t.skewY).shearO(t.shear).rotateO(t.theta).translateO(ox, oy); // If we want the origin at a particular place, we force it there var transformer = new Matrix().translateO(t.rx, t.ry).lmultiplyO(current).translateO(-ox, -oy).scaleO(t.scaleX, t.scaleY).skewO(t.skewX, t.skewY).shearO(t.shear).rotateO(t.theta).translateO(ox, oy); // If we want the origin at a particular place, we force it there


if (isFinite(t.px) || isFinite(t.py)) { if (isFinite(t.px) || isFinite(t.py)) {
var origin = new Point(ox, oy).transform(transformer); // TODO: Replace t.px with isFinite(t.px)
var origin = new Point$1(ox, oy).transform(transformer); // TODO: Replace t.px with isFinite(t.px)


var dx = t.px ? t.px - origin.x : 0; var dx = t.px ? t.px - origin.x : 0;
var dy = t.py ? t.py - origin.y : 0; var dy = t.py ? t.py - origin.y : 0;
var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY : isFinite(o.scale) ? o.scale * flipY : isFinite(o.scaleY) ? o.scaleY * flipY : flipY; var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY : isFinite(o.scale) ? o.scale * flipY : isFinite(o.scaleY) ? o.scaleY * flipY : flipY;
var shear = o.shear || 0; var shear = o.shear || 0;
var theta = o.rotate || o.theta || 0; var theta = o.rotate || o.theta || 0;
var origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY);
var origin = new Point$1(o.origin || o.around || o.ox || o.originX, o.oy || o.originY);
var ox = origin.x; var ox = origin.x;
var oy = origin.y; var oy = origin.y;
var position = new Point(o.position || o.px || o.positionX, o.py || o.positionY);
var position = new Point$1(o.position || o.px || o.positionX, o.py || o.positionY);
var px = position.x; var px = position.x;
var py = position.y; var py = position.y;
var translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY);
var translate = new Point$1(o.translate || o.tx || o.translateX, o.ty || o.translateY);
var tx = translate.x; var tx = translate.x;
var ty = translate.y; var ty = translate.y;
var relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY);
var relative = new Point$1(o.relative || o.rx || o.relativeX, o.ry || o.relativeY);
var rx = relative.x; var rx = relative.x;
var ry = relative.y; // Populate all of the values var ry = relative.y; // Populate all of the values


Element: { Element: {
// Get current matrix // Get current matrix
ctm: function ctm() { ctm: function ctm() {
return new Matrix(this.node.getCTM());
return new Matrix$1(this.node.getCTM());
}, },
// Get current screen matrix // Get current screen matrix
screenCTM: function screenCTM() { screenCTM: function screenCTM() {
var rect = this.rect(1, 1); var rect = this.rect(1, 1);
var m = rect.node.getScreenCTM(); var m = rect.node.getScreenCTM();
rect.remove(); rect.remove();
return new Matrix(m);
return new Matrix$1(m);
} }


return new Matrix(this.node.getScreenCTM());
return new Matrix$1(this.node.getScreenCTM());
} }
} }
}); });
var xMax = -Infinity; var xMax = -Infinity;
var yMin = Infinity; var yMin = Infinity;
var yMax = -Infinity; var yMax = -Infinity;
var pts = [new Point(this.x, this.y), new Point(this.x2, this.y), new Point(this.x, this.y2), new Point(this.x2, this.y2)];
var pts = [new Point$1(this.x, this.y), new Point$1(this.x2, this.y), new Point$1(this.x, this.y2), new Point$1(this.x2, this.y2)];
pts.forEach(function (p) { pts.forEach(function (p) {
p = p.transform(m); p = p.transform(m);
xMin = Math.min(xMin, p.x); xMin = Math.min(xMin, p.x);
var type = _typeof(value); var type = _typeof(value);


if (type === 'number') { if (type === 'number') {
this.type(SVGNumber);
this.type(SVGNumber$1);
} else if (type === 'string') { } else if (type === 'string') {
if (Color.isColor(value)) { if (Color.isColor(value)) {
this.type(Color); this.type(Color);
} else if (regex.delimiter.test(value)) { } else if (regex.delimiter.test(value)) {
this.type(regex.pathLetters.test(value) ? PathArray : SVGArray); this.type(regex.pathLetters.test(value) ? PathArray : SVGArray);
} else if (regex.numberAndUnit.test(value)) { } else if (regex.numberAndUnit.test(value)) {
this.type(SVGNumber);
this.type(SVGNumber$1);
} else { } else {
this.type(Morphable.NonMorphable); this.type(Morphable.NonMorphable);
} }
return _class3; return _class3;
}(); }();


var morphableTypes = [SVGNumber, Color, Box$1, Matrix, SVGArray, PointArray$1, PathArray, Morphable.NonMorphable, Morphable.TransformBag, Morphable.ObjectBag];
var morphableTypes = [SVGNumber$1, Color, Box$1, Matrix$1, SVGArray, PointArray$1, PathArray, Morphable.NonMorphable, Morphable.TransformBag, Morphable.ObjectBag];
extend$1(morphableTypes, { extend$1(morphableTypes, {
to: function to(val, args) { to: function to(val, args) {
return new Morphable().type(this.constructor).from(this.valueOf()).to(val, args); return new Morphable().type(this.constructor).from(this.valueOf()).to(val, args);
// '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 } // '<': function (pos) { return -Math.cos(pos * Math.PI / 2) + 1 }
// } // }


var Runner =
var Runner$1 =
/*#__PURE__*/ /*#__PURE__*/
function () { function () {
function Runner(options) { function Runner(options) {
this._time = 0; this._time = 0;
this._last = 0; // Save transforms applied to this runner this._last = 0; // Save transforms applied to this runner


this.transforms = new Matrix();
this.transforms = new Matrix$1();
this.transformId = 1; // Looping variables this.transformId = 1; // Looping variables


this._haveReversed = false; this._haveReversed = false;
this._initialise(running); // clear the transforms on this runner so they dont get added again and again this._initialise(running); // clear the transforms on this runner so they dont get added again and again




this.transforms = new Matrix();
this.transforms = new Matrix$1();


var converged = this._run(declarative ? dt : position); // this.fire('step', this) var converged = this._run(declarative ? dt : position); // this.fire('step', this)


}, { }, {
key: "clearTransform", key: "clearTransform",
value: function clearTransform() { value: function clearTransform() {
this.transforms = new Matrix();
this.transforms = new Matrix$1();
return this; return this;
} }
}], [{ }], [{


return Runner; return Runner;
}(); }();
Runner.id = 0;
Runner$1.id = 0;


var FakeRunner = function FakeRunner() { var FakeRunner = function FakeRunner() {
var transforms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Matrix();
var transforms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Matrix$1();
var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1; var id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1;
var done = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var done = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;


this.done = done; this.done = done;
}; };


extend$1([Runner, FakeRunner], {
extend$1([Runner$1, FakeRunner], {
mergeWith: function mergeWith(runner) { mergeWith: function mergeWith(runner) {
return new FakeRunner(runner.transforms.lmultiply(this.transforms), runner.id); return new FakeRunner(runner.transforms.lmultiply(this.transforms), runner.id);
} }
function mergeTransforms() { function mergeTransforms() {
// Find the matrix to apply to the element and apply it // Find the matrix to apply to the element and apply it
var runners = this._transformationRunners.runners; var runners = this._transformationRunners.runners;
var netTransform = runners.map(getRunnerTransform).reduce(lmultiply, new Matrix());
var netTransform = runners.map(getRunnerTransform).reduce(lmultiply, new Matrix$1());
this.transform(netTransform); this.transform(netTransform);


this._transformationRunners.merge(); this._transformationRunners.merge();
registerMethods({ registerMethods({
Element: { Element: {
animate: function animate(duration, delay, when) { animate: function animate(duration, delay, when) {
var o = Runner.sanitise(duration, delay, when);
var o = Runner$1.sanitise(duration, delay, when);
var timeline$$1 = this.timeline(); var timeline$$1 = this.timeline();
return new Runner(o.duration).loop(o).element(this).timeline(timeline$$1).schedule(delay, when);
return new Runner$1(o.duration).loop(o).element(this).timeline(timeline$$1).schedule(delay, when);
}, },
delay: function delay(by, when) { delay: function delay(by, when) {
return this.animate(0, by, when); return this.animate(0, by, when);
// taken into account // taken into account
.filter(function (runner) { .filter(function (runner) {
return runner.id <= current.id; return runner.id <= current.id;
}).map(getRunnerTransform).reduce(lmultiply, new Matrix());
}).map(getRunnerTransform).reduce(lmultiply, new Matrix$1());
}, },
addRunner: function addRunner(runner) { addRunner: function addRunner(runner) {
this._transformationRunners.add(runner); this._transformationRunners.add(runner);
}, },
_prepareRunner: function _prepareRunner() { _prepareRunner: function _prepareRunner() {
if (this._frameId == null) { if (this._frameId == null) {
this._transformationRunners = new RunnerArray().add(new FakeRunner(new Matrix(this)));
this._transformationRunners = new RunnerArray().add(new FakeRunner(new Matrix$1(this)));
this._frameId = frameId++; this._frameId = frameId++;
} }
} }
} }
}); });
extend$1(Runner, {
extend$1(Runner$1, {
attr: function attr(a, v) { attr: function attr(a, v) {
return this.styleAttr('attr', a, v); return this.styleAttr('attr', a, v);
}, },
return this; return this;
}, },
zoom: function zoom(level, point) { zoom: function zoom(level, point) {
var morpher = new Morphable(this._stepper).to(new SVGNumber(level));
var morpher = new Morphable(this._stepper).to(new SVGNumber$1(level));
this.queue(function () { this.queue(function () {
morpher = morpher.from(this.zoom()); morpher = morpher.from(this.zoom());
}, function (pos) { }, function (pos) {
var isMatrix = isMatrixLike(transforms); var isMatrix = isMatrixLike(transforms);
affine = transforms.affine != null ? transforms.affine : affine != null ? affine : !isMatrix; // Create a morepher and set its type affine = transforms.affine != null ? transforms.affine : affine != null ? affine : !isMatrix; // Create a morepher and set its type


var morpher = new Morphable().type(affine ? Morphable.TransformBag : Matrix).stepper(this._stepper);
var morpher = new Morphable().type(affine ? Morphable.TransformBag : Matrix$1).stepper(this._stepper);
var origin; var origin;
var element; var element;
var current; var current;
// make sure element and origin is defined // make sure element and origin is defined
element = element || this.element(); element = element || this.element();
origin = origin || getOrigin(transforms, element); origin = origin || getOrigin(transforms, element);
startTransform = new Matrix(relative ? undefined : element); // add the runner to the element so it can merge transformations
startTransform = new Matrix$1(relative ? undefined : element); // add the runner to the element so it can merge transformations


element.addRunner(this); // Deactivate all transforms that have run so far if we are absolute element.addRunner(this); // Deactivate all transforms that have run so far if we are absolute


// on this runner. We are absolute. We dont need these! // on this runner. We are absolute. We dont need these!
if (!relative) this.clearTransform(); if (!relative) this.clearTransform();


var _transform = new Point(origin).transform(element._currentTransform(this)),
var _transform = new Point$1(origin).transform(element._currentTransform(this)),
x = _transform.x, x = _transform.x,
y = _transform.y; y = _transform.y;


var target = new Matrix(_objectSpread({}, transforms, {
var target = new Matrix$1(_objectSpread({}, transforms, {
origin: [x, y] origin: [x, y]
})); }));
var start = this._isDeclarative && current ? current : startTransform; var start = this._isDeclarative && current ? current : startTransform;
morpher.to(target); morpher.to(target);
var affineParameters = morpher.at(pos); var affineParameters = morpher.at(pos);
currentAngle = affineParameters.rotate; currentAngle = affineParameters.rotate;
current = new Matrix(affineParameters);
current = new Matrix$1(affineParameters);
this.addTransform(current); this.addTransform(current);
return morpher.done(); return morpher.done();
} }
return this._queueNumberDelta('dy', y); return this._queueNumberDelta('dy', y);
}, },
_queueNumberDelta: function _queueNumberDelta(method, to) { _queueNumberDelta: function _queueNumberDelta(method, to) {
to = new SVGNumber(to); // Try to change the target if we have this method already registerd
to = new SVGNumber$1(to); // Try to change the target if we have this method already registerd


if (this._tryRetargetDelta(method, to)) return this; // Make a morpher and queue the animation if (this._tryRetargetDelta(method, to)) return this; // Make a morpher and queue the animation


return this; return this;
}, },
_queueNumber: function _queueNumber(method, value) { _queueNumber: function _queueNumber(method, value) {
return this._queueObject(method, new SVGNumber(value));
return this._queueObject(method, new SVGNumber$1(value));
}, },
// Animatable center x-axis // Animatable center x-axis
cx: function cx(x) { cx: function cx(x) {
TextPath: TextPath, TextPath: TextPath,
Tspan: Tspan, Tspan: Tspan,
Use: Use, Use: Use,
SVGNumber: SVGNumber,
SVGNumber: SVGNumber$1,
SVGArray: SVGArray, SVGArray: SVGArray,
PathArray: PathArray, PathArray: PathArray,
PointArray: PointArray$1, PointArray: PointArray$1,
Matrix: Matrix,
Point: Point,
Matrix: Matrix$1,
Point: Point$1,
Box: Box$1, Box: Box$1,
Color: Color, Color: Color,
Morphable: Morphable, Morphable: Morphable,
Queue: Queue, Queue: Queue,
Runner: Runner,
Runner: Runner$1,
Timeline: Timeline, Timeline: Timeline,
Controller: Controller, Controller: Controller,
Ease: Ease, Ease: Ease,
} }


return matrix[transform[0]].apply(matrix, transform[1]); return matrix[transform[0]].apply(matrix, transform[1]);
}, new Matrix());
}, new Matrix$1());
return matrix; return matrix;
} // add an element to another parent without changing the visual representation on the screen } // add an element to another parent without changing the visual representation on the screen


function transform(o, relative) { function transform(o, relative) {
// Act as a getter if no object was passed // Act as a getter if no object was passed
if (o == null || typeof o === 'string') { if (o == null || typeof o === 'string') {
var decomposed = new Matrix(this).decompose();
var decomposed = new Matrix$1(this).decompose();
return decomposed[o] || decomposed; return decomposed[o] || decomposed;
} }






var cleanRelative = relative === true ? this : relative || false; var cleanRelative = relative === true ? this : relative || false;
var result = new Matrix(cleanRelative).transform(o);
var result = new Matrix$1(cleanRelative).transform(o);
return this.attr('transform', result); return this.attr('transform', result);
} }
registerMethods('Element', { registerMethods('Element', {
}); });
registerConstructor('Memory', setup$1); registerConstructor('Memory', setup$1);


var sugar = {
stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'],
fill: ['color', 'opacity', 'rule'],
prefix: function prefix(t, a) {
return a === 'color' ? t : t + '-' + a;
} // Add sugar for fill and stroke

};
['fill', 'stroke'].forEach(function (m) {
var extension = {};
var i;

extension[m] = function (o) {
if (typeof o === 'undefined') {
return this;
}

if (typeof o === 'string' || Color.isRgb(o) || o && typeof o.fill === 'function') {
this.attr(m, o);
} else {
// set all attributes from sugar.fill and sugar.stroke list
for (i = sugar[m].length - 1; i >= 0; i--) {
if (o[sugar[m][i]] != null) {
this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]]);
}
}
}

return this;
};

registerMethods(['Element', 'Runner'], extension);
});
registerMethods(['Element', 'Runner'], {
// Let the user set the matrix directly
matrix: function matrix(mat, b, c, d, e, f) {
// Act as a getter
if (mat == null) {
return new Matrix(this);
} // Act as a setter, the user can pass a matrix or a set of numbers


return this.attr('transform', new Matrix(mat, b, c, d, e, f));
},
// Map rotation to transform
rotate: function rotate(angle, cx, cy) {
return this.transform({
rotate: angle,
ox: cx,
oy: cy
}, true);
},
// Map skew to transform
skew: function skew(x, y, cx, cy) {
return arguments.length === 1 || arguments.length === 3 ? this.transform({
skew: x,
ox: y,
oy: cx
}, true) : this.transform({
skew: [x, y],
ox: cx,
oy: cy
}, true);
},
shear: function shear(lam, cx, cy) {
return this.transform({
shear: lam,
ox: cx,
oy: cy
}, true);
},
// Map scale to transform
scale: function scale(x, y, cx, cy) {
return arguments.length === 1 || arguments.length === 3 ? this.transform({
scale: x,
ox: y,
oy: cx
}, true) : this.transform({
scale: [x, y],
ox: cx,
oy: cy
}, true);
},
// Map translate to transform
translate: function translate(x, y) {
return this.transform({
translate: [x, y]
}, true);
},
// Map relative translations to transform
relative: function relative(x, y) {
return this.transform({
relative: [x, y]
}, true);
},
// Map flip to transform
flip: function flip(direction, around) {
var directionString = typeof direction === 'string' ? direction : isFinite(direction) ? 'both' : 'both';
var origin = direction === 'both' && isFinite(around) ? [around, around] : direction === 'x' ? [around, 0] : direction === 'y' ? [0, around] : isFinite(direction) ? [direction, direction] : [0, 0];
this.transform({
flip: directionString,
origin: origin
}, true);
},
// Opacity
opacity: function opacity(value) {
return this.attr('opacity', value);
},
// Relative move over x axis
dx: function dx(x) {
return this.x(new SVGNumber(x).plus(this instanceof Runner ? 0 : this.x()), true);
},
// Relative move over y axis
dy: function dy(y) {
return this.y(new SVGNumber(y).plus(this instanceof Runner ? 0 : this.y()), true);
},
// Relative move over x and y axes
dmove: function dmove(x, y) {
return this.dx(x).dy(y);
}
});
registerMethods('radius', {
// Add x and y radius
radius: function radius(x, y) {
var type = (this._target || this).type;
return type === 'radialGradient' || type === 'radialGradient' ? this.attr('r', new SVGNumber(x)) : this.rx(x).ry(y == null ? x : y);
}
});
registerMethods('Path', {
// Get path length
length: function length() {
return this.node.getTotalLength();
},
// Get point at length
pointAt: function pointAt(length) {
return new Point(this.node.getPointAtLength(length));
}
});
registerMethods(['Container', 'Runner'], {
// Set font
font: function font(a, v) {
if (_typeof(a) === 'object') {
for (v in a) {
this.font(v, a[v]);
}
}

return a === 'leading' ? this.leading(v) : a === 'anchor' ? this.attr('text-anchor', v) : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style' ? this.attr('font-' + a, v) : this.attr(a, v);
}
});

function setup$2() { function setup$2() {
var node = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var node = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
this.events = node.events || {}; this.events = node.events || {};
function add(element, i) { function add(element, i) {
element = makeInstance(element); element = makeInstance(element);


if (element.node !== this.node.children[i]) {
this.node.insertBefore(element.node, this.node.children[i] || null);
if (i == null) {
this.node.appendChild(element.node);
} else if (element.node !== this.node.childNodes[i]) {
this.node.insertBefore(element.node, this.node.childNodes[i]);
} }


return this; return this;
extend$2(Path, getMethodsFor('Path')); extend$2(Path, getMethodsFor('Path'));
extend$2(Defs, getMethodsFor('Defs')); extend$2(Defs, getMethodsFor('Defs'));
extend$2([Text$1, Tspan], getMethodsFor('Tspan')); extend$2([Text$1, Tspan], getMethodsFor('Tspan'));
extend$2([Rect, Ellipse, Circle, Gradient], getMethodsFor('radius'));
var containerMethods = getMethodsFor('Container'); // FIXME: We need a container array var containerMethods = getMethodsFor('Container'); // FIXME: We need a container array


for (var i$1 in containers) { for (var i$1 in containers) {

+ 1
- 1
dist/svg.min.js
File diff suppressed because it is too large
View File


+ 1
- 1
src/Element.js View File



registerMethods('Element', { registerMethods('Element', {
x, y, cx, cy, move, center, width, height, size, clone, remove, replace, x, y, cx, cy, move, center, width, height, size, clone, remove, replace,
putIn, id, inside, toString, classes, hasClass, addClass, removeClass,
addTo, putIn, id, inside, toString, classes, hasClass, addClass, removeClass,
toggleClass, reference, doc, defs, parents, matches, native, svg, toggleClass, reference, doc, defs, parents, matches, native, svg,
writeDataToDom, setData, getEventTarget writeDataToDom, setData, getEventTarget
}) })

+ 8
- 6
src/Parent.js View File

export function add (element, i) { export function add (element, i) {
element = makeInstance(element) element = makeInstance(element)


if (element.node !== this.node.children[i]) {
this.node.insertBefore(element.node, this.node.children[i] || null)
if (i == null) {
this.node.appendChild(element.node)
} else if (element.node !== this.node.childNodes[i]) {
this.node.insertBefore(element.node, this.node.childNodes[i])
} }


return this return this


// Gets index of given element // Gets index of given element
export function index (element) { export function index (element) {
return [].slice.call(this.node.children).indexOf(element.node)
return [].slice.call(this.node.childNodes).indexOf(element.node)
} }


// Get a element at the given index // Get a element at the given index
export function get (i) { export function get (i) {
return adopt(this.node.children[i])
return adopt(this.node.childNodes[i])
} }


// Get first child // Get first child
export function first () { export function first () {
return this.get(0)
return adopt(this.node.firstChild)
} }


// Get the last child // Get the last child
export function last () { export function last () {
return this.get(this.node.children.length - 1)
return adopt(this.node.lastChild)
} }


// Iterates over all children and invokes a given block // Iterates over all children and invokes a given block

+ 47
- 14
src/elemnts-svg.js View File

// Import raw svg // Import raw svg
svg: function (svg) {
svg: function (svg, fn = false) {
var well, len var well, len


// act as getter if no svg string is given // act as getter if no svg string is given
if(svg == null || svg === true) {
if(svg == null || svg === true || typeof svg == 'function') {
// write svgjs data to the dom // write svgjs data to the dom
this.writeDataToDom() this.writeDataToDom()
let current = this


// return outer or inner content
// An export modifier was passed
if (typeof svg == 'function') {
// Juggle arguments
[fn, svg] = [svg, fn]

// If the user wants outerHTML we need to process this node, too
if (!svg) {
current = fn(current)

// The user does not want this node? Well, then he gets nothing
if (current === false) return ''
}

// Deep loop through all children and apply modifier
current.each(function () {
let result = fn(this)

// If modifier returns false, discard node
if (result === false) {
this.remove()

// If modifier returns new node, use it
} else if (result !== this) {
this.replace(result)
}
}, true)
}

// Return outer or inner content
return svg return svg
? this.node.innerHTML
: this.node.outerHTML
? current.node.innerHTML
: current.node.outerHTML
} }


// act as setter if we got a string
// Act as setter if we got a string


// make sure we are on a parent when trying to import
if(!(this instanceof SVG.Parent))
throw Error('Cannot import svg into non-parent element')
// Make sure we are on a current when trying to import
if(!(this instanceof SVG.current))
throw Error('Cannot import svg into non-current element')


// create temporary holder
// Create temporary holder
well = document.createElementNS(SVG.ns, 'svg') well = document.createElementNS(SVG.ns, 'svg')
fragment = document.createDocumentFragment()


// dump raw svg
// Dump raw svg
well.innerHTML = svg well.innerHTML = svg


// transplant nodes
// Transplant nodes into the fragment
for (len = well.children.length; len--;) { for (len = well.children.length; len--;) {
this.node.appendChild(well.firstElementChild)
fragment.appendChild(well.firstElementChild)
} }


// Add the whole fragment at once
this.node.appendChild(fragment)

return this return this
},
},

+ 10
- 2
src/methods.js View File

const constructors = {} const constructors = {}


export function registerMethods (name, m) { export function registerMethods (name, m) {
if (Array.isArray(name)) {
for (let _name of name) {
registerMethods(_name, m)
}
return
}

if (typeof name == 'object') { if (typeof name == 'object') {
for (let [_name, _m] of Object.entries(name)) { for (let [_name, _m] of Object.entries(name)) {
registerMethods(_name, _m) registerMethods(_name, _m)
} }
return
} }


methods[name] = Object.assign(methods[name] || {}, m) methods[name] = Object.assign(methods[name] || {}, m)
} }


export function getMethodsFor (name) { export function getMethodsFor (name) {
return methods[name]
return methods[name] || {}
} }


// FIXME: save memory? // FIXME: save memory?
} }


export function getConstructor (name) { export function getConstructor (name) {
return {setup: constructors[name], name}
return constructors[name] ? {setup: constructors[name], name} : {}
} }

+ 7
- 6
src/sugar.js View File

import {Color, Element, Runner} from './classes.js'
import Color from './Color.js'
import {registerMethods} from './methods.js'


// Define list of available attributes for stroke and fill // Define list of available attributes for stroke and fill
var sugar = { var sugar = {
return this return this
} }


extend([Element, Runner], extension)
registerMethods(['Element', 'Runner'], extension)
}) })


extend([Element, Runner], {
registerMethods(['Element', 'Runner'], {
// Let the user set the matrix directly // Let the user set the matrix directly
matrix: function (mat, b, c, d, e, f) { matrix: function (mat, b, c, d, e, f) {
// Act as a getter // Act as a getter
} }
}) })


extend([Rect, Ellipse, Circle, Gradient, Runner], {
registerMethods('radius', {
// Add x and y radius // Add x and y radius
radius: function (x, y) { radius: function (x, y) {
var type = (this._target || this).type var type = (this._target || this).type
} }
}) })


extend(Path, {
registerMethods('Path', {
// Get path length // Get path length
length: function () { length: function () {
return this.node.getTotalLength() return this.node.getTotalLength()
} }
}) })


extend([Parent, Text, Tspan, Runner], {
registerMethods(['Container', 'Runner'], {
// Set font // Set font
font: function (a, v) { font: function (a, v) {
if (typeof a === 'object') { if (typeof a === 'object') {

+ 8
- 0
src/svg.js View File

import './css.js' import './css.js'
import './transform.js' import './transform.js'
import './memory.js' import './memory.js'
import './sugar.js'
import {getMethodsFor, getConstructor} from './methods.js' import {getMethodsFor, getConstructor} from './methods.js'
const extend = tools.extend const extend = tools.extend


Classes.Tspan Classes.Tspan
], getMethodsFor('Tspan')) ], getMethodsFor('Tspan'))


extend([
Classes.Rect,
Classes.Ellipse,
Classes.Circle,
Classes.Gradient
], getMethodsFor('radius'))

const containerMethods = getMethodsFor('Container') const containerMethods = getMethodsFor('Container')
// FIXME: We need a container array // FIXME: We need a container array
for (let i in containers) { for (let i in containers) {

Loading…
Cancel
Save