diff options
70 files changed, 2148 insertions, 4221 deletions
diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 6243075..c2212c7 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -7,4 +7,3 @@ rules: flatTernaryExpressions: true }] padded-blocks: off - space-in-parens: [ error, always ] diff --git a/dist/svg.js b/dist/svg.js index 2072971..2b7a05e 100644 --- a/dist/svg.js +++ b/dist/svg.js @@ -6,7 +6,7 @@ * @copyright Wout Fierens <wout@mick-wout.com> * @license MIT * -* BUILT: Sun Nov 25 2018 16:17:19 GMT+1300 (New Zealand Daylight Time) +* BUILT: Mon Nov 26 2018 00:15:11 GMT+1300 (New Zealand Daylight Time) */; var SVG = (function () { 'use strict'; @@ -112,36 +112,6 @@ var SVG = (function () { return _setPrototypeOf(o, p); } - function isNativeReflectConstruct() { - if (typeof Reflect === "undefined" || !Reflect.construct) return false; - if (Reflect.construct.sham) return false; - if (typeof Proxy === "function") return true; - - try { - Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); - return true; - } catch (e) { - return false; - } - } - - function _construct(Parent, args, Class) { - if (isNativeReflectConstruct()) { - _construct = Reflect.construct; - } else { - _construct = function _construct(Parent, args, Class) { - var a = [null]; - a.push.apply(a, args); - var Constructor = Function.bind.apply(Parent, a); - var instance = new Constructor(); - if (Class) _setPrototypeOf(instance, Class.prototype); - return instance; - }; - } - - return _construct.apply(null, arguments); - } - function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); @@ -1107,112 +1077,117 @@ var SVG = (function () { /*#__PURE__*/ function () { function Color() { - var a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; - var b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - var c = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; - var d = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; - var space = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'rgb'; - _classCallCheck(this, Color); - // If the user gave us an array, make the color from it - if (typeof a === 'number') { - // Allow for the case that we don't need d... - space = typeof d === 'string' ? d : space; - d = typeof d === 'string' ? undefined : d; // Assign the values straight to the color - - Object.assign(this, { - _a: a, - _b: b, - _c: c, - _d: d, - space: space - }); - } else if (a instanceof Array) { - this.space = b || 'rgb'; - Object.assign(this, { - _a: a[0], - _b: a[1], - _c: a[2], - _d: a[3] - }); - } else if (a instanceof Object) { - // Set the object up and assign its values directly - var values = getParameters(a); - Object.assign(this, values); - } else if (typeof a === 'string') { - if (isRgb.test(a)) { - var noWhitespace = a.replace(whitespace, ''); - - var _rgb$exec$slice$map = rgb.exec(noWhitespace).slice(1, 4).map(function (v) { - return parseInt(v); - }), - _rgb$exec$slice$map2 = _slicedToArray(_rgb$exec$slice$map, 3), - _a2 = _rgb$exec$slice$map2[0], - _b2 = _rgb$exec$slice$map2[1], - _c2 = _rgb$exec$slice$map2[2]; + this.init.apply(this, arguments); + } + + _createClass(Color, [{ + key: "init", + value: function init() { + var a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var c = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + var d = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; + var space = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'rgb'; + + // If the user gave us an array, make the color from it + if (typeof a === 'number') { + // Allow for the case that we don't need d... + space = typeof d === 'string' ? d : space; + d = typeof d === 'string' ? undefined : d; // Assign the values straight to the color Object.assign(this, { - _a: _a2, - _b: _b2, - _c: _c2, - space: 'rgb' + _a: a, + _b: b, + _c: c, + _d: d, + space: space }); - } else if (isHex.test(a)) { - var hexParse = function hexParse(v) { - return parseInt(v, 16); - }; - - var _hex$exec$map = hex.exec(sixDigitHex(a)).map(hexParse), - _hex$exec$map2 = _slicedToArray(_hex$exec$map, 4), - _a3 = _hex$exec$map2[1], - _b3 = _hex$exec$map2[2], - _c3 = _hex$exec$map2[3]; - + } else if (a instanceof Array) { + this.space = b || 'rgb'; Object.assign(this, { - _a: _a3, - _b: _b3, - _c: _c3, - space: 'rgb' + _a: a[0], + _b: a[1], + _c: a[2], + _d: a[3] }); - } else throw Error("Unsupported string format, can't construct Color"); - } // Now add the components as a convenience - - - var _a = this._a, - _b = this._b, - _c = this._c, - _d = this._d; - var components = this.space === 'rgb' ? { - r: _a, - g: _b, - b: _c - } : this.space === 'xyz' ? { - x: _a, - y: _b, - z: _c - } : this.space === 'hsl' ? { - h: _a, - s: _b, - l: _c - } : this.space === 'lab' ? { - l: _a, - a: _b, - b: _c - } : this.space === 'lch' ? { - l: _a, - c: _b, - h: _c - } : this.space === 'cmyk' ? { - c: _a, - y: _b, - m: _c, - k: _d - } : {}; - Object.assign(this, components); - } + } else if (a instanceof Object) { + // Set the object up and assign its values directly + var values = getParameters(a); + Object.assign(this, values); + } else if (typeof a === 'string') { + if (isRgb.test(a)) { + var noWhitespace = a.replace(whitespace, ''); + + var _rgb$exec$slice$map = rgb.exec(noWhitespace).slice(1, 4).map(function (v) { + return parseInt(v); + }), + _rgb$exec$slice$map2 = _slicedToArray(_rgb$exec$slice$map, 3), + _a2 = _rgb$exec$slice$map2[0], + _b2 = _rgb$exec$slice$map2[1], + _c2 = _rgb$exec$slice$map2[2]; + + Object.assign(this, { + _a: _a2, + _b: _b2, + _c: _c2, + space: 'rgb' + }); + } else if (isHex.test(a)) { + var hexParse = function hexParse(v) { + return parseInt(v, 16); + }; + + var _hex$exec$map = hex.exec(sixDigitHex(a)).map(hexParse), + _hex$exec$map2 = _slicedToArray(_hex$exec$map, 4), + _a3 = _hex$exec$map2[1], + _b3 = _hex$exec$map2[2], + _c3 = _hex$exec$map2[3]; + + Object.assign(this, { + _a: _a3, + _b: _b3, + _c: _c3, + space: 'rgb' + }); + } else throw Error("Unsupported string format, can't construct Color"); + } // Now add the components as a convenience - _createClass(Color, [{ + + var _a = this._a, + _b = this._b, + _c = this._c, + _d = this._d; + var components = this.space === 'rgb' ? { + r: _a, + g: _b, + b: _c + } : this.space === 'xyz' ? { + x: _a, + y: _b, + z: _c + } : this.space === 'hsl' ? { + h: _a, + s: _b, + l: _c + } : this.space === 'lab' ? { + l: _a, + a: _b, + b: _c + } : this.space === 'lch' ? { + l: _a, + c: _b, + h: _c + } : this.space === 'cmyk' ? { + c: _a, + m: _b, + y: _c, + k: _d + } : {}; + Object.assign(this, components); + } + }, { key: "opacity", value: function opacity() { var _opacity = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; @@ -1264,8 +1239,8 @@ var SVG = (function () { var yL = (l + 16) / 116; - var xL = a / 500 + y; - var zL = y - _b4 / 200; // Get the xyz values + var xL = a / 500 + yL; + var zL = yL - _b4 / 200; // Get the xyz values var ct = 16 / 116; var mx = 0.008856; @@ -1286,14 +1261,17 @@ var SVG = (function () { var g = gU > bd ? 1.055 * pow(gU, 1 / 2.4) - 0.055 : 12.92 * gU; var b = bU > bd ? 1.055 * pow(bU, 1 / 2.4) - 0.055 : 12.92 * bU; // Make and return the color - var color = new Color(r, g, b); + var color = new Color(255 * r, 255 * g, 255 * b); return color; } else if (this.space === 'hsl') { - // stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion + // https://bgrins.github.io/TinyColor/docs/tinycolor.html // Get the current hsl values var _h = this.h, s = this.s, - _l = this.l; // If we are grey, then just make the color directly + _l = this.l; + _h /= 360; + s /= 100; + _l /= 100; // If we are grey, then just make the color directly if (s === 0) { var _color2 = new Color(_l, _l, _l); @@ -1305,11 +1283,11 @@ var SVG = (function () { var q = _l < 0.5 ? _l * (1 + s) : _l + s - _l * s; var p = 2 * _l - q; // Get the rgb values - var _r = hueToRgb(p, q, _h + 1 / 3); + var _r = 255 * hueToRgb(p, q, _h + 1 / 3); - var _g = hueToRgb(p, q, _h); + var _g = 255 * hueToRgb(p, q, _h); - var _b5 = hueToRgb(p, q, _h - 1 / 3); // Make a new color + var _b5 = 255 * hueToRgb(p, q, _h - 1 / 3); // Make a new color var _color = new Color(_r, _g, _b5); @@ -1318,26 +1296,16 @@ var SVG = (function () { } else if (this.space === 'cmyk') { // https://gist.github.com/felipesabino/5066336 // Get the normalised cmyk values - var _a = this._a, - _b = this._b, - _c = this._c, - _d = this._d; - - var _map = [_a, _b, _c, _d].map(function (v) { - return v / 100; - }), - _map2 = _slicedToArray(_map, 4), - _c4 = _map2[0], - m = _map2[1], - _y = _map2[2], - k = _map2[3]; // Get the rgb values - + var _c4 = this.c, + m = this.m, + _y = this.y, + k = this.k; // Get the rgb values - var _r2 = 1 - Math.min(1, _c4 * (1 - k) + k); + var _r2 = 255 * (1 - Math.min(1, _c4 * (1 - k) + k)); - var _g2 = 1 - Math.min(1, m * (1 - k) + k); + var _g2 = 255 * (1 - Math.min(1, m * (1 - k) + k)); - var _b6 = 1 - Math.min(1, _y * (1 - k) + k); // Form the color and return it + var _b6 = 255 * (1 - Math.min(1, _y * (1 - k) + k)); // Form the color and return it var _color3 = new Color(_r2, _g2, _b6); @@ -1373,13 +1341,13 @@ var SVG = (function () { g255 = _this$rgb2._b, b255 = _this$rgb2._c; - var _map3 = [r255, g255, b255].map(function (v) { + var _map = [r255, g255, b255].map(function (v) { return v / 255; }), - _map4 = _slicedToArray(_map3, 3), - r = _map4[0], - g = _map4[1], - b = _map4[2]; // Convert to the lab rgb space + _map2 = _slicedToArray(_map, 3), + r = _map2[0], + g = _map2[1], + b = _map2[2]; // Convert to the lab rgb space var rL = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92; @@ -1428,13 +1396,13 @@ var SVG = (function () { _b = _this$rgb3._b, _c = _this$rgb3._c; - var _map5 = [_a, _b, _c].map(function (v) { + var _map3 = [_a, _b, _c].map(function (v) { return v / 255; }), - _map6 = _slicedToArray(_map5, 3), - r = _map6[0], - g = _map6[1], - b = _map6[2]; // Find the maximum and minimum values to get the lightness + _map4 = _slicedToArray(_map3, 3), + r = _map4[0], + g = _map4[1], + b = _map4[2]; // Find the maximum and minimum values to get the lightness var max = Math.max(r, g, b); @@ -1447,7 +1415,7 @@ var SVG = (function () { var s = isGrey ? 0 : l > 0.5 ? delta / (2 - max - min) : delta / (max + min); var h = isGrey ? 0 : max === r ? ((g - b) / delta + (g < b ? 6 : 0)) / 6 : max === g ? ((b - r) / delta + 2) / 6 : max === b ? ((r - g) / delta + 4) / 6 : 0; // Construct and return the new color - var color = new Color(h, s, l, 'hsl'); + var color = new Color(360 * h, 100 * s, 100 * l, 'hsl'); return color; } }, { @@ -1459,54 +1427,24 @@ var SVG = (function () { _b = _this$rgb4._b, _c = _this$rgb4._c; - var _map7 = [_a, _b, _c].map(function (v) { + var _map5 = [_a, _b, _c].map(function (v) { return v / 255; }), - _map8 = _slicedToArray(_map7, 3), - r = _map8[0], - g = _map8[1], - b = _map8[2]; // Get the cmyk values in an unbounded format + _map6 = _slicedToArray(_map5, 3), + r = _map6[0], + g = _map6[1], + b = _map6[2]; // Get the cmyk values in an unbounded format - var k = 100 * Math.min(1 - r, 1 - g, 1 - b); - var c = 100 * (1 - r - k) / (1 - k); - var m = 100 * (1 - g - k) / (1 - k); - var y = 100 * (1 - b - k) / (1 - k); // Construct the new color + var k = Math.min(1 - r, 1 - g, 1 - b); + var c = (1 - r - k) / (1 - k); + var m = (1 - g - k) / (1 - k); + var y = (1 - b - k) / (1 - k); // Construct the new color var color = new Color(c, m, y, k, 'cmyk'); return color; } /* - Modifying the color - */ - - }, { - key: "brighten", - value: function brighten() { - } - }, { - key: "darken", - value: function darken() { - } - /* - Mixing methods - */ - - }, { - key: "to", - value: function to(otherColor, space) { - // Force both colors to the color of this space (or let the user decide) - space = space || this.space; // Get the starting and ending colors - // let start = this[ space ]() - // let end = otherColor[ space ]() - // Return a function that blends between the two colors - - return function (t) {}; - } - }, { - key: "avearge", - value: function avearge(otherColor, space) {} - /* Input and Output methods */ @@ -1518,11 +1456,11 @@ var SVG = (function () { _b = _this$rgb5._b, _c = _this$rgb5._c; - var _map9 = [_a, _b, _c].map(componentHex), - _map10 = _slicedToArray(_map9, 3), - r = _map10[0], - g = _map10[1], - b = _map10[2]; + var _map7 = [_a, _b, _c].map(componentHex), + _map8 = _slicedToArray(_map7, 3), + r = _map8[0], + g = _map8[1], + b = _map8[2]; return "#".concat(r).concat(g).concat(b); } @@ -1547,11 +1485,11 @@ var SVG = (function () { return max(0, min(round(v), 255)); }; - var _map11 = [r, g, b].map(format), - _map12 = _slicedToArray(_map11, 3), - rV = _map12[0], - gV = _map12[1], - bV = _map12[2]; + var _map9 = [r, g, b].map(format), + _map10 = _slicedToArray(_map9, 3), + rV = _map10[0], + gV = _map10[1], + bV = _map10[2]; var string = "rgb(".concat(rV, ",").concat(gV, ",").concat(bV, ")"); return string; @@ -1566,18 +1504,11 @@ var SVG = (function () { space = this.space; return [_a, _b, _c, _d, space]; } - }], [{ - key: "fromArray", - value: function fromArray(array) { - var newColor = _construct(Color, _toConsumableArray(array)); - - return newColor; - } /* Generating random colors */ - }, { + }], [{ key: "random", value: function random() { 'sine'; @@ -1591,10 +1522,7 @@ var SVG = (function () { /* Constructing colors */ - - }, { - key: "temperature", - value: function temperature(kelvin) {} // Test if given value is a color string + // Test if given value is a color string }, { key: "test", diff --git a/src/animation/Animator.js b/src/animation/Animator.js index e9d5797..cac0eb9 100644 --- a/src/animation/Animator.js +++ b/src/animation/Animator.js @@ -8,106 +8,80 @@ const Animator = { timer: globals.window.performance || globals.window.Date, transforms: [], - frame ( fn ) { - + frame (fn) { // Store the node - var node = Animator.frames.push( { run: fn } ) + var node = Animator.frames.push({ run: fn }) // Request an animation frame if we don't have one - if ( Animator.nextDraw === null ) { - - Animator.nextDraw = globals.window.requestAnimationFrame( Animator._draw ) - + if (Animator.nextDraw === null) { + Animator.nextDraw = globals.window.requestAnimationFrame(Animator._draw) } // Return the node so we can remove it easily return node - }, - transform_frame ( fn, id ) { - + transform_frame (fn, id) { Animator.transforms[id] = fn - }, - timeout ( fn, delay ) { - + timeout (fn, delay) { delay = delay || 0 // Work out when the event should fire var time = Animator.timer.now() + delay // Add the timeout to the end of the queue - var node = Animator.timeouts.push( { run: fn, time: time } ) + var node = Animator.timeouts.push({ run: fn, time: time }) // Request another animation frame if we need one - if ( Animator.nextDraw === null ) { - - Animator.nextDraw = globals.window.requestAnimationFrame( Animator._draw ) - + if (Animator.nextDraw === null) { + Animator.nextDraw = globals.window.requestAnimationFrame(Animator._draw) } return node - }, - cancelFrame ( node ) { - - Animator.frames.remove( node ) - + cancelFrame (node) { + Animator.frames.remove(node) }, - clearTimeout ( node ) { - - Animator.timeouts.remove( node ) - + clearTimeout (node) { + Animator.timeouts.remove(node) }, - _draw ( now ) { - + _draw (now) { // Run all the timeouts we can run, if they are not ready yet, add them // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) var nextTimeout = null var lastTimeout = Animator.timeouts.last() - while ( ( nextTimeout = Animator.timeouts.shift() ) ) { - + while ((nextTimeout = Animator.timeouts.shift())) { // Run the timeout if its time, or push it to the end - if ( now >= nextTimeout.time ) { - + if (now >= nextTimeout.time) { nextTimeout.run() - } else { - - Animator.timeouts.push( nextTimeout ) - + Animator.timeouts.push(nextTimeout) } // If we hit the last item, we should stop shifting out more items - if ( nextTimeout === lastTimeout ) break - + if (nextTimeout === lastTimeout) break } // Run all of the animation frames var nextFrame = null var lastFrame = Animator.frames.last() - while ( ( nextFrame !== lastFrame ) && ( nextFrame = Animator.frames.shift() ) ) { - + while ((nextFrame !== lastFrame) && (nextFrame = Animator.frames.shift())) { nextFrame.run() - } - Animator.transforms.forEach( function ( el ) { - + Animator.transforms.forEach(function (el) { el() - - } ) + }) // If we have remaining timeouts or frames, draw until we don't anymore Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() - ? globals.window.requestAnimationFrame( Animator._draw ) + ? globals.window.requestAnimationFrame(Animator._draw) : null - } } diff --git a/src/animation/Controller.js b/src/animation/Controller.js index 9efe87e..6cf58cd 100644 --- a/src/animation/Controller.js +++ b/src/animation/Controller.js @@ -7,149 +7,95 @@ Base Class The base stepper class that will be ***/ -function makeSetterGetter ( k, f ) { - - return function ( v ) { - - if ( v == null ) return this[v] +function makeSetterGetter (k, f) { + return function (v) { + if (v == null) return this[v] this[k] = v - if ( f ) f.call( this ) + if (f) f.call(this) return this - } - } export let easing = { - '-': function ( pos ) { - + '-': function (pos) { return pos - }, - '<>': function ( pos ) { - - return -Math.cos( pos * Math.PI ) / 2 + 0.5 - + '<>': function (pos) { + return -Math.cos(pos * Math.PI) / 2 + 0.5 }, - '>': function ( pos ) { - - return Math.sin( pos * Math.PI / 2 ) - + '>': function (pos) { + return Math.sin(pos * Math.PI / 2) }, - '<': function ( pos ) { - - return -Math.cos( pos * Math.PI / 2 ) + 1 - + '<': function (pos) { + return -Math.cos(pos * Math.PI / 2) + 1 }, - bezier: function ( x1, y1, x2, y2 ) { - + bezier: function (x1, y1, x2, y2) { // see https://www.w3.org/TR/css-easing-1/#cubic-bezier-algo - return function ( t ) { - - if ( t < 0 ) { - - if ( x1 > 0 ) { - + return function (t) { + if (t < 0) { + if (x1 > 0) { return y1 / x1 * t - - } else if ( x2 > 0 ) { - + } else if (x2 > 0) { return y2 / x2 * t - } else { - return 0 - } - - } else if ( t > 1 ) { - - if ( x2 < 1 ) { - - return ( 1 - y2 ) / ( 1 - x2 ) * t + ( y2 - x2 ) / ( 1 - x2 ) - - } else if ( x1 < 1 ) { - - return ( 1 - y1 ) / ( 1 - x1 ) * t + ( y1 - x1 ) / ( 1 - x1 ) - + } else if (t > 1) { + if (x2 < 1) { + return (1 - y2) / (1 - x2) * t + (y2 - x2) / (1 - x2) + } else if (x1 < 1) { + return (1 - y1) / (1 - x1) * t + (y1 - x1) / (1 - x1) } else { - return 1 - } - } else { - - return 3 * t * ( 1 - t ) ** 2 * y1 + 3 * t ** 2 * ( 1 - t ) * y2 + t ** 3 - + return 3 * t * (1 - t) ** 2 * y1 + 3 * t ** 2 * (1 - t) * y2 + t ** 3 } - } - }, // see https://www.w3.org/TR/css-easing-1/#step-timing-function-algo - steps: function ( steps, stepPosition = 'end' ) { - + steps: function (steps, stepPosition = 'end') { // deal with "jump-" prefix - stepPosition = stepPosition.split( '-' ).reverse()[0] + stepPosition = stepPosition.split('-').reverse()[0] let jumps = steps - if ( stepPosition === 'none' ) { - + if (stepPosition === 'none') { --jumps - - } else if ( stepPosition === 'both' ) { - + } else if (stepPosition === 'both') { ++jumps - } // The beforeFlag is essentially useless - return ( t, beforeFlag = false ) => { - + return (t, beforeFlag = false) => { // Step is called currentStep in referenced url - let step = Math.floor( t * steps ) - const jumping = ( t * step ) % 1 === 0 - - if ( stepPosition === 'start' || stepPosition === 'both' ) { + let step = Math.floor(t * steps) + const jumping = (t * step) % 1 === 0 + if (stepPosition === 'start' || stepPosition === 'both') { ++step - } - if ( beforeFlag && jumping ) { - + if (beforeFlag && jumping) { --step - } - if ( t >= 0 && step < 0 ) { - + if (t >= 0 && step < 0) { step = 0 - } - if ( t <= 1 && step > jumps ) { - + if (t <= 1 && step > jumps) { step = jumps - } return step / jumps - } - } } export class Stepper { - done () { - return false - } - } /*** @@ -158,25 +104,17 @@ Easing Functions ***/ export class Ease extends Stepper { - - constructor ( fn ) { - + constructor (fn) { super() this.ease = easing[fn || timeline.ease] || fn - } - step ( from, to, pos ) { - - if ( typeof from !== 'number' ) { - + step (from, to, pos) { + if (typeof from !== 'number') { return pos < 1 ? from : to - } - return from + ( to - from ) * this.ease( pos ) - + return from + (to - from) * this.ease(pos) } - } /*** @@ -185,65 +123,51 @@ Controller Types ***/ export class Controller extends Stepper { - - constructor ( fn ) { - + constructor (fn) { super() this.stepper = fn - } - step ( current, target, dt, c ) { - - return this.stepper( current, target, dt, c ) - + step (current, target, dt, c) { + return this.stepper(current, target, dt, c) } - done ( c ) { - + done (c) { return c.done - } - } function recalculate () { - // Apply the default parameters - var duration = ( this._duration || 500 ) / 1000 + var duration = (this._duration || 500) / 1000 var overshoot = this._overshoot || 0 // Calculate the PID natural response var eps = 1e-10 var pi = Math.PI - var os = Math.log( overshoot / 100 + eps ) - var zeta = -os / Math.sqrt( pi * pi + os * os ) - var wn = 3.9 / ( zeta * duration ) + var os = Math.log(overshoot / 100 + eps) + var zeta = -os / Math.sqrt(pi * pi + os * os) + var wn = 3.9 / (zeta * duration) // Calculate the Spring values this.d = 2 * zeta * wn this.k = wn * wn - } export class Spring extends Controller { - - constructor ( duration, overshoot ) { - + constructor (duration, overshoot) { super() - this.duration( duration || 500 ) - .overshoot( overshoot || 0 ) - + this.duration(duration || 500) + .overshoot(overshoot || 0) } - step ( current, target, dt, c ) { - - if ( typeof current === 'string' ) return current + step (current, target, dt, c) { + if (typeof current === 'string') return current c.done = dt === Infinity - if ( dt === Infinity ) return target - if ( dt === 0 ) return current + if (dt === Infinity) return target + if (dt === 0) return current - if ( dt > 100 ) dt = 16 + if (dt > 100) dt = 16 dt /= 1000 @@ -251,7 +175,7 @@ export class Spring extends Controller { var velocity = c.velocity || 0 // Apply the control to get the new position and store it - var acceleration = -this.d * velocity - this.k * ( current - target ) + var acceleration = -this.d * velocity - this.k * (current - target) var newPosition = current + velocity * dt + acceleration * dt * dt / 2 @@ -260,66 +184,56 @@ export class Spring extends Controller { c.velocity = velocity + acceleration * dt // Figure out if we have converged, and if so, pass the value - c.done = Math.abs( target - newPosition ) + Math.abs( velocity ) < 0.002 + c.done = Math.abs(target - newPosition) + Math.abs(velocity) < 0.002 return c.done ? target : newPosition - } - } -extend( Spring, { - duration: makeSetterGetter( '_duration', recalculate ), - overshoot: makeSetterGetter( '_overshoot', recalculate ) -} ) +extend(Spring, { + duration: makeSetterGetter('_duration', recalculate), + overshoot: makeSetterGetter('_overshoot', recalculate) +}) export class PID extends Controller { - - constructor ( p, i, d, windup ) { - + constructor (p, i, d, windup) { super() p = p == null ? 0.1 : p i = i == null ? 0.01 : i d = d == null ? 0 : d windup = windup == null ? 1000 : windup - this.p( p ).i( i ).d( d ).windup( windup ) - + this.p(p).i(i).d(d).windup(windup) } - step ( current, target, dt, c ) { - - if ( typeof current === 'string' ) return current + step (current, target, dt, c) { + if (typeof current === 'string') return current c.done = dt === Infinity - if ( dt === Infinity ) return target - if ( dt === 0 ) return current + if (dt === Infinity) return target + if (dt === 0) return current var p = target - current - var i = ( c.integral || 0 ) + p * dt - var d = ( p - ( c.error || 0 ) ) / dt + var i = (c.integral || 0) + p * dt + var d = (p - (c.error || 0)) / dt var windup = this.windup // antiwindup - if ( windup !== false ) { - - i = Math.max( -windup, Math.min( i, windup ) ) - + if (windup !== false) { + i = Math.max(-windup, Math.min(i, windup)) } c.error = p c.integral = i - c.done = Math.abs( p ) < 0.001 - - return c.done ? target : current + ( this.P * p + this.I * i + this.D * d ) + c.done = Math.abs(p) < 0.001 + return c.done ? target : current + (this.P * p + this.I * i + this.D * d) } - } -extend( PID, { - windup: makeSetterGetter( 'windup' ), - p: makeSetterGetter( 'P' ), - i: makeSetterGetter( 'I' ), - d: makeSetterGetter( 'D' ) -} ) +extend(PID, { + windup: makeSetterGetter('windup'), + p: makeSetterGetter('P'), + i: makeSetterGetter('I'), + d: makeSetterGetter('D') +}) diff --git a/src/animation/Queue.js b/src/animation/Queue.js index b4e2722..14b92b4 100644 --- a/src/animation/Queue.js +++ b/src/animation/Queue.js @@ -1,77 +1,59 @@ export default class Queue { - constructor () { - this._first = null this._last = null - } - push ( value ) { - + push (value) { // An item stores an id and the provided value var item = value.next ? value : { value: value, next: null, prev: null } // Deal with the queue being empty or populated - if ( this._last ) { - + if (this._last) { item.prev = this._last this._last.next = item this._last = item - } else { - this._last = item this._first = item - } // Update the length and return the current item return item - } shift () { - // Check if we have a value var remove = this._first - if ( !remove ) return null + if (!remove) return null // If we do, remove it and relink things this._first = remove.next - if ( this._first ) this._first.prev = null + if (this._first) this._first.prev = null this._last = this._first ? this._last : null return remove.value - } // Shows us the first item in the list first () { - return this._first && this._first.value - } // Shows us the last item in the list last () { - return this._last && this._last.value - } // Removes the item that was returned from the push - remove ( item ) { - + remove (item) { // Relink the previous item - if ( item.prev ) item.prev.next = item.next - if ( item.next ) item.next.prev = item.prev - if ( item === this._last ) this._last = item.prev - if ( item === this._first ) this._first = item.next + if (item.prev) item.prev.next = item.next + if (item.next) item.next.prev = item.prev + if (item === this._last) this._last = item.prev + if (item === this._first) this._first = item.next // Invalidate item item.prev = null item.next = null - } - } diff --git a/src/animation/Runner.js b/src/animation/Runner.js index d2c7bdf..7e04c21 100644 --- a/src/animation/Runner.js +++ b/src/animation/Runner.js @@ -15,9 +15,7 @@ import SVGNumber from '../types/SVGNumber.js' import Timeline from './Timeline.js' export default class Runner extends EventTarget { - - constructor ( options ) { - + constructor (options) { super() // Store a unique id on the runner, so that we can identify it later @@ -30,7 +28,7 @@ export default class Runner extends EventTarget { // Ensure that we get a controller options = typeof options === 'function' - ? new Controller( options ) + ? new Controller(options) : options // Declare all of the variables @@ -63,7 +61,6 @@ export default class Runner extends EventTarget { this._swing = false this._wait = 0 this._times = 1 - } /* @@ -73,75 +70,58 @@ export default class Runner extends EventTarget { help us make new runners from the current runner */ - element ( element ) { - - if ( element == null ) return this._element + element (element) { + if (element == null) return this._element this._element = element element._prepareRunner() return this - } - timeline ( timeline ) { - + timeline (timeline) { // check explicitly for undefined so we can set the timeline to null - if ( typeof timeline === 'undefined' ) return this._timeline + if (typeof timeline === 'undefined') return this._timeline this._timeline = timeline return this - } - animate ( duration, delay, when ) { - - var o = Runner.sanitise( duration, delay, when ) - var runner = new Runner( o.duration ) - if ( this._timeline ) runner.timeline( this._timeline ) - if ( this._element ) runner.element( this._element ) - return runner.loop( o ).schedule( delay, when ) - + animate (duration, delay, when) { + var o = Runner.sanitise(duration, delay, when) + var runner = new Runner(o.duration) + if (this._timeline) runner.timeline(this._timeline) + if (this._element) runner.element(this._element) + return runner.loop(o).schedule(delay, when) } - schedule ( timeline, delay, when ) { - + schedule (timeline, delay, when) { // The user doesn't need to pass a timeline if we already have one - if ( !( timeline instanceof Timeline ) ) { - + if (!(timeline instanceof Timeline)) { when = delay delay = timeline timeline = this.timeline() - } // If there is no timeline, yell at the user... - if ( !timeline ) { - - throw Error( 'Runner cannot be scheduled without timeline' ) - + if (!timeline) { + throw Error('Runner cannot be scheduled without timeline') } // Schedule the runner on the timeline provided - timeline.schedule( this, delay, when ) + timeline.schedule(this, delay, when) return this - } unschedule () { - var timeline = this.timeline() - timeline && timeline.unschedule( this ) + timeline && timeline.unschedule(this) return this - } - loop ( times, swing, wait ) { - + loop (times, swing, wait) { // Deal with the user passing in an object - if ( typeof times === 'object' ) { - + if (typeof times === 'object') { swing = times.swing wait = times.wait times = times.times - } // Sanitise the values and store them @@ -149,13 +129,10 @@ export default class Runner extends EventTarget { this._swing = swing || false this._wait = wait || 0 return this - } - delay ( delay ) { - - return this.animate( 0, delay ) - + delay (delay) { + return this.animate(0, delay) } /* @@ -164,32 +141,26 @@ export default class Runner extends EventTarget { These methods allow us to attach basic functions to the runner directly */ - queue ( initFn, runFn, retargetFn, isTransform ) { - - this._queue.push( { + queue (initFn, runFn, retargetFn, isTransform) { + this._queue.push({ initialiser: initFn || noop, runner: runFn || noop, retarget: retargetFn, isTransform: isTransform, initialised: false, finished: false - } ) + }) var timeline = this.timeline() timeline && this.timeline()._continue() return this - } - during ( fn ) { - - return this.queue( null, fn ) - + during (fn) { + return this.queue(null, fn) } - after ( fn ) { - - return this.on( 'finish', fn ) - + after (fn) { + return this.on('finish', fn) } /* @@ -198,45 +169,34 @@ export default class Runner extends EventTarget { Control how the animation plays */ - time ( time ) { - - if ( time == null ) { - + time (time) { + if (time == null) { return this._time - } let dt = time - this._time - this.step( dt ) + this.step(dt) return this - } duration () { - - return this._times * ( this._wait + this._duration ) - this._wait - + return this._times * (this._wait + this._duration) - this._wait } - loops ( p ) { - + loops (p) { var loopDuration = this._duration + this._wait - if ( p == null ) { - - var loopsDone = Math.floor( this._time / loopDuration ) - var relativeTime = ( this._time - loopsDone * loopDuration ) + if (p == null) { + var loopsDone = Math.floor(this._time / loopDuration) + var relativeTime = (this._time - loopsDone * loopDuration) var position = relativeTime / this._duration - return Math.min( loopsDone + position, this._times ) - + return Math.min(loopsDone + position, this._times) } - var whole = Math.floor( p ) + var whole = Math.floor(p) var partial = p % 1 var time = loopDuration * whole + this._duration * partial - return this.time( time ) - + return this.time(time) } - position ( p ) { - + position (p) { // Get all of the variables we need var x = this._time var d = this._duration @@ -246,8 +206,7 @@ export default class Runner extends EventTarget { var r = this._reverse var position - if ( p == null ) { - + if (p == null) { /* This function converts a time to a position in the range [0, 1] The full explanation can be found in this desmos demonstration @@ -256,49 +215,40 @@ export default class Runner extends EventTarget { */ // Figure out the value without thinking about the start or end time - const f = function ( x ) { - - var swinging = s * Math.floor( x % ( 2 * ( w + d ) ) / ( w + d ) ) - var backwards = ( swinging && !r ) || ( !swinging && r ) - var uncliped = Math.pow( -1, backwards ) * ( x % ( w + d ) ) / d + backwards - var clipped = Math.max( Math.min( uncliped, 1 ), 0 ) + const f = function (x) { + var swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)) + var backwards = (swinging && !r) || (!swinging && r) + var uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards + var clipped = Math.max(Math.min(uncliped, 1), 0) return clipped - } // Figure out the value by incorporating the start time - var endTime = t * ( w + d ) - w - position = x <= 0 ? Math.round( f( 1e-5 ) ) - : x < endTime ? f( x ) - : Math.round( f( endTime - 1e-5 ) ) + var endTime = t * (w + d) - w + position = x <= 0 ? Math.round(f(1e-5)) + : x < endTime ? f(x) + : Math.round(f(endTime - 1e-5)) return position - } // Work out the loops done and add the position to the loops done - var loopsDone = Math.floor( this.loops() ) - var swingForward = s && ( loopsDone % 2 === 0 ) - var forwards = ( swingForward && !r ) || ( r && swingForward ) - position = loopsDone + ( forwards ? p : 1 - p ) - return this.loops( position ) - + var loopsDone = Math.floor(this.loops()) + var swingForward = s && (loopsDone % 2 === 0) + var forwards = (swingForward && !r) || (r && swingForward) + position = loopsDone + (forwards ? p : 1 - p) + return this.loops(position) } - progress ( p ) { - - if ( p == null ) { - - return Math.min( 1, this._time / this.duration() ) - + progress (p) { + if (p == null) { + return Math.min(1, this._time / this.duration()) } - return this.time( p * this.duration() ) - + return this.time(p * this.duration()) } - step ( dt ) { - + step (dt) { // If we are inactive, this stepper just gets skipped - if ( !this.enabled ) return this + if (!this.enabled) return this // Update the time and get the new position dt = dt == null ? 16 : dt @@ -314,10 +264,8 @@ export default class Runner extends EventTarget { var justStarted = this._lastTime < 0 && this._time > 0 var justFinished = this._lastTime < this._time && this.time > duration this._lastTime = this._time - if ( justStarted ) { - - this.fire( 'start', this ) - + if (justStarted) { + this.fire('start', this) } // Work out if the runner is finished set the done flag here so animations @@ -327,54 +275,41 @@ export default class Runner extends EventTarget { this.done = !declarative && !justFinished && this._time >= duration // Call initialise and the run function - if ( running || declarative ) { - - this._initialise( running ) + if (running || declarative) { + this._initialise(running) // clear the transforms on this runner so they dont get added again and again this.transforms = new Matrix() - var converged = this._run( declarative ? dt : position ) - this.fire( 'step', this ) - + var converged = this._run(declarative ? dt : position) + this.fire('step', this) } // correct the done flag here // declaritive animations itself know when they converged - this.done = this.done || ( converged && declarative ) - if ( this.done ) { - - this.fire( 'finish', this ) - + this.done = this.done || (converged && declarative) + if (this.done) { + this.fire('finish', this) } return this - } finish () { - - return this.step( Infinity ) - + return this.step(Infinity) } - reverse ( reverse ) { - + reverse (reverse) { this._reverse = reverse == null ? !this._reverse : reverse return this - } - ease ( fn ) { - - this._stepper = new Ease( fn ) + ease (fn) { + this._stepper = new Ease(fn) return this - } - active ( enabled ) { - - if ( enabled == null ) return this.enabled + active (enabled) { + if (enabled == null) return this.enabled this.enabled = enabled return this - } /* @@ -384,135 +319,102 @@ export default class Runner extends EventTarget { */ // Save a morpher to the morpher list so that we can retarget it later - _rememberMorpher ( method, morpher ) { - + _rememberMorpher (method, morpher) { this._history[method] = { morpher: morpher, caller: this._queue[this._queue.length - 1] } - } // Try to set the target for a morpher if the morpher exists, otherwise // do nothing and return false - _tryRetarget ( method, target ) { - - if ( this._history[method] ) { - + _tryRetarget (method, target) { + if (this._history[method]) { // if the last method wasnt even initialised, throw it away - if ( !this._history[method].caller.initialised ) { - - let index = this._queue.indexOf( this._history[method].caller ) - this._queue.splice( index, 1 ) + if (!this._history[method].caller.initialised) { + let index = this._queue.indexOf(this._history[method].caller) + this._queue.splice(index, 1) return false - } // for the case of transformations, we use the special retarget function // which has access to the outer scope - if ( this._history[method].caller.retarget ) { - - this._history[method].caller.retarget( target ) + if (this._history[method].caller.retarget) { + this._history[method].caller.retarget(target) // for everything else a simple morpher change is sufficient - } else { - - this._history[method].morpher.to( target ) - + this._history[method].morpher.to(target) } this._history[method].caller.finished = false var timeline = this.timeline() timeline && timeline._continue() return true - } return false - } // Run each initialise function in the runner if required - _initialise ( running ) { - + _initialise (running) { // If we aren't running, we shouldn't initialise when not declarative - if ( !running && !this._isDeclarative ) return + if (!running && !this._isDeclarative) return // Loop through all of the initialisers - for ( var i = 0, len = this._queue.length; i < len; ++i ) { - + for (var i = 0, len = this._queue.length; i < len; ++i) { // Get the current initialiser var current = this._queue[i] // Determine whether we need to initialise - var needsIt = this._isDeclarative || ( !current.initialised && running ) + var needsIt = this._isDeclarative || (!current.initialised && running) running = !current.finished // Call the initialiser if we need to - if ( needsIt && running ) { - - current.initialiser.call( this ) + if (needsIt && running) { + current.initialiser.call(this) current.initialised = true - } - } - } // Run each run function for the position or dt given - _run ( positionOrDt ) { - + _run (positionOrDt) { // Run all of the _queue directly var allfinished = true - for ( var i = 0, len = this._queue.length; i < len; ++i ) { - + for (var i = 0, len = this._queue.length; i < len; ++i) { // Get the current function to run var current = this._queue[i] // Run the function if its not finished, we keep track of the finished // flag for the sake of declarative _queue - var converged = current.runner.call( this, positionOrDt ) - current.finished = current.finished || ( converged === true ) + var converged = current.runner.call(this, positionOrDt) + current.finished = current.finished || (converged === true) allfinished = allfinished && current.finished - } // We report when all of the constructors are finished return allfinished - } - addTransform ( transform, index ) { - - this.transforms.lmultiplyO( transform ) + addTransform (transform, index) { + this.transforms.lmultiplyO(transform) return this - } clearTransform () { - this.transforms = new Matrix() return this - } // TODO: Keep track of all transformations so that deletion is faster clearTransformsFromQueue () { - - if ( !this.done ) { - - this._queue = this._queue.filter( ( item ) => { - + if (!this.done) { + this._queue = this._queue.filter((item) => { return !item.isTransform - - } ) - + }) } - } - static sanitise ( duration, delay, when ) { - + static sanitise (duration, delay, when) { // Initialise the default parameters var times = 1 var swing = false @@ -522,15 +424,13 @@ export default class Runner extends EventTarget { when = when || 'last' // If we have an object, unpack the values - if ( typeof duration === 'object' && !( duration instanceof Stepper ) ) { - + if (typeof duration === 'object' && !(duration instanceof Stepper)) { delay = duration.delay || delay when = duration.when || when swing = duration.swing || swing times = duration.times || times wait = duration.wait || wait duration = duration.duration || timeline.duration - } return { @@ -541,285 +441,215 @@ export default class Runner extends EventTarget { wait: wait, when: when } - } - } Runner.id = 0 class FakeRunner { - - constructor ( transforms = new Matrix(), id = -1, done = true ) { - + constructor (transforms = new Matrix(), id = -1, done = true) { this.transforms = transforms this.id = id this.done = done - } clearTransformsFromQueue () { } - } -extend( [ Runner, FakeRunner ], { - mergeWith ( runner ) { - +extend([ Runner, FakeRunner ], { + mergeWith (runner) { return new FakeRunner( - runner.transforms.lmultiply( this.transforms ), + runner.transforms.lmultiply(this.transforms), runner.id ) - } -} ) +}) // FakeRunner.emptyRunner = new FakeRunner() -const lmultiply = ( last, curr ) => last.lmultiplyO( curr ) -const getRunnerTransform = ( runner ) => runner.transforms +const lmultiply = (last, curr) => last.lmultiplyO(curr) +const getRunnerTransform = (runner) => runner.transforms function mergeTransforms () { - // Find the matrix to apply to the element and apply it let runners = this._transformationRunners.runners let netTransform = runners - .map( getRunnerTransform ) - .reduce( lmultiply, new Matrix() ) + .map(getRunnerTransform) + .reduce(lmultiply, new Matrix()) - this.transform( netTransform ) + this.transform(netTransform) this._transformationRunners.merge() - if ( this._transformationRunners.length() === 1 ) { - + if (this._transformationRunners.length() === 1) { this._frameId = null - } - } class RunnerArray { - constructor () { - this.runners = [] this.ids = [] - } - add ( runner ) { - - if ( this.runners.includes( runner ) ) return + add (runner) { + if (this.runners.includes(runner)) return let id = runner.id + 1 - let leftSibling = this.ids.reduce( ( last, curr ) => { - - if ( curr > last && curr < id ) return curr + let leftSibling = this.ids.reduce((last, curr) => { + if (curr > last && curr < id) return curr return last + }, 0) - }, 0 ) + let index = this.ids.indexOf(leftSibling) + 1 - let index = this.ids.indexOf( leftSibling ) + 1 - - this.ids.splice( index, 0, id ) - this.runners.splice( index, 0, runner ) + this.ids.splice(index, 0, id) + this.runners.splice(index, 0, runner) return this - } - getByID ( id ) { - - return this.runners[this.ids.indexOf( id + 1 )] - + getByID (id) { + return this.runners[this.ids.indexOf(id + 1)] } - remove ( id ) { - - let index = this.ids.indexOf( id + 1 ) - this.ids.splice( index, 1 ) - this.runners.splice( index, 1 ) + remove (id) { + let index = this.ids.indexOf(id + 1) + this.ids.splice(index, 1) + this.runners.splice(index, 1) return this - } merge () { - let lastRunner = null - this.runners.forEach( ( runner, i ) => { - - if ( lastRunner && runner.done && lastRunner.done ) { - - this.remove( runner.id ) - this.edit( lastRunner.id, runner.mergeWith( lastRunner ) ) - + this.runners.forEach((runner, i) => { + if (lastRunner && runner.done && lastRunner.done) { + this.remove(runner.id) + this.edit(lastRunner.id, runner.mergeWith(lastRunner)) } lastRunner = runner - - } ) + }) return this - } - edit ( id, newRunner ) { - - let index = this.ids.indexOf( id + 1 ) - this.ids.splice( index, 1, id ) - this.runners.splice( index, 1, newRunner ) + edit (id, newRunner) { + let index = this.ids.indexOf(id + 1) + this.ids.splice(index, 1, id) + this.runners.splice(index, 1, newRunner) return this - } length () { - return this.ids.length - } - clearBefore ( id ) { - - let deleteCnt = this.ids.indexOf( id + 1 ) || 1 - this.ids.splice( 0, deleteCnt, 0 ) - this.runners.splice( 0, deleteCnt, new FakeRunner() ) - .forEach( ( r ) => r.clearTransformsFromQueue() ) + clearBefore (id) { + let deleteCnt = this.ids.indexOf(id + 1) || 1 + this.ids.splice(0, deleteCnt, 0) + this.runners.splice(0, deleteCnt, new FakeRunner()) + .forEach((r) => r.clearTransformsFromQueue()) return this - } - } let frameId = 0 -registerMethods( { +registerMethods({ Element: { - animate ( duration, delay, when ) { - - var o = Runner.sanitise( duration, delay, when ) + animate (duration, delay, when) { + var o = Runner.sanitise(duration, delay, when) var timeline = this.timeline() - return new Runner( o.duration ) - .loop( o ) - .element( this ) - .timeline( timeline ) - .schedule( delay, when ) - + return new Runner(o.duration) + .loop(o) + .element(this) + .timeline(timeline) + .schedule(delay, when) }, - delay ( by, when ) { - - return this.animate( 0, by, when ) - + delay (by, when) { + return this.animate(0, by, when) }, // this function searches for all runners on the element and deletes the ones // which run before the current one. This is because absolute transformations // overwfrite anything anyway so there is no need to waste time computing // other runners - _clearTransformRunnersBefore ( currentRunner ) { - - this._transformationRunners.clearBefore( currentRunner.id ) - + _clearTransformRunnersBefore (currentRunner) { + this._transformationRunners.clearBefore(currentRunner.id) }, - _currentTransform ( current ) { - + _currentTransform (current) { return this._transformationRunners.runners // we need the equal sign here to make sure, that also transformations // on the same runner which execute before the current transformation are // taken into account - .filter( ( runner ) => runner.id <= current.id ) - .map( getRunnerTransform ) - .reduce( lmultiply, new Matrix() ) - + .filter((runner) => runner.id <= current.id) + .map(getRunnerTransform) + .reduce(lmultiply, new Matrix()) }, - addRunner ( runner ) { - - this._transformationRunners.add( runner ) + addRunner (runner) { + this._transformationRunners.add(runner) Animator.transform_frame( - mergeTransforms.bind( this ), this._frameId + mergeTransforms.bind(this), this._frameId ) - }, _prepareRunner () { - - if ( this._frameId == null ) { - + if (this._frameId == null) { this._transformationRunners = new RunnerArray() - .add( new FakeRunner( new Matrix( this ) ) ) + .add(new FakeRunner(new Matrix(this))) this._frameId = frameId++ - } - } } -} ) - -extend( Runner, { - attr ( a, v ) { - - return this.styleAttr( 'attr', a, v ) +}) +extend(Runner, { + attr (a, v) { + return this.styleAttr('attr', a, v) }, // Add animatable styles - css ( s, v ) { - - return this.styleAttr( 'css', s, v ) - + css (s, v) { + return this.styleAttr('css', s, v) }, - styleAttr ( type, name, val ) { - + styleAttr (type, name, val) { // apply attributes individually - if ( typeof name === 'object' ) { - - for ( var key in val ) { - - this.styleAttr( type, key, val[key] ) - + if (typeof name === 'object') { + for (var key in val) { + this.styleAttr(type, key, val[key]) } - } - var morpher = new Morphable( this._stepper ).to( val ) - - this.queue( function () { - - morpher = morpher.from( this.element()[type]( name ) ) - - }, function ( pos ) { + var morpher = new Morphable(this._stepper).to(val) - this.element()[type]( name, morpher.at( pos ) ) + this.queue(function () { + morpher = morpher.from(this.element()[type](name)) + }, function (pos) { + this.element()[type](name, morpher.at(pos)) return morpher.done() - - } ) + }) return this - }, - zoom ( level, point ) { - - var morpher = new Morphable( this._stepper ).to( new SVGNumber( level ) ) - - this.queue( function () { + zoom (level, point) { + var morpher = new Morphable(this._stepper).to(new SVGNumber(level)) - morpher = morpher.from( this.zoom() ) - - }, function ( pos ) { - - this.element().zoom( morpher.at( pos ), point ) + this.queue(function () { + morpher = morpher.from(this.zoom()) + }, function (pos) { + this.element().zoom(morpher.at(pos), point) return morpher.done() - - } ) + }) return this - }, /** @@ -839,25 +669,22 @@ extend( Runner, { // - Note F(1) = T // 4. Now you get the delta matrix as a result: D = F * inv(M) - transform ( transforms, relative, affine ) { - + transform (transforms, relative, affine) { // If we have a declarative function, we should retarget it if possible relative = transforms.relative || relative - if ( this._isDeclarative && !relative && this._tryRetarget( 'transform', transforms ) ) { - + if (this._isDeclarative && !relative && this._tryRetarget('transform', transforms)) { return this - } // Parse the parameters - var isMatrix = Matrix.isMatrixLike( transforms ) + var isMatrix = Matrix.isMatrixLike(transforms) affine = transforms.affine != null ? transforms.affine - : ( affine != null ? affine : !isMatrix ) + : (affine != null ? affine : !isMatrix) // Create a morepher and set its type - const morpher = new Morphable( this._stepper ) - .type( affine ? TransformBag : Matrix ) + const morpher = new Morphable(this._stepper) + .type(affine ? TransformBag : Matrix) let origin let element @@ -866,42 +693,36 @@ extend( Runner, { let startTransform function setup () { - // make sure element and origin is defined element = element || this.element() - origin = origin || getOrigin( transforms, element ) + origin = origin || getOrigin(transforms, element) - startTransform = new Matrix( relative ? undefined : element ) + startTransform = new Matrix(relative ? undefined : element) // add the runner to the element so it can merge transformations - element.addRunner( this ) + element.addRunner(this) // Deactivate all transforms that have run so far if we are absolute - if ( !relative ) { - - element._clearTransformRunnersBefore( this ) - + if (!relative) { + element._clearTransformRunnersBefore(this) } - } - function run ( pos ) { - + function run (pos) { // clear all other transforms before this in case something is saved // on this runner. We are absolute. We dont need these! - if ( !relative ) this.clearTransform() + if (!relative) this.clearTransform() - let { x, y } = new Point( origin ).transform( element._currentTransform( this ) ) + let { x, y } = new Point(origin).transform(element._currentTransform(this)) - let target = new Matrix( { ...transforms, origin: [ x, y ] } ) + let target = new Matrix({ ...transforms, origin: [ x, y ] }) let start = this._isDeclarative && current ? current : startTransform - if ( affine ) { - - target = target.decompose( x, y ) - start = start.decompose( x, y ) + if (affine) { + target = target.decompose(x, y) + start = start.decompose(x, y) // Get the current and target angle as it was set const rTarget = target.rotate @@ -909,285 +730,212 @@ extend( Runner, { // Figure out the shortest path to rotate directly const possibilities = [ rTarget - 360, rTarget, rTarget + 360 ] - const distances = possibilities.map( a => Math.abs( a - rCurrent ) ) - const shortest = Math.min( ...distances ) - const index = distances.indexOf( shortest ) + const distances = possibilities.map(a => Math.abs(a - rCurrent)) + const shortest = Math.min(...distances) + const index = distances.indexOf(shortest) target.rotate = possibilities[index] - } - if ( relative ) { - + if (relative) { // we have to be careful here not to overwrite the rotation // with the rotate method of Matrix - if ( !isMatrix ) { - + if (!isMatrix) { target.rotate = transforms.rotate || 0 - } - if ( this._isDeclarative && currentAngle ) { - + if (this._isDeclarative && currentAngle) { start.rotate = currentAngle - } - } - morpher.from( start ) - morpher.to( target ) + morpher.from(start) + morpher.to(target) - let affineParameters = morpher.at( pos ) + let affineParameters = morpher.at(pos) currentAngle = affineParameters.rotate - current = new Matrix( affineParameters ) + current = new Matrix(affineParameters) - this.addTransform( current ) + this.addTransform(current) return morpher.done() - } - function retarget ( newTransforms ) { - + function retarget (newTransforms) { // only get a new origin if it changed since the last call if ( - ( newTransforms.origin || 'center' ).toString() - !== ( transforms.origin || 'center' ).toString() + (newTransforms.origin || 'center').toString() + !== (transforms.origin || 'center').toString() ) { - - origin = getOrigin( transforms, element ) - + origin = getOrigin(transforms, element) } // overwrite the old transformations with the new ones transforms = { ...newTransforms, origin } - } - this.queue( setup, run, retarget, true ) - this._isDeclarative && this._rememberMorpher( 'transform', morpher ) + this.queue(setup, run, retarget, true) + this._isDeclarative && this._rememberMorpher('transform', morpher) return this - }, // Animatable x-axis - x ( x, relative ) { - - return this._queueNumber( 'x', x ) - + x (x, relative) { + return this._queueNumber('x', x) }, // Animatable y-axis - y ( y ) { - - return this._queueNumber( 'y', y ) - + y (y) { + return this._queueNumber('y', y) }, - dx ( x ) { - - return this._queueNumberDelta( 'x', x ) - + dx (x) { + return this._queueNumberDelta('x', x) }, - dy ( y ) { - - return this._queueNumberDelta( 'y', y ) - + dy (y) { + return this._queueNumberDelta('y', y) }, - _queueNumberDelta ( method, to ) { - - to = new SVGNumber( to ) + _queueNumberDelta (method, to) { + to = new SVGNumber(to) // Try to change the target if we have this method already registerd - if ( this._tryRetarget( method, to ) ) return this + if (this._tryRetarget(method, to)) return this // Make a morpher and queue the animation - var morpher = new Morphable( this._stepper ).to( to ) + var morpher = new Morphable(this._stepper).to(to) var from = null - this.queue( function () { - + this.queue(function () { from = this.element()[method]() - morpher.from( from ) - morpher.to( from + to ) - - }, function ( pos ) { - - this.element()[method]( morpher.at( pos ) ) + morpher.from(from) + morpher.to(from + to) + }, function (pos) { + this.element()[method](morpher.at(pos)) return morpher.done() - - }, function ( newTo ) { - - morpher.to( from + new SVGNumber( newTo ) ) - - } ) + }, function (newTo) { + morpher.to(from + new SVGNumber(newTo)) + }) // Register the morpher so that if it is changed again, we can retarget it - this._rememberMorpher( method, morpher ) + this._rememberMorpher(method, morpher) return this - }, - _queueObject ( method, to ) { - + _queueObject (method, to) { // Try to change the target if we have this method already registerd - if ( this._tryRetarget( method, to ) ) return this + if (this._tryRetarget(method, to)) return this // Make a morpher and queue the animation - var morpher = new Morphable( this._stepper ).to( to ) - this.queue( function () { - - morpher.from( this.element()[method]() ) - - }, function ( pos ) { - - this.element()[method]( morpher.at( pos ) ) + var morpher = new Morphable(this._stepper).to(to) + this.queue(function () { + morpher.from(this.element()[method]()) + }, function (pos) { + this.element()[method](morpher.at(pos)) return morpher.done() - - } ) + }) // Register the morpher so that if it is changed again, we can retarget it - this._rememberMorpher( method, morpher ) + this._rememberMorpher(method, morpher) return this - }, - _queueNumber ( method, value ) { - - return this._queueObject( method, new SVGNumber( value ) ) - + _queueNumber (method, value) { + return this._queueObject(method, new SVGNumber(value)) }, // Animatable center x-axis - cx ( x ) { - - return this._queueNumber( 'cx', x ) - + cx (x) { + return this._queueNumber('cx', x) }, // Animatable center y-axis - cy ( y ) { - - return this._queueNumber( 'cy', y ) - + cy (y) { + return this._queueNumber('cy', y) }, // Add animatable move - move ( x, y ) { - - return this.x( x ).y( y ) - + move (x, y) { + return this.x(x).y(y) }, // Add animatable center - center ( x, y ) { - - return this.cx( x ).cy( y ) - + center (x, y) { + return this.cx(x).cy(y) }, // Add animatable size - size ( width, height ) { - + size (width, height) { // animate bbox based size for all other elements var box - if ( !width || !height ) { - + if (!width || !height) { box = this._element.bbox() - } - if ( !width ) { - + if (!width) { width = box.width / box.height * height - } - if ( !height ) { - + if (!height) { height = box.height / box.width * width - } return this - .width( width ) - .height( height ) - + .width(width) + .height(height) }, // Add animatable width - width ( width ) { - - return this._queueNumber( 'width', width ) - + width (width) { + return this._queueNumber('width', width) }, // Add animatable height - height ( height ) { - - return this._queueNumber( 'height', height ) - + height (height) { + return this._queueNumber('height', height) }, // Add animatable plot - plot ( a, b, c, d ) { - + plot (a, b, c, d) { // Lines can be plotted with 4 arguments - if ( arguments.length === 4 ) { - - return this.plot( [ a, b, c, d ] ) - + if (arguments.length === 4) { + return this.plot([ a, b, c, d ]) } - var morpher = this._element.MorphArray().to( a ) - - this.queue( function () { - - morpher.from( this._element.array() ) + var morpher = this._element.MorphArray().to(a) - }, function ( pos ) { - - this._element.plot( morpher.at( pos ) ) - - } ) + this.queue(function () { + morpher.from(this._element.array()) + }, function (pos) { + this._element.plot(morpher.at(pos)) + }) return this - }, // Add leading method - leading ( value ) { - - return this._queueNumber( 'leading', value ) - + leading (value) { + return this._queueNumber('leading', value) }, // Add animatable viewbox - viewbox ( x, y, width, height ) { - - return this._queueObject( 'viewbox', new Box( x, y, width, height ) ) - + viewbox (x, y, width, height) { + return this._queueObject('viewbox', new Box(x, y, width, height)) }, - update ( o ) { - - if ( typeof o !== 'object' ) { - - return this.update( { + update (o) { + if (typeof o !== 'object') { + return this.update({ offset: arguments[0], color: arguments[1], opacity: arguments[2] - } ) - + }) } - if ( o.opacity != null ) this.attr( 'stop-opacity', o.opacity ) - if ( o.color != null ) this.attr( 'stop-color', o.color ) - if ( o.offset != null ) this.attr( 'offset', o.offset ) + if (o.opacity != null) this.attr('stop-opacity', o.opacity) + if (o.color != null) this.attr('stop-color', o.color) + if (o.offset != null) this.attr('offset', o.offset) return this - } -} ) +}) -extend( Runner, { rx, ry, from, to } ) +extend(Runner, { rx, ry, from, to }) diff --git a/src/animation/Timeline.js b/src/animation/Timeline.js index 2fa281c..6abcb80 100644 --- a/src/animation/Timeline.js +++ b/src/animation/Timeline.js @@ -3,27 +3,21 @@ import { registerMethods } from '../utils/methods.js' import Animator from './Animator.js' import EventTarget from '../types/EventTarget.js' -var makeSchedule = function ( runnerInfo ) { - +var makeSchedule = function (runnerInfo) { var start = runnerInfo.start var duration = runnerInfo.runner.duration() var end = start + duration return { start: start, duration: duration, end: end, runner: runnerInfo.runner } - } export default class Timeline extends EventTarget { - // Construct a new timeline on the given element constructor () { - super() this._timeSource = function () { - let w = globals.window - return ( w.performance || w.Date ).now() - + return (w.performance || w.Date).now() } // Store the timing variables @@ -42,7 +36,6 @@ export default class Timeline extends EventTarget { this._time = 0 this._lastSourceTime = 0 this._lastStepTime = 0 - } /** @@ -50,28 +43,19 @@ export default class Timeline extends EventTarget { */ // schedules a runner on the timeline - schedule ( runner, delay, when ) { - + schedule (runner, delay, when) { // FIXME: how to sort? maybe by runner id? - if ( runner == null ) { - - return this._runners.map( makeSchedule ).sort( function ( a, b ) { - - return ( a.start - b.start ) || ( a.duration - b.duration ) - - } ) - + if (runner == null) { + return this._runners.map(makeSchedule).sort(function (a, b) { + return (a.start - b.start) || (a.duration - b.duration) + }) } - if ( !this.active() ) { - + if (!this.active()) { this._step() - if ( when == null ) { - + if (when == null) { when = 'now' - } - } // The start time for the next animation can either be given explicitly, @@ -81,40 +65,28 @@ export default class Timeline extends EventTarget { delay = delay || 0 // Work out when to start the animation - if ( when == null || when === 'last' || when === 'after' ) { - + if (when == null || when === 'last' || when === 'after') { // Take the last time and increment absoluteStartTime = this._startTime - - } else if ( when === 'absolute' || when === 'start' ) { - + } else if (when === 'absolute' || when === 'start') { absoluteStartTime = delay delay = 0 - - } else if ( when === 'now' ) { - + } else if (when === 'now') { absoluteStartTime = this._time - - } else if ( when === 'relative' ) { - + } else if (when === 'relative') { let runnerInfo = this._runners[runner.id] - if ( runnerInfo ) { - + if (runnerInfo) { absoluteStartTime = runnerInfo.start + delay delay = 0 - } - } else { - - throw new Error( 'Invalid value for the "when" parameter' ) - + throw new Error('Invalid value for the "when" parameter') } // Manage runner runner.unschedule() - runner.timeline( this ) - runner.time( -delay ) + runner.timeline(this) + runner.time(-delay) // Save startTime for next runner this._startTime = absoluteStartTime + runner.duration() + delay @@ -127,115 +99,91 @@ export default class Timeline extends EventTarget { } // Save order and continue - this._order.push( runner.id ) + this._order.push(runner.id) this._continue() return this - } // Remove the runner from this timeline - unschedule ( runner ) { - - var index = this._order.indexOf( runner.id ) - if ( index < 0 ) return this + unschedule (runner) { + var index = this._order.indexOf(runner.id) + if (index < 0) return this delete this._runners[runner.id] - this._order.splice( index, 1 ) - runner.timeline( null ) + this._order.splice(index, 1) + runner.timeline(null) return this - } play () { - // Now make sure we are not paused and continue the animation this._paused = false return this._continue() - } pause () { - // Cancel the next animation frame and pause this._nextFrame = null this._paused = true return this - } stop () { - // Cancel the next animation frame and go to start - this.seek( -this._time ) + this.seek(-this._time) return this.pause() - } finish () { - - this.seek( Infinity ) + this.seek(Infinity) return this.pause() - } - speed ( speed ) { - - if ( speed == null ) return this._speed + speed (speed) { + if (speed == null) return this._speed this._speed = speed return this - } - reverse ( yes ) { - + reverse (yes) { var currentSpeed = this.speed() - if ( yes == null ) return this.speed( -currentSpeed ) - - var positive = Math.abs( currentSpeed ) - return this.speed( yes ? positive : -positive ) + if (yes == null) return this.speed(-currentSpeed) + var positive = Math.abs(currentSpeed) + return this.speed(yes ? positive : -positive) } - seek ( dt ) { - + seek (dt) { this._time += dt return this._continue() - } - time ( time ) { - - if ( time == null ) return this._time + time (time) { + if (time == null) return this._time this._time = time return this - } - persist ( dtOrForever ) { - - if ( dtOrForever == null ) return this._persist + persist (dtOrForever) { + if (dtOrForever == null) return this._persist this._persist = dtOrForever return this - } - source ( fn ) { - - if ( fn == null ) return this._timeSource + source (fn) { + if (fn == null) return this._timeSource this._timeSource = fn return this - } _step () { - // If the timeline is paused, just do nothing - if ( this._paused ) return + if (this._paused) return // Get the time delta from the last time and update the time var time = this._timeSource() var dtSource = time - this._lastSourceTime - var dtTime = this._speed * dtSource + ( this._time - this._lastStepTime ) + var dtTime = this._speed * dtSource + (this._time - this._lastStepTime) this._lastSourceTime = time // Update the time @@ -245,8 +193,7 @@ export default class Timeline extends EventTarget { // Run all of the runners directly var runnersLeft = false - for ( var i = 0, len = this._order.length; i < len; i++ ) { - + for (var i = 0, len = this._order.length; i < len; i++) { // Get and run the current runner and ignore it if its inactive var runnerInfo = this._runners[this._order[i]] var runner = runnerInfo.runner @@ -257,89 +204,64 @@ export default class Timeline extends EventTarget { let dtToStart = this._time - runnerInfo.start // Dont run runner if not started yet - if ( dtToStart < 0 ) { - + if (dtToStart < 0) { runnersLeft = true continue - - } else if ( dtToStart < dt ) { - + } else if (dtToStart < dt) { // Adjust dt to make sure that animation is on point dt = dtToStart - } - if ( !runner.active() ) continue + if (!runner.active()) continue // If this runner is still going, signal that we need another animation // frame, otherwise, remove the completed runner - var finished = runner.step( dt ).done - if ( !finished ) { - + var finished = runner.step(dt).done + if (!finished) { runnersLeft = true // continue - - } else if ( runnerInfo.persist !== true ) { - + } else if (runnerInfo.persist !== true) { // runner is finished. And runner might get removed var endTime = runner.duration() - runner.time() + this._time - if ( endTime + this._persist < this._time ) { - + if (endTime + this._persist < this._time) { // Delete runner and correct index delete this._runners[this._order[i]] - this._order.splice( i--, 1 ) && --len - runner.timeline( null ) - + this._order.splice(i--, 1) && --len + runner.timeline(null) } - } - } // Get the next animation frame to keep the simulation going - if ( runnersLeft ) { - - this._nextFrame = Animator.frame( this._step.bind( this ) ) - + if (runnersLeft) { + this._nextFrame = Animator.frame(this._step.bind(this)) } else { - this._nextFrame = null - } return this - } // Checks if we are running and continues the animation _continue () { - - if ( this._paused ) return this - if ( !this._nextFrame ) { - - this._nextFrame = Animator.frame( this._step.bind( this ) ) - + if (this._paused) return this + if (!this._nextFrame) { + this._nextFrame = Animator.frame(this._step.bind(this)) } return this - } active () { - return !!this._nextFrame - } - } -registerMethods( { +registerMethods({ Element: { timeline: function () { - - this._timeline = ( this._timeline || new Timeline() ) + this._timeline = (this._timeline || new Timeline()) return this._timeline - } } -} ) +}) diff --git a/src/elements/A.js b/src/elements/A.js index ee81975..ef047a2 100644 --- a/src/elements/A.js +++ b/src/elements/A.js @@ -4,58 +4,42 @@ import { xlink } from '../modules/core/namespaces.js' import Container from './Container.js' export default class A extends Container { - - constructor ( node ) { - - super( nodeOrNew( 'a', node ), node ) - + constructor (node) { + super(nodeOrNew('a', node), node) } // Link url - to ( url ) { - - return this.attr( 'href', url, xlink ) - + to (url) { + return this.attr('href', url, xlink) } // Link target attribute - target ( target ) { - - return this.attr( 'target', target ) - + target (target) { + return this.attr('target', target) } - } -registerMethods( { +registerMethods({ Container: { // Create a hyperlink element - link: wrapWithAttrCheck( function ( url ) { - - return this.put( new A() ).to( url ) - - } ) + link: wrapWithAttrCheck(function (url) { + return this.put(new A()).to(url) + }) }, Element: { // Create a hyperlink element - linkTo: function ( url ) { - + linkTo: function (url) { var link = new A() - if ( typeof url === 'function' ) { - - url.call( link, link ) - + if (typeof url === 'function') { + url.call(link, link) } else { - - link.to( url ) - + link.to(url) } - return this.parent().put( link ).put( this ) - + return this.parent().put(link).put(this) } } -} ) +}) -register( A ) +register(A) diff --git a/src/elements/Bare.js b/src/elements/Bare.js index 190aa1f..a057634 100644 --- a/src/elements/Bare.js +++ b/src/elements/Bare.js @@ -4,38 +4,28 @@ import Container from './Container.js' import { globals } from '../utils/window.js' export default class Bare extends Container { - - constructor ( node, attrs ) { - - super( nodeOrNew( node, typeof node === 'string' ? null : node ), attrs ) - + constructor (node, attrs) { + super(nodeOrNew(node, typeof node === 'string' ? null : node), attrs) } - words ( text ) { - + words (text) { // remove contents - while ( this.node.hasChildNodes() ) { - - this.node.removeChild( this.node.lastChild ) - + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild) } // create text node - this.node.appendChild( globals.document.createTextNode( text ) ) + this.node.appendChild(globals.document.createTextNode(text)) return this - } - } -register( Bare ) +register(Bare) -registerMethods( 'Container', { +registerMethods('Container', { // Create an element that is not described by SVG.js - element: wrapWithAttrCheck( function ( node ) { - - return this.put( new Bare( node ) ) - - } ) -} ) + element: wrapWithAttrCheck(function (node) { + return this.put(new Bare(node)) + }) +}) diff --git a/src/elements/Circle.js b/src/elements/Circle.js index 5aa969a..3135ada 100644 --- a/src/elements/Circle.js +++ b/src/elements/Circle.js @@ -10,54 +10,40 @@ import SVGNumber from '../types/SVGNumber.js' import Shape from './Shape.js' export default class Circle extends Shape { - - constructor ( node ) { - - super( nodeOrNew( 'circle', node ), node ) - + constructor (node) { + super(nodeOrNew('circle', node), node) } - radius ( r ) { - - return this.attr( 'r', r ) - + radius (r) { + return this.attr('r', r) } // Radius x value - rx ( rx ) { - - return this.attr( 'r', rx ) - + rx (rx) { + return this.attr('r', rx) } // Alias radius x value - ry ( ry ) { - - return this.rx( ry ) - + ry (ry) { + return this.rx(ry) } - size ( size ) { - - return this.radius( new SVGNumber( size ).divide( 2 ) ) - + size (size) { + return this.radius(new SVGNumber(size).divide(2)) } - } -extend( Circle, { x, y, cx, cy, width, height } ) +extend(Circle, { x, y, cx, cy, width, height }) -registerMethods( { +registerMethods({ Element: { // Create circle element - circle: wrapWithAttrCheck( function ( size ) { - - return this.put( new Circle() ) - .size( size ) - .move( 0, 0 ) - - } ) + circle: wrapWithAttrCheck(function (size) { + return this.put(new Circle()) + .size(size) + .move(0, 0) + }) } -} ) +}) -register( Circle ) +register(Circle) diff --git a/src/elements/ClipPath.js b/src/elements/ClipPath.js index 199ee5b..e545baa 100644 --- a/src/elements/ClipPath.js +++ b/src/elements/ClipPath.js @@ -4,72 +4,54 @@ import Container from './Container.js' import baseFind from '../modules/core/selector.js' export default class ClipPath extends Container { - - constructor ( node ) { - - super( nodeOrNew( 'clipPath', node ), node ) - + constructor (node) { + super(nodeOrNew('clipPath', node), node) } // Unclip all clipped elements and remove itself remove () { - // unclip all targets - this.targets().forEach( function ( el ) { - + this.targets().forEach(function (el) { el.unclip() - - } ) + }) // remove clipPath from parent return super.remove() - } targets () { - - return baseFind( 'svg [clip-path*="' + this.id() + '"]' ) - + return baseFind('svg [clip-path*="' + this.id() + '"]') } - } -registerMethods( { +registerMethods({ Container: { // Create clipping element - clip: wrapWithAttrCheck( function () { - - return this.defs().put( new ClipPath() ) - - } ) + clip: wrapWithAttrCheck(function () { + return this.defs().put(new ClipPath()) + }) }, Element: { // Distribute clipPath to svg element - clipWith ( element ) { - + clipWith (element) { // use given clip or create a new one let clipper = element instanceof ClipPath ? element - : this.parent().clip().add( element ) + : this.parent().clip().add(element) // apply mask - return this.attr( 'clip-path', 'url("#' + clipper.id() + '")' ) - + return this.attr('clip-path', 'url("#' + clipper.id() + '")') }, // Unclip element unclip () { - - return this.attr( 'clip-path', null ) - + return this.attr('clip-path', null) }, clipper () { - - return this.reference( 'clip-path' ) - + return this.reference('clip-path') } } -} ) +}) -register( ClipPath ) +register(ClipPath) diff --git a/src/elements/Container.js b/src/elements/Container.js index 82ee0ae..b47972e 100644 --- a/src/elements/Container.js +++ b/src/elements/Container.js @@ -2,39 +2,29 @@ import { register } from '../utils/adopter.js' import Element from './Element.js' export default class Container extends Element { - - flatten ( parent ) { - - this.each( function () { - - if ( this instanceof Container ) return this.flatten( parent ).ungroup( parent ) - return this.toParent( parent ) - - } ) + flatten (parent) { + this.each(function () { + if (this instanceof Container) return this.flatten(parent).ungroup(parent) + return this.toParent(parent) + }) // we need this so that the root does not get removed this.node.firstElementChild || this.remove() return this - } - ungroup ( parent ) { - + ungroup (parent) { parent = parent || this.parent() - this.each( function () { - - return this.toParent( parent ) - - } ) + this.each(function () { + return this.toParent(parent) + }) this.remove() return this - } - } -register( Container ) +register(Container) diff --git a/src/elements/Defs.js b/src/elements/Defs.js index bcbea01..6b486ca 100644 --- a/src/elements/Defs.js +++ b/src/elements/Defs.js @@ -2,24 +2,16 @@ import { nodeOrNew, register } from '../utils/adopter.js' import Container from './Container.js' export default class Defs extends Container { - - constructor ( node ) { - - super( nodeOrNew( 'defs', node ), node ) - + constructor (node) { + super(nodeOrNew('defs', node), node) } flatten () { - return this - } ungroup () { - return this - } - } -register( Defs ) +register(Defs) diff --git a/src/elements/Dom.js b/src/elements/Dom.js index f3ea467..566008c 100644 --- a/src/elements/Dom.js +++ b/src/elements/Dom.js @@ -15,294 +15,217 @@ import List from '../types/List.js' import attr from '../modules/core/attr.js' export default class Dom extends EventTarget { - - constructor ( node, attrs ) { - - super( node ) + constructor (node, attrs) { + super(node) this.node = node this.type = node.nodeName - if ( attrs && node !== attrs ) { - - this.attr( attrs ) - + if (attrs && node !== attrs) { + this.attr(attrs) } - } // Add given element at a position - add ( element, i ) { - - element = makeInstance( element ) - - 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] ) + add (element, i) { + element = makeInstance(element) + 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 - } // Add element to given container and return self - addTo ( parent ) { - - return makeInstance( parent ).put( this ) - + addTo (parent) { + return makeInstance(parent).put(this) } // Returns all child elements children () { - - return new List( map( this.node.children, function ( node ) { - - return adopt( node ) - - } ) ) - + return new List(map(this.node.children, function (node) { + return adopt(node) + })) } // Remove all elements in this container clear () { - // remove children - while ( this.node.hasChildNodes() ) { - - this.node.removeChild( this.node.lastChild ) - + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild) } // remove defs reference delete this._defs return this - } // Clone element clone () { - // write dom data to the dom so the clone can pickup the data this.writeDataToDom() // clone element and assign new id - return assignNewId( this.node.cloneNode( true ) ) - + return assignNewId(this.node.cloneNode(true)) } // Iterates over all children and invokes a given block - each ( block, deep ) { - + each (block, deep) { var children = this.children() var i, il - for ( i = 0, il = children.length; i < il; i++ ) { - - block.apply( children[i], [ i, children ] ) - - if ( deep ) { - - children[i].each( block, deep ) + for (i = 0, il = children.length; i < il; i++) { + block.apply(children[i], [ i, children ]) + if (deep) { + children[i].each(block, deep) } - } return this - } // Get first child first () { - - return adopt( this.node.firstChild ) - + return adopt(this.node.firstChild) } // Get a element at the given index - get ( i ) { - - return adopt( this.node.childNodes[i] ) - + get (i) { + return adopt(this.node.childNodes[i]) } getEventHolder () { - return this.node - } getEventTarget () { - return this.node - } // Checks if the given element is a child - has ( element ) { - - return this.index( element ) >= 0 - + has (element) { + return this.index(element) >= 0 } // Get / set id - id ( id ) { - + id (id) { // generate new id if no id set - if ( typeof id === 'undefined' && !this.node.id ) { - - this.node.id = eid( this.type ) - + if (typeof id === 'undefined' && !this.node.id) { + this.node.id = eid(this.type) } // dont't set directly width this.node.id to make `null` work correctly - return this.attr( 'id', id ) - + return this.attr('id', id) } // Gets index of given element - index ( element ) { - - return [].slice.call( this.node.childNodes ).indexOf( element.node ) - + index (element) { + return [].slice.call(this.node.childNodes).indexOf(element.node) } // Get the last child last () { - - return adopt( this.node.lastChild ) - + return adopt(this.node.lastChild) } // matches the element vs a css selector - matches ( selector ) { - + matches (selector) { const el = this.node - return ( el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector ).call( el, selector ) - + return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector) } // Returns the parent element instance - parent ( type ) { - + parent (type) { var parent = this // check for parent - if ( !parent.node.parentNode ) return null + if (!parent.node.parentNode) return null // get parent element - parent = adopt( parent.node.parentNode ) + parent = adopt(parent.node.parentNode) - if ( !type ) return parent + if (!type) return parent // loop trough ancestors if type is given - while ( parent && parent.node instanceof globals.window.SVGElement ) { // FIXME: That shouldnt be neccessary - - if ( typeof type === 'string' ? parent.matches( type ) : parent instanceof type ) return parent - parent = adopt( parent.node.parentNode ) - + while (parent && parent.node instanceof globals.window.SVGElement) { // FIXME: That shouldnt be neccessary + if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent + parent = adopt(parent.node.parentNode) } - } // Basically does the same as `add()` but returns the added element instead - put ( element, i ) { - - this.add( element, i ) + put (element, i) { + this.add(element, i) return element - } // Add element to given container and return container - putIn ( parent ) { - - return makeInstance( parent ).add( this ) - + putIn (parent) { + return makeInstance(parent).add(this) } // Remove element remove () { - - if ( this.parent() ) { - - this.parent().removeElement( this ) - + if (this.parent()) { + this.parent().removeElement(this) } return this - } // Remove a given child - removeElement ( element ) { - - this.node.removeChild( element.node ) + removeElement (element) { + this.node.removeChild(element.node) return this - } // Replace this with element - replace ( element ) { - - element = makeInstance( element ) - this.node.parentNode.replaceChild( element.node, this.node ) + replace (element) { + element = makeInstance(element) + this.node.parentNode.replaceChild(element.node, this.node) return element - } - round ( precision = 2, map ) { - + round (precision = 2, map) { const factor = 10 ** precision const attrs = this.attr() // If we have no map, build one from attrs - if ( !map ) { - - map = Object.keys( attrs ) - + if (!map) { + map = Object.keys(attrs) } // Holds rounded attributes const newAttrs = {} - map.forEach( ( key ) => { - - newAttrs[key] = Math.round( attrs[key] * factor ) / factor + map.forEach((key) => { + newAttrs[key] = Math.round(attrs[key] * factor) / factor + }) - } ) - - this.attr( newAttrs ) + this.attr(newAttrs) return this - } // Return id on string conversion toString () { - return this.id() - } // Import raw svg - svg ( svgOrFn, outerHTML ) { - + svg (svgOrFn, outerHTML) { var well, len, fragment - if ( svgOrFn === false ) { - + if (svgOrFn === false) { outerHTML = false svgOrFn = null - } // act as getter if no svg string is given - if ( svgOrFn == null || typeof svgOrFn === 'function' ) { - + if (svgOrFn == null || typeof svgOrFn === 'function') { // The default for exports is, that the outerNode is included outerHTML = outerHTML == null ? true : outerHTML @@ -311,49 +234,38 @@ export default class Dom extends EventTarget { let current = this // An export modifier was passed - if ( svgOrFn != null ) { - - current = adopt( current.node.cloneNode( true ) ) + if (svgOrFn != null) { + current = adopt(current.node.cloneNode(true)) // If the user wants outerHTML we need to process this node, too - if ( outerHTML ) { - - let result = svgOrFn( current ) + if (outerHTML) { + let result = svgOrFn(current) current = result || current // The user does not want this node? Well, then he gets nothing - if ( result === false ) return '' - + if (result === false) return '' } // Deep loop through all children and apply modifier - current.each( function () { - - let result = svgOrFn( this ) + current.each(function () { + let result = svgOrFn(this) let _this = result || this // If modifier returns false, discard node - if ( result === false ) { - + if (result === false) { this.remove() // If modifier returns new node, use it - - } else if ( result && this !== _this ) { - - this.replace( _this ) - + } else if (result && this !== _this) { + this.replace(_this) } - - }, true ) - + }, true) } // Return outer or inner content return outerHTML ? current.node.outerHTML : current.node.innerHTML - } // Act as setter if we got a string @@ -362,41 +274,33 @@ export default class Dom extends EventTarget { outerHTML = outerHTML == null ? false : outerHTML // Create temporary holder - well = globals.document.createElementNS( ns, 'svg' ) + well = globals.document.createElementNS(ns, 'svg') fragment = globals.document.createDocumentFragment() // Dump raw svg well.innerHTML = svgOrFn // Transplant nodes into the fragment - for ( len = well.children.length; len--; ) { - - fragment.appendChild( well.firstElementChild ) - + for (len = well.children.length; len--;) { + fragment.appendChild(well.firstElementChild) } // Add the whole fragment at once return outerHTML - ? this.replace( fragment ) - : this.add( fragment ) - + ? this.replace(fragment) + : this.add(fragment) } // write svgjs data to the dom writeDataToDom () { - // dump variables recursively - this.each( function () { - + this.each(function () { this.writeDataToDom() - - } ) + }) return this - } - } -extend( Dom, { attr, find } ) -register( Dom ) +extend(Dom, { attr, find }) +register(Dom) diff --git a/src/elements/Element.js b/src/elements/Element.js index 169c872..594daa1 100644 --- a/src/elements/Element.js +++ b/src/elements/Element.js @@ -15,13 +15,11 @@ import Dom from './Dom.js' import List from '../types/List.js' import SVGNumber from '../types/SVGNumber.js' -const Svg = getClass( root ) +const Svg = getClass(root) export default class Element extends Dom { - - constructor ( node, attrs ) { - - super( node, attrs ) + constructor (node, attrs) { + super(node, attrs) // initialize data object this.dom = {} @@ -29,177 +27,135 @@ export default class Element extends Dom { // create circular reference this.node.instance = this - if ( node.hasAttribute( 'svgjs:data' ) ) { - + if (node.hasAttribute('svgjs:data')) { // pull svgjs data from the dom (getAttributeNS doesn't work in html5) - this.setData( JSON.parse( node.getAttribute( 'svgjs:data' ) ) || {} ) - + this.setData(JSON.parse(node.getAttribute('svgjs:data')) || {}) } - } // Move element by its center - center ( x, y ) { - - return this.cx( x ).cy( y ) - + center (x, y) { + return this.cx(x).cy(y) } // Move by center over x-axis - cx ( x ) { - - return x == null ? this.x() + this.width() / 2 : this.x( x - this.width() / 2 ) - + cx (x) { + return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2) } // Move by center over y-axis - cy ( y ) { - + cy (y) { return y == null ? this.y() + this.height() / 2 - : this.y( y - this.height() / 2 ) - + : this.y(y - this.height() / 2) } // Get defs defs () { - return this.root().defs() - } // Get parent document root () { - - let p = this.parent( Svg ) + let p = this.parent(Svg) return p && p.root() - } getEventHolder () { - return this - } // Set height of element - height ( height ) { - - return this.attr( 'height', height ) - + height (height) { + return this.attr('height', height) } // Checks whether the given point inside the bounding box of the element - inside ( x, y ) { - + inside (x, y) { let box = this.bbox() return x > box.x && y > box.y && x < box.x + box.width && y < box.y + box.height - } // Move element to given x and y values - move ( x, y ) { - - return this.x( x ).y( y ) - + move (x, y) { + return this.x(x).y(y) } // return array of all ancestors of given type up to the root svg - parents ( until = globals.document ) { - - until = makeInstance( until ) + parents (until = globals.document) { + until = makeInstance(until) let parents = new List() let parent = this while ( - ( parent = parent.parent() ) + (parent = parent.parent()) && parent.node !== until.node && parent.node !== globals.document ) { - - parents.push( parent ) - + parents.push(parent) } return parents - } // Get referenced element form attribute value - reference ( attr ) { - - attr = this.attr( attr ) - if ( !attr ) return null - - const m = attr.match( reference ) - return m ? makeInstance( m[1] ) : null + reference (attr) { + attr = this.attr(attr) + if (!attr) return null + const m = attr.match(reference) + return m ? makeInstance(m[1]) : null } // set given data to the elements data property - setData ( o ) { - + setData (o) { this.dom = o return this - } // Set element size to given width and height - size ( width, height ) { - - let p = proportionalSize( this, width, height ) + size (width, height) { + let p = proportionalSize(this, width, height) return this - .width( new SVGNumber( p.width ) ) - .height( new SVGNumber( p.height ) ) - + .width(new SVGNumber(p.width)) + .height(new SVGNumber(p.height)) } // Set width of element - width ( width ) { - - return this.attr( 'width', width ) - + width (width) { + return this.attr('width', width) } // write svgjs data to the dom writeDataToDom () { - // remove previously set data - this.node.removeAttribute( 'svgjs:data' ) - - if ( Object.keys( this.dom ).length ) { - - this.node.setAttribute( 'svgjs:data', JSON.stringify( this.dom ) ) // see #428 + this.node.removeAttribute('svgjs:data') + if (Object.keys(this.dom).length) { + this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)) // see #428 } return super.writeDataToDom() - } // Move over x-axis - x ( x ) { - - return this.attr( 'x', x ) - + x (x) { + return this.attr('x', x) } // Move over y-axis - y ( y ) { - - return this.attr( 'y', y ) - + y (y) { + return this.attr('y', y) } - } -extend( Element, { +extend(Element, { bbox, rbox, point, ctm, screenCTM -} ) +}) -register( Element ) +register(Element) diff --git a/src/elements/Ellipse.js b/src/elements/Ellipse.js index e1e1fe0..0350f1f 100644 --- a/src/elements/Ellipse.js +++ b/src/elements/Ellipse.js @@ -11,34 +11,26 @@ import Shape from './Shape.js' import * as circled from '../modules/core/circled.js' export default class Ellipse extends Shape { - - constructor ( node ) { - - super( nodeOrNew( 'ellipse', node ), node ) - + constructor (node) { + super(nodeOrNew('ellipse', node), node) } - size ( width, height ) { - - var p = proportionalSize( this, width, height ) + size (width, height) { + var p = proportionalSize(this, width, height) return this - .rx( new SVGNumber( p.width ).divide( 2 ) ) - .ry( new SVGNumber( p.height ).divide( 2 ) ) - + .rx(new SVGNumber(p.width).divide(2)) + .ry(new SVGNumber(p.height).divide(2)) } - } -extend( Ellipse, circled ) +extend(Ellipse, circled) -registerMethods( 'Container', { +registerMethods('Container', { // Create an ellipse - ellipse: wrapWithAttrCheck( function ( width, height ) { - - return this.put( new Ellipse() ).size( width, height ).move( 0, 0 ) - - } ) -} ) + ellipse: wrapWithAttrCheck(function (width, height) { + return this.put(new Ellipse()).size(width, height).move(0, 0) + }) +}) -register( Ellipse ) +register(Ellipse) diff --git a/src/elements/G.js b/src/elements/G.js index a72f1fb..6a93a3f 100644 --- a/src/elements/G.js +++ b/src/elements/G.js @@ -3,24 +3,18 @@ import { registerMethods } from '../utils/methods.js' import Container from './Container.js' export default class G extends Container { - - constructor ( node ) { - - super( nodeOrNew( 'g', node ), node ) - + constructor (node) { + super(nodeOrNew('g', node), node) } - } -registerMethods( { +registerMethods({ Element: { // Create a group element - group: wrapWithAttrCheck( function () { - - return this.put( new G() ) - - } ) + group: wrapWithAttrCheck(function () { + return this.put(new G()) + }) } -} ) +}) -register( G ) +register(G) diff --git a/src/elements/Gradient.js b/src/elements/Gradient.js index 7116fc8..23de97d 100644 --- a/src/elements/Gradient.js +++ b/src/elements/Gradient.js @@ -12,95 +12,71 @@ import baseFind from '../modules/core/selector.js' import * as gradiented from '../modules/core/gradiented.js' export default class Gradient extends Container { - - constructor ( type, attrs ) { - + constructor (type, attrs) { super( - nodeOrNew( type + 'Gradient', typeof type === 'string' ? null : type ), + nodeOrNew(type + 'Gradient', typeof type === 'string' ? null : type), attrs ) - } // Add a color stop - stop ( offset, color, opacity ) { - - return this.put( new Stop() ).update( offset, color, opacity ) - + stop (offset, color, opacity) { + return this.put(new Stop()).update(offset, color, opacity) } // Update gradient - update ( block ) { - + update (block) { // remove all stops this.clear() // invoke passed block - if ( typeof block === 'function' ) { - - block.call( this, this ) - + if (typeof block === 'function') { + block.call(this, this) } return this - } // Return the fill id url () { - return 'url(#' + this.id() + ')' - } // Alias string convertion to fill toString () { - return this.url() - } // custom attr to handle transform - attr ( a, b, c ) { - - if ( a === 'transform' ) a = 'gradientTransform' - return super.attr( a, b, c ) - + attr (a, b, c) { + if (a === 'transform') a = 'gradientTransform' + return super.attr(a, b, c) } targets () { - - return baseFind( 'svg [fill*="' + this.id() + '"]' ) - + return baseFind('svg [fill*="' + this.id() + '"]') } bbox () { - return new Box() - } - } -extend( Gradient, gradiented ) +extend(Gradient, gradiented) -registerMethods( { +registerMethods({ Container: { // Create gradient element in defs - gradient: wrapWithAttrCheck( function ( type, block ) { - - return this.defs().gradient( type, block ) - - } ) + gradient: wrapWithAttrCheck(function (type, block) { + return this.defs().gradient(type, block) + }) }, // define gradient Defs: { - gradient: wrapWithAttrCheck( function ( type, block ) { - - return this.put( new Gradient( type ) ).update( block ) - - } ) + gradient: wrapWithAttrCheck(function (type, block) { + return this.put(new Gradient(type)).update(block) + }) } -} ) +}) -register( Gradient ) +register(Gradient) diff --git a/src/elements/HtmlNode.js b/src/elements/HtmlNode.js index d2299ed..009b122 100644 --- a/src/elements/HtmlNode.js +++ b/src/elements/HtmlNode.js @@ -3,4 +3,4 @@ import Dom from './Dom.js' export default class HtmlNode extends Dom {} -register( HtmlNode ) +register(HtmlNode) diff --git a/src/elements/Image.js b/src/elements/Image.js index 4945271..8f27470 100644 --- a/src/elements/Image.js +++ b/src/elements/Image.js @@ -9,99 +9,69 @@ import Shape from './Shape.js' import { globals } from '../utils/window.js' export default class Image extends Shape { - - constructor ( node ) { - - super( nodeOrNew( 'image', node ), node ) - + constructor (node) { + super(nodeOrNew('image', node), node) } // (re)load image - load ( url, callback ) { - - if ( !url ) return this + load (url, callback) { + if (!url) return this var img = new globals.window.Image() - on( img, 'load', function ( e ) { - - var p = this.parent( Pattern ) + on(img, 'load', function (e) { + var p = this.parent(Pattern) // ensure image size - if ( this.width() === 0 && this.height() === 0 ) { - - this.size( img.width, img.height ) - + if (this.width() === 0 && this.height() === 0) { + this.size(img.width, img.height) } - if ( p instanceof Pattern ) { - + if (p instanceof Pattern) { // ensure pattern size if not set - if ( p.width() === 0 && p.height() === 0 ) { - - p.size( this.width(), this.height() ) - + if (p.width() === 0 && p.height() === 0) { + p.size(this.width(), this.height()) } - } - if ( typeof callback === 'function' ) { - - callback.call( this, e ) - + if (typeof callback === 'function') { + callback.call(this, e) } + }, this) - }, this ) - - on( img, 'load error', function () { - + on(img, 'load error', function () { // dont forget to unbind memory leaking events - off( img ) - - } ) - - return this.attr( 'href', ( img.src = url ), xlink ) + off(img) + }) + return this.attr('href', (img.src = url), xlink) } - } -registerAttrHook( function ( attr, val, _this ) { - +registerAttrHook(function (attr, val, _this) { // convert image fill and stroke to patterns - if ( attr === 'fill' || attr === 'stroke' ) { - - if ( isImage.test( val ) ) { - - val = _this.root().defs().image( val ) - + if (attr === 'fill' || attr === 'stroke') { + if (isImage.test(val)) { + val = _this.root().defs().image(val) } - } - if ( val instanceof Image ) { - - val = _this.root().defs().pattern( 0, 0, ( pattern ) => { - - pattern.add( val ) - - } ) - + if (val instanceof Image) { + val = _this.root().defs().pattern(0, 0, (pattern) => { + pattern.add(val) + }) } return val +}) -} ) - -registerMethods( { +registerMethods({ Container: { // create image element, load image and set its size - image: wrapWithAttrCheck( function ( source, callback ) { - - return this.put( new Image() ).size( 0, 0 ).load( source, callback ) - - } ) + image: wrapWithAttrCheck(function (source, callback) { + return this.put(new Image()).size(0, 0).load(source, callback) + }) } -} ) +}) -register( Image ) +register(Image) diff --git a/src/elements/Line.js b/src/elements/Line.js index 123f2bb..edf10e7 100644 --- a/src/elements/Line.js +++ b/src/elements/Line.js @@ -11,78 +11,58 @@ import Shape from './Shape.js' import * as pointed from '../modules/core/pointed.js' export default class Line extends Shape { - // Initialize node - constructor ( node ) { - - super( nodeOrNew( 'line', node ), node ) - + constructor (node) { + super(nodeOrNew('line', node), node) } // Get array array () { - - return new PointArray( [ - [ this.attr( 'x1' ), this.attr( 'y1' ) ], - [ this.attr( 'x2' ), this.attr( 'y2' ) ] - ] ) - + return new PointArray([ + [ this.attr('x1'), this.attr('y1') ], + [ this.attr('x2'), this.attr('y2') ] + ]) } // Overwrite native plot() method - plot ( x1, y1, x2, y2 ) { - - if ( x1 == null ) { - + plot (x1, y1, x2, y2) { + if (x1 == null) { return this.array() - - } else if ( typeof y1 !== 'undefined' ) { - + } else if (typeof y1 !== 'undefined') { x1 = { x1: x1, y1: y1, x2: x2, y2: y2 } - } else { - - x1 = new PointArray( x1 ).toLine() - + x1 = new PointArray(x1).toLine() } - return this.attr( x1 ) - + return this.attr(x1) } // Move by left top corner - move ( x, y ) { - - return this.attr( this.array().move( x, y ).toLine() ) - + move (x, y) { + return this.attr(this.array().move(x, y).toLine()) } // Set element size to given width and height - size ( width, height ) { - - var p = proportionalSize( this, width, height ) - return this.attr( this.array().size( p.width, p.height ).toLine() ) - + size (width, height) { + var p = proportionalSize(this, width, height) + return this.attr(this.array().size(p.width, p.height).toLine()) } - } -extend( Line, pointed ) +extend(Line, pointed) -registerMethods( { +registerMethods({ Container: { // Create a line element - line: wrapWithAttrCheck( function ( ...args ) { - + line: wrapWithAttrCheck(function (...args) { // make sure plot is called as a setter // x1 is not necessarily a number, it can also be an array, a string and a PointArray return Line.prototype.plot.apply( - this.put( new Line() ) + this.put(new Line()) , args[0] != null ? args : [ 0, 0, 0, 0 ] ) - - } ) + }) } -} ) +}) -register( Line ) +register(Line) diff --git a/src/elements/Marker.js b/src/elements/Marker.js index 1054987..238f559 100644 --- a/src/elements/Marker.js +++ b/src/elements/Marker.js @@ -3,103 +3,81 @@ import { registerMethods } from '../utils/methods.js' import Container from './Container.js' export default class Marker extends Container { - // Initialize node - constructor ( node ) { - - super( nodeOrNew( 'marker', node ), node ) - + constructor (node) { + super(nodeOrNew('marker', node), node) } // Set width of element - width ( width ) { - - return this.attr( 'markerWidth', width ) - + width (width) { + return this.attr('markerWidth', width) } // Set height of element - height ( height ) { - - return this.attr( 'markerHeight', height ) - + height (height) { + return this.attr('markerHeight', height) } // Set marker refX and refY - ref ( x, y ) { - - return this.attr( 'refX', x ).attr( 'refY', y ) - + ref (x, y) { + return this.attr('refX', x).attr('refY', y) } // Update marker - update ( block ) { - + update (block) { // remove all content this.clear() // invoke passed block - if ( typeof block === 'function' ) { - - block.call( this, this ) - + if (typeof block === 'function') { + block.call(this, this) } return this - } // Return the fill id toString () { - return 'url(#' + this.id() + ')' - } - } -registerMethods( { +registerMethods({ Container: { - marker ( ...args ) { - + marker (...args) { // Create marker element in defs - return this.defs().marker( ...args ) - + return this.defs().marker(...args) } }, Defs: { // Create marker - marker: wrapWithAttrCheck( function ( width, height, block ) { - + marker: wrapWithAttrCheck(function (width, height, block) { // Set default viewbox to match the width and height, set ref to cx and cy and set orient to auto - return this.put( new Marker() ) - .size( width, height ) - .ref( width / 2, height / 2 ) - .viewbox( 0, 0, width, height ) - .attr( 'orient', 'auto' ) - .update( block ) - - } ) + return this.put(new Marker()) + .size(width, height) + .ref(width / 2, height / 2) + .viewbox(0, 0, width, height) + .attr('orient', 'auto') + .update(block) + }) }, marker: { // Create and attach markers - marker ( marker, width, height, block ) { - + marker (marker, width, height, block) { var attr = [ 'marker' ] // Build attribute name - if ( marker !== 'all' ) attr.push( marker ) - attr = attr.join( '-' ) + if (marker !== 'all') attr.push(marker) + attr = attr.join('-') // Set marker attribute marker = arguments[1] instanceof Marker ? arguments[1] - : this.defs().marker( width, height, block ) - - return this.attr( attr, marker ) + : this.defs().marker(width, height, block) + return this.attr(attr, marker) } } -} ) +}) -register( Marker ) +register(Marker) diff --git a/src/elements/Mask.js b/src/elements/Mask.js index 523b9de..8dfffd6 100644 --- a/src/elements/Mask.js +++ b/src/elements/Mask.js @@ -4,72 +4,54 @@ import Container from './Container.js' import baseFind from '../modules/core/selector.js' export default class Mask extends Container { - // Initialize node - constructor ( node ) { - - super( nodeOrNew( 'mask', node ), node ) - + constructor (node) { + super(nodeOrNew('mask', node), node) } // Unmask all masked elements and remove itself remove () { - // unmask all targets - this.targets().forEach( function ( el ) { - + this.targets().forEach(function (el) { el.unmask() - - } ) + }) // remove mask from parent return super.remove() - } targets () { - - return baseFind( 'svg [mask*="' + this.id() + '"]' ) - + return baseFind('svg [mask*="' + this.id() + '"]') } - } -registerMethods( { +registerMethods({ Container: { - mask: wrapWithAttrCheck( function () { - - return this.defs().put( new Mask() ) - - } ) + mask: wrapWithAttrCheck(function () { + return this.defs().put(new Mask()) + }) }, Element: { // Distribute mask to svg element - maskWith ( element ) { - + maskWith (element) { // use given mask or create a new one var masker = element instanceof Mask ? element - : this.parent().mask().add( element ) + : this.parent().mask().add(element) // apply mask - return this.attr( 'mask', 'url("#' + masker.id() + '")' ) - + return this.attr('mask', 'url("#' + masker.id() + '")') }, // Unmask element unmask () { - - return this.attr( 'mask', null ) - + return this.attr('mask', null) }, masker () { - - return this.reference( 'mask' ) - + return this.reference('mask') } } -} ) +}) -register( Mask ) +register(Mask) diff --git a/src/elements/Path.js b/src/elements/Path.js index 1fe5661..dc27320 100644 --- a/src/elements/Path.js +++ b/src/elements/Path.js @@ -6,102 +6,76 @@ import Shape from './Shape.js' import baseFind from '../modules/core/selector.js' export default class Path extends Shape { - // Initialize node - constructor ( node ) { - - super( nodeOrNew( 'path', node ), node ) - + constructor (node) { + super(nodeOrNew('path', node), node) } // Get array array () { - - return this._array || ( this._array = new PathArray( this.attr( 'd' ) ) ) - + return this._array || (this._array = new PathArray(this.attr('d'))) } // Plot new path - plot ( d ) { - - return ( d == null ) ? this.array() - : this.clear().attr( 'd', typeof d === 'string' ? d : ( this._array = new PathArray( d ) ) ) - + plot (d) { + return (d == null) ? this.array() + : this.clear().attr('d', typeof d === 'string' ? d : (this._array = new PathArray(d))) } // Clear array cache clear () { - delete this._array return this - } // Move by left top corner - move ( x, y ) { - - return this.attr( 'd', this.array().move( x, y ) ) - + move (x, y) { + return this.attr('d', this.array().move(x, y)) } // Move by left top corner over x-axis - x ( x ) { - - return x == null ? this.bbox().x : this.move( x, this.bbox().y ) - + x (x) { + return x == null ? this.bbox().x : this.move(x, this.bbox().y) } // Move by left top corner over y-axis - y ( y ) { - - return y == null ? this.bbox().y : this.move( this.bbox().x, y ) - + y (y) { + return y == null ? this.bbox().y : this.move(this.bbox().x, y) } // Set element size to given width and height - size ( width, height ) { - - var p = proportionalSize( this, width, height ) - return this.attr( 'd', this.array().size( p.width, p.height ) ) - + size (width, height) { + var p = proportionalSize(this, width, height) + return this.attr('d', this.array().size(p.width, p.height)) } // Set width of element - width ( width ) { - - return width == null ? this.bbox().width : this.size( width, this.bbox().height ) - + width (width) { + return width == null ? this.bbox().width : this.size(width, this.bbox().height) } // Set height of element - height ( height ) { - - return height == null ? this.bbox().height : this.size( this.bbox().width, height ) - + height (height) { + return height == null ? this.bbox().height : this.size(this.bbox().width, height) } targets () { - - return baseFind( 'svg textpath [href*="' + this.id() + '"]' ) - + return baseFind('svg textpath [href*="' + this.id() + '"]') } - } // Define morphable array Path.prototype.MorphArray = PathArray // Add parent method -registerMethods( { +registerMethods({ Container: { // Create a wrapped path element - path: wrapWithAttrCheck( function ( d ) { - + path: wrapWithAttrCheck(function (d) { // make sure plot is called as a setter - return this.put( new Path() ).plot( d || new PathArray() ) - - } ) + return this.put(new Path()).plot(d || new PathArray()) + }) } -} ) +}) -register( Path ) +register(Path) diff --git a/src/elements/Pattern.js b/src/elements/Pattern.js index 6f7897b..6dd4e01 100644 --- a/src/elements/Pattern.js +++ b/src/elements/Pattern.js @@ -5,89 +5,67 @@ import Container from './Container.js' import baseFind from '../modules/core/selector.js' export default class Pattern extends Container { - // Initialize node - constructor ( node ) { - - super( nodeOrNew( 'pattern', node ), node ) - + constructor (node) { + super(nodeOrNew('pattern', node), node) } // Return the fill id url () { - return 'url(#' + this.id() + ')' - } // Update pattern by rebuilding - update ( block ) { - + update (block) { // remove content this.clear() // invoke passed block - if ( typeof block === 'function' ) { - - block.call( this, this ) - + if (typeof block === 'function') { + block.call(this, this) } return this - } // Alias string convertion to fill toString () { - return this.url() - } // custom attr to handle transform - attr ( a, b, c ) { - - if ( a === 'transform' ) a = 'patternTransform' - return super.attr( a, b, c ) - + attr (a, b, c) { + if (a === 'transform') a = 'patternTransform' + return super.attr(a, b, c) } targets () { - - return baseFind( 'svg [fill*="' + this.id() + '"]' ) - + return baseFind('svg [fill*="' + this.id() + '"]') } bbox () { - return new Box() - } - } -registerMethods( { +registerMethods({ Container: { // Create pattern element in defs - pattern ( ...args ) { - - return this.defs().pattern( ...args ) - + pattern (...args) { + return this.defs().pattern(...args) } }, Defs: { - pattern: wrapWithAttrCheck( function ( width, height, block ) { - - return this.put( new Pattern() ).update( block ).attr( { + pattern: wrapWithAttrCheck(function (width, height, block) { + return this.put(new Pattern()).update(block).attr({ x: 0, y: 0, width: width, height: height, patternUnits: 'userSpaceOnUse' - } ) - - } ) + }) + }) } -} ) +}) -register( Pattern ) +register(Pattern) diff --git a/src/elements/Polygon.js b/src/elements/Polygon.js index 2288b75..afa5f31 100644 --- a/src/elements/Polygon.js +++ b/src/elements/Polygon.js @@ -11,28 +11,22 @@ import * as pointed from '../modules/core/pointed.js' import * as poly from '../modules/core/poly.js' export default class Polygon extends Shape { - // Initialize node - constructor ( node ) { - - super( nodeOrNew( 'polygon', node ), node ) - + constructor (node) { + super(nodeOrNew('polygon', node), node) } - } -registerMethods( { +registerMethods({ Container: { // Create a wrapped polygon element - polygon: wrapWithAttrCheck( function ( p ) { - + polygon: wrapWithAttrCheck(function (p) { // make sure plot is called as a setter - return this.put( new Polygon() ).plot( p || new PointArray() ) - - } ) + return this.put(new Polygon()).plot(p || new PointArray()) + }) } -} ) +}) -extend( Polygon, pointed ) -extend( Polygon, poly ) -register( Polygon ) +extend(Polygon, pointed) +extend(Polygon, poly) +register(Polygon) diff --git a/src/elements/Polyline.js b/src/elements/Polyline.js index 3749c93..5897295 100644 --- a/src/elements/Polyline.js +++ b/src/elements/Polyline.js @@ -11,28 +11,22 @@ import * as pointed from '../modules/core/pointed.js' import * as poly from '../modules/core/poly.js' export default class Polyline extends Shape { - // Initialize node - constructor ( node ) { - - super( nodeOrNew( 'polyline', node ), node ) - + constructor (node) { + super(nodeOrNew('polyline', node), node) } - } -registerMethods( { +registerMethods({ Container: { // Create a wrapped polygon element - polyline: wrapWithAttrCheck( function ( p ) { - + polyline: wrapWithAttrCheck(function (p) { // make sure plot is called as a setter - return this.put( new Polyline() ).plot( p || new PointArray() ) - - } ) + return this.put(new Polyline()).plot(p || new PointArray()) + }) } -} ) +}) -extend( Polyline, pointed ) -extend( Polyline, poly ) -register( Polyline ) +extend(Polyline, pointed) +extend(Polyline, poly) +register(Polyline) diff --git a/src/elements/Rect.js b/src/elements/Rect.js index 465b52b..6e161c9 100644 --- a/src/elements/Rect.js +++ b/src/elements/Rect.js @@ -9,27 +9,21 @@ import { rx, ry } from '../modules/core/circled.js' import Shape from './Shape.js' export default class Rect extends Shape { - // Initialize node - constructor ( node ) { - - super( nodeOrNew( 'rect', node ), node ) - + constructor (node) { + super(nodeOrNew('rect', node), node) } - } -extend( Rect, { rx, ry } ) +extend(Rect, { rx, ry }) -registerMethods( { +registerMethods({ Container: { // Create a rect element - rect: wrapWithAttrCheck( function ( width, height ) { - - return this.put( new Rect() ).size( width, height ) - - } ) + rect: wrapWithAttrCheck(function (width, height) { + return this.put(new Rect()).size(width, height) + }) } -} ) +}) -register( Rect ) +register(Rect) diff --git a/src/elements/Shape.js b/src/elements/Shape.js index 0d5a5b0..cdddc60 100644 --- a/src/elements/Shape.js +++ b/src/elements/Shape.js @@ -3,4 +3,4 @@ import Element from './Element.js' export default class Shape extends Element {} -register( Shape ) +register(Shape) diff --git a/src/elements/Stop.js b/src/elements/Stop.js index 8838923..9a5acaa 100644 --- a/src/elements/Stop.js +++ b/src/elements/Stop.js @@ -3,35 +3,27 @@ import Element from './Element.js' import SVGNumber from '../types/SVGNumber.js' export default class Stop extends Element { - - constructor ( node ) { - - super( nodeOrNew( 'stop', node ), node ) - + constructor (node) { + super(nodeOrNew('stop', node), node) } // add color stops - update ( o ) { - - if ( typeof o === 'number' || o instanceof SVGNumber ) { - + update (o) { + if (typeof o === 'number' || o instanceof SVGNumber) { o = { offset: arguments[0], color: arguments[1], opacity: arguments[2] } - } // set attributes - if ( o.opacity != null ) this.attr( 'stop-opacity', o.opacity ) - if ( o.color != null ) this.attr( 'stop-color', o.color ) - if ( o.offset != null ) this.attr( 'offset', new SVGNumber( o.offset ) ) + if (o.opacity != null) this.attr('stop-opacity', o.opacity) + if (o.color != null) this.attr('stop-color', o.color) + if (o.offset != null) this.attr('offset', new SVGNumber(o.offset)) return this - } - } -register( Stop ) +register(Stop) diff --git a/src/elements/Style.js b/src/elements/Style.js index 643f356..50ec50e 100644 --- a/src/elements/Style.js +++ b/src/elements/Style.js @@ -3,69 +3,51 @@ import { registerMethods } from '../utils/methods.js' import { unCamelCase } from '../utils/utils.js' import Element from './Element.js' -function cssRule ( selector, rule ) { - - if ( !selector ) return '' - if ( !rule ) return selector +function cssRule (selector, rule) { + if (!selector) return '' + if (!rule) return selector var ret = selector + '{' - for ( var i in rule ) { - - ret += unCamelCase( i ) + ':' + rule[i] + ';' - + for (var i in rule) { + ret += unCamelCase(i) + ':' + rule[i] + ';' } ret += '}' return ret - } export default class Style extends Element { - - constructor ( node ) { - - super( nodeOrNew( 'style', node ), node ) - + constructor (node) { + super(nodeOrNew('style', node), node) } - words ( w ) { - - this.node.textContent += ( w || '' ) + words (w) { + this.node.textContent += (w || '') return this - } - font ( name, src, params = {} ) { - - return this.rule( '@font-face', { + font (name, src, params = {}) { + return this.rule('@font-face', { fontFamily: name, src: src, ...params - } ) - + }) } - rule ( selector, obj ) { - - return this.words( cssRule( selector, obj ) ) - + rule (selector, obj) { + return this.words(cssRule(selector, obj)) } - } -registerMethods( 'Dom', { - style: wrapWithAttrCheck( function ( selector, obj ) { - - return this.put( new Style() ).rule( selector, obj ) - - } ), - fontface: wrapWithAttrCheck( function ( name, src, params ) { - - return this.put( new Style() ).font( name, src, params ) - - } ) -} ) +registerMethods('Dom', { + style: wrapWithAttrCheck(function (selector, obj) { + return this.put(new Style()).rule(selector, obj) + }), + fontface: wrapWithAttrCheck(function (name, src, params) { + return this.put(new Style()).font(name, src, params) + }) +}) -register( Style ) +register(Style) diff --git a/src/elements/Svg.js b/src/elements/Svg.js index 1326900..ab7d89f 100644 --- a/src/elements/Svg.js +++ b/src/elements/Svg.js @@ -11,90 +11,68 @@ import Defs from './Defs.js' import { globals } from '../utils/window.js' export default class Svg extends Container { - - constructor ( node ) { - - super( nodeOrNew( 'svg', node ), node ) + constructor (node) { + super(nodeOrNew('svg', node), node) this.namespace() - } isRoot () { - return !this.node.parentNode - || !( this.node.parentNode instanceof globals.window.SVGElement ) + || !(this.node.parentNode instanceof globals.window.SVGElement) || this.node.parentNode.nodeName === '#document' - } // Check if this is a root svg // If not, call docs from this element root () { - - if ( this.isRoot() ) return this + if (this.isRoot()) return this return super.root() - } // Add namespaces namespace () { - - if ( !this.isRoot() ) return this.root().namespace() + if (!this.isRoot()) return this.root().namespace() return this - .attr( { xmlns: ns, version: '1.1' } ) - .attr( 'xmlns:xlink', xlink, xmlns ) - .attr( 'xmlns:svgjs', svgjs, xmlns ) - + .attr({ xmlns: ns, version: '1.1' }) + .attr('xmlns:xlink', xlink, xmlns) + .attr('xmlns:svgjs', svgjs, xmlns) } // Creates and returns defs element defs () { + if (!this.isRoot()) return this.root().defs() - if ( !this.isRoot() ) return this.root().defs() - - return adopt( this.node.getElementsByTagName( 'defs' )[0] ) - || this.put( new Defs() ) - + return adopt(this.node.getElementsByTagName('defs')[0]) + || this.put(new Defs()) } // custom parent method - parent ( type ) { - - if ( this.isRoot() ) { - + parent (type) { + if (this.isRoot()) { return this.node.parentNode.nodeName === '#document' ? null - : adopt( this.node.parentNode ) - + : adopt(this.node.parentNode) } - return super.parent( type ) - + return super.parent(type) } clear () { - // remove children - while ( this.node.hasChildNodes() ) { - - this.node.removeChild( this.node.lastChild ) - + while (this.node.hasChildNodes()) { + this.node.removeChild(this.node.lastChild) } return this - } - } -registerMethods( { +registerMethods({ Container: { // Create nested svg document - nested: wrapWithAttrCheck( function () { - - return this.put( new Svg() ) - - } ) + nested: wrapWithAttrCheck(function () { + return this.put(new Svg()) + }) } -} ) +}) -register( Svg, 'Svg', true ) +register(Svg, 'Svg', true) diff --git a/src/elements/Symbol.js b/src/elements/Symbol.js index 577d1f1..f44125c 100644 --- a/src/elements/Symbol.js +++ b/src/elements/Symbol.js @@ -3,24 +3,18 @@ import { registerMethods } from '../utils/methods.js' import Container from './Container.js' export default class Symbol extends Container { - // Initialize node - constructor ( node ) { - - super( nodeOrNew( 'symbol', node ), node ) - + constructor (node) { + super(nodeOrNew('symbol', node), node) } - } -registerMethods( { +registerMethods({ Container: { - symbol: wrapWithAttrCheck( function () { - - return this.put( new Symbol() ) - - } ) + symbol: wrapWithAttrCheck(function () { + return this.put(new Symbol()) + }) } -} ) +}) -register( Symbol ) +register(Symbol) diff --git a/src/elements/Text.js b/src/elements/Text.js index a981d73..db9c2ee 100644 --- a/src/elements/Text.js +++ b/src/elements/Text.js @@ -13,233 +13,175 @@ import { globals } from '../utils/window.js' import * as textable from '../modules/core/textable.js' export default class Text extends Shape { - // Initialize node - constructor ( node ) { - - super( nodeOrNew( 'text', node ), node ) + constructor (node) { + super(nodeOrNew('text', node), node) - this.dom.leading = new SVGNumber( 1.3 ) // store leading value for rebuilding + this.dom.leading = new SVGNumber(1.3) // store leading value for rebuilding this._rebuild = true // enable automatic updating of dy values this._build = false // disable build mode for adding multiple lines // set default font - this.attr( 'font-family', attrs['font-family'] ) - + this.attr('font-family', attrs['font-family']) } // Move over x-axis - x ( x ) { - + x (x) { // act as getter - if ( x == null ) { - - return this.attr( 'x' ) - + if (x == null) { + return this.attr('x') } - return this.attr( 'x', x ) - + return this.attr('x', x) } // Move over y-axis - y ( y ) { - - var oy = this.attr( 'y' ) + y (y) { + var oy = this.attr('y') var o = typeof oy === 'number' ? oy - this.bbox().y : 0 // act as getter - if ( y == null ) { - + if (y == null) { return typeof oy === 'number' ? oy - o : oy - } - return this.attr( 'y', typeof y === 'number' ? y + o : y ) - + return this.attr('y', typeof y === 'number' ? y + o : y) } // Move center over x-axis - cx ( x ) { - - return x == null ? this.bbox().cx : this.x( x - this.bbox().width / 2 ) - + cx (x) { + return x == null ? this.bbox().cx : this.x(x - this.bbox().width / 2) } // Move center over y-axis - cy ( y ) { - - return y == null ? this.bbox().cy : this.y( y - this.bbox().height / 2 ) - + cy (y) { + return y == null ? this.bbox().cy : this.y(y - this.bbox().height / 2) } // Set the text content - text ( text ) { - + text (text) { // act as getter - if ( text === undefined ) { - + if (text === undefined) { var children = this.node.childNodes var firstLine = 0 text = '' - for ( var i = 0, len = children.length; i < len; ++i ) { - + for (var i = 0, len = children.length; i < len; ++i) { // skip textPaths - they are no lines - if ( children[i].nodeName === 'textPath' ) { - - if ( i === 0 ) firstLine = 1 + if (children[i].nodeName === 'textPath') { + if (i === 0) firstLine = 1 continue - } // add newline if its not the first child and newLined is set to true - if ( i !== firstLine && children[i].nodeType !== 3 && adopt( children[i] ).dom.newLined === true ) { - + if (i !== firstLine && children[i].nodeType !== 3 && adopt(children[i]).dom.newLined === true) { text += '\n' - } // add content of this node text += children[i].textContent - } return text - } // remove existing content - this.clear().build( true ) - - if ( typeof text === 'function' ) { + this.clear().build(true) + if (typeof text === 'function') { // call block - text.call( this, this ) - + text.call(this, this) } else { - // store text and make sure text is not blank - text = text.split( '\n' ) + text = text.split('\n') // build new lines - for ( var j = 0, jl = text.length; j < jl; j++ ) { - - this.tspan( text[j] ).newLine() - + for (var j = 0, jl = text.length; j < jl; j++) { + this.tspan(text[j]).newLine() } - } // disable build mode and rebuild lines - return this.build( false ).rebuild() - + return this.build(false).rebuild() } // Set / get leading - leading ( value ) { - + leading (value) { // act as getter - if ( value == null ) { - + if (value == null) { return this.dom.leading - } // act as setter - this.dom.leading = new SVGNumber( value ) + this.dom.leading = new SVGNumber(value) return this.rebuild() - } // Rebuild appearance type - rebuild ( rebuild ) { - + rebuild (rebuild) { // store new rebuild flag if given - if ( typeof rebuild === 'boolean' ) { - + if (typeof rebuild === 'boolean') { this._rebuild = rebuild - } // define position of all lines - if ( this._rebuild ) { - + if (this._rebuild) { var self = this var blankLineOffset = 0 var leading = this.dom.leading - this.each( function () { - - var fontSize = globals.window.getComputedStyle( this.node ) - .getPropertyValue( 'font-size' ) - var dy = leading * new SVGNumber( fontSize ) - - if ( this.dom.newLined ) { + this.each(function () { + var fontSize = globals.window.getComputedStyle(this.node) + .getPropertyValue('font-size') + var dy = leading * new SVGNumber(fontSize) - this.attr( 'x', self.attr( 'x' ) ) - - if ( this.text() === '\n' ) { + if (this.dom.newLined) { + this.attr('x', self.attr('x')) + if (this.text() === '\n') { blankLineOffset += dy - } else { - - this.attr( 'dy', dy + blankLineOffset ) + this.attr('dy', dy + blankLineOffset) blankLineOffset = 0 - } - } + }) - } ) - - this.fire( 'rebuild' ) - + this.fire('rebuild') } return this - } // Enable / disable build mode - build ( build ) { - + build (build) { this._build = !!build return this - } // overwrite method from parent to set data properly - setData ( o ) { - + setData (o) { this.dom = o - this.dom.leading = new SVGNumber( o.leading || 1.3 ) + this.dom.leading = new SVGNumber(o.leading || 1.3) return this - } - } -extend( Text, textable ) +extend(Text, textable) -registerMethods( { +registerMethods({ Container: { // Create text element - text: wrapWithAttrCheck( function ( text ) { - - return this.put( new Text() ).text( text ) - - } ), + text: wrapWithAttrCheck(function (text) { + return this.put(new Text()).text(text) + }), // Create plain text element - plain: wrapWithAttrCheck( function ( text ) { - - return this.put( new Text() ).plain( text ) - - } ) + plain: wrapWithAttrCheck(function (text) { + return this.put(new Text()).plain(text) + }) } -} ) +}) -register( Text ) +register(Text) diff --git a/src/elements/TextPath.js b/src/elements/TextPath.js index af89ef7..91c48ae 100644 --- a/src/elements/TextPath.js +++ b/src/elements/TextPath.js @@ -7,106 +7,80 @@ import Text from './Text.js' import baseFind from '../modules/core/selector.js' export default class TextPath extends Text { - // Initialize node - constructor ( node ) { - - super( nodeOrNew( 'textPath', node ), node ) - + constructor (node) { + super(nodeOrNew('textPath', node), node) } // return the array of the path track element array () { - var track = this.track() return track ? track.array() : null - } // Plot path if any - plot ( d ) { - + plot (d) { var track = this.track() var pathArray = null - if ( track ) { - - pathArray = track.plot( d ) - + if (track) { + pathArray = track.plot(d) } - return ( d == null ) ? pathArray : this - + return (d == null) ? pathArray : this } // Get the path element track () { - - return this.reference( 'href' ) - + return this.reference('href') } - } -registerMethods( { +registerMethods({ Container: { - textPath: wrapWithAttrCheck( function ( text, path ) { - - return this.defs().path( path ).text( text ).addTo( this ) - - } ) + textPath: wrapWithAttrCheck(function (text, path) { + return this.defs().path(path).text(text).addTo(this) + }) }, Text: { // Create path for text to run on - path: wrapWithAttrCheck( function ( track ) { - + path: wrapWithAttrCheck(function (track) { var path = new TextPath() // if track is a path, reuse it - if ( !( track instanceof Path ) ) { - + if (!(track instanceof Path)) { // create path element - track = this.root().defs().path( track ) - + track = this.root().defs().path(track) } // link textPath to path and add content - path.attr( 'href', '#' + track, xlink ) + path.attr('href', '#' + track, xlink) // add textPath element as child node and return textPath - return this.put( path ) - - } ), + return this.put(path) + }), // Get the textPath children textPath () { - - return this.find( 'textPath' )[0] - + return this.find('textPath')[0] } }, Path: { // creates a textPath from this path - text: wrapWithAttrCheck( function ( text ) { - - if ( text instanceof Text ) { - + text: wrapWithAttrCheck(function (text) { + if (text instanceof Text) { var txt = text.text() - return text.clear().path( this ).text( txt ) - + return text.clear().path(this).text(txt) } - return this.parent().put( new Text() ).path( this ).text( text ) - - } ), + return this.parent().put(new Text()).path(this).text(text) + }), targets () { - - return baseFind( 'svg [href*="' + this.id() + '"]' ) - + return baseFind('svg [href*="' + this.id() + '"]') } } -} ) +}) TextPath.prototype.MorphArray = PathArray -register( TextPath ) +register(TextPath) diff --git a/src/elements/Tspan.js b/src/elements/Tspan.js index fcf8cf5..abd032f 100644 --- a/src/elements/Tspan.js +++ b/src/elements/Tspan.js @@ -9,77 +9,61 @@ import Text from './Text.js' import * as textable from '../modules/core/textable.js' export default class Tspan extends Text { - // Initialize node - constructor ( node ) { - - super( nodeOrNew( 'tspan', node ), node ) - + constructor (node) { + super(nodeOrNew('tspan', node), node) } // Set text content - text ( text ) { - - if ( text == null ) return this.node.textContent + ( this.dom.newLined ? '\n' : '' ) + text (text) { + if (text == null) return this.node.textContent + (this.dom.newLined ? '\n' : '') - typeof text === 'function' ? text.call( this, this ) : this.plain( text ) + typeof text === 'function' ? text.call(this, this) : this.plain(text) return this - } // Shortcut dx - dx ( dx ) { - - return this.attr( 'dx', dx ) - + dx (dx) { + return this.attr('dx', dx) } // Shortcut dy - dy ( dy ) { - - return this.attr( 'dy', dy ) - + dy (dy) { + return this.attr('dy', dy) } // Create new line newLine () { - // fetch text parent - var t = this.parent( Text ) + var t = this.parent(Text) // mark new line this.dom.newLined = true // apply new position - return this.dy( t.dom.leading * t.attr( 'font-size' ) ).attr( 'x', t.x() ) - + return this.dy(t.dom.leading * t.attr('font-size')).attr('x', t.x()) } - } -extend( Tspan, textable ) +extend(Tspan, textable) -registerMethods( { +registerMethods({ Tspan: { - tspan: wrapWithAttrCheck( function ( text ) { - + tspan: wrapWithAttrCheck(function (text) { var tspan = new Tspan() // clear if build mode is disabled - if ( !this._build ) { - + if (!this._build) { this.clear() - } // add new tspan - this.node.appendChild( tspan.node ) - - return tspan.text( text ) + this.node.appendChild(tspan.node) - } ) + return tspan.text(text) + }) } -} ) +}) -register( Tspan ) +register(Tspan) diff --git a/src/elements/Use.js b/src/elements/Use.js index 9237e08..7921461 100644 --- a/src/elements/Use.js +++ b/src/elements/Use.js @@ -4,32 +4,24 @@ import { xlink } from '../modules/core/namespaces.js' import Shape from './Shape.js' export default class Use extends Shape { - - constructor ( node ) { - - super( nodeOrNew( 'use', node ), node ) - + constructor (node) { + super(nodeOrNew('use', node), node) } // Use element as a reference - element ( element, file ) { - + element (element, file) { // Set lined element - return this.attr( 'href', ( file || '' ) + '#' + element, xlink ) - + return this.attr('href', (file || '') + '#' + element, xlink) } - } -registerMethods( { +registerMethods({ Container: { // Create a use element - use: wrapWithAttrCheck( function ( element, file ) { - - return this.put( new Use() ).element( element, file ) - - } ) + use: wrapWithAttrCheck(function (element, file) { + return this.put(new Use()).element(element, file) + }) } -} ) +}) -register( Use ) +register(Use) diff --git a/src/main.js b/src/main.js index 951cc69..919fb25 100644 --- a/src/main.js +++ b/src/main.js @@ -116,50 +116,50 @@ export { default as TextPath } from './elements/TextPath.js' export { default as Tspan } from './elements/Tspan.js' export { default as Use } from './elements/Use.js' -extend( [ +extend([ Svg, Symbol, Image, Pattern, Marker -], getMethodsFor( 'viewbox' ) ) +], getMethodsFor('viewbox')) -extend( [ +extend([ Line, Polyline, Polygon, Path -], getMethodsFor( 'marker' ) ) +], getMethodsFor('marker')) -extend( Text, getMethodsFor( 'Text' ) ) -extend( Path, getMethodsFor( 'Path' ) ) +extend(Text, getMethodsFor('Text')) +extend(Path, getMethodsFor('Path')) -extend( Defs, getMethodsFor( 'Defs' ) ) +extend(Defs, getMethodsFor('Defs')) -extend( [ +extend([ Text, Tspan -], getMethodsFor( 'Tspan' ) ) +], getMethodsFor('Tspan')) -extend( [ +extend([ Rect, Ellipse, Circle, Gradient -], getMethodsFor( 'radius' ) ) +], getMethodsFor('radius')) -extend( EventTarget, getMethodsFor( 'EventTarget' ) ) -extend( Dom, getMethodsFor( 'Dom' ) ) -extend( Element, getMethodsFor( 'Element' ) ) -extend( Shape, getMethodsFor( 'Shape' ) ) +extend(EventTarget, getMethodsFor('EventTarget')) +extend(Dom, getMethodsFor('Dom')) +extend(Element, getMethodsFor('Element')) +extend(Shape, getMethodsFor('Shape')) // extend(Element, getConstructor('Memory')) -extend( Container, getMethodsFor( 'Container' ) ) +extend(Container, getMethodsFor('Container')) -extend( Runner, getMethodsFor( 'Runner' ) ) +extend(Runner, getMethodsFor('Runner')) -List.extend( getMethodNames() ) +List.extend(getMethodNames()) -registerMorphableType( [ +registerMorphableType([ SVGNumber, Color, Box, @@ -167,6 +167,6 @@ registerMorphableType( [ SVGArray, PointArray, PathArray -] ) +]) makeMorphable() diff --git a/src/modules/core/attr.js b/src/modules/core/attr.js index 7cb9e2a..79dd0d7 100644 --- a/src/modules/core/attr.js +++ b/src/modules/core/attr.js @@ -5,113 +5,77 @@ import SVGArray from '../../types/SVGArray.js' import SVGNumber from '../../types/SVGNumber.js' const hooks = [] -export function registerAttrHook ( fn ) { - - hooks.push( fn ) - +export function registerAttrHook (fn) { + hooks.push(fn) } // Set svg element attribute -export default function attr ( attr, val, ns ) { - +export default function attr (attr, val, ns) { // act as full getter - if ( attr == null ) { - + if (attr == null) { // get an object of attributes attr = {} val = this.node.attributes - for ( let node of val ) { - - attr[node.nodeName] = isNumber.test( node.nodeValue ) - ? parseFloat( node.nodeValue ) + for (let node of val) { + attr[node.nodeName] = isNumber.test(node.nodeValue) + ? parseFloat(node.nodeValue) : node.nodeValue - } return attr - - } else if ( attr instanceof Array ) { - + } else if (attr instanceof Array) { // loop through array and get all values - return attr.reduce( ( last, curr ) => { - - last[curr] = this.attr( curr ) + return attr.reduce((last, curr) => { + last[curr] = this.attr(curr) return last - - }, {} ) - - } else if ( typeof attr === 'object' ) { - + }, {}) + } else if (typeof attr === 'object') { // apply every attribute individually if an object is passed - for ( val in attr ) this.attr( val, attr[val] ) - - } else if ( val === null ) { - + for (val in attr) this.attr(val, attr[val]) + } else if (val === null) { // remove value - this.node.removeAttribute( attr ) - - } else if ( val == null ) { - + this.node.removeAttribute(attr) + } else if (val == null) { // act as a getter if the first and only argument is not an object - val = this.node.getAttribute( attr ) + val = this.node.getAttribute(attr) return val == null ? defaults[attr] - : isNumber.test( val ) ? parseFloat( val ) + : isNumber.test(val) ? parseFloat(val) : val - } else { - // Loop through hooks and execute them to convert value - val = hooks.reduce( ( _val, hook ) => { - - return hook( attr, _val, this ) - - }, val ) + val = hooks.reduce((_val, hook) => { + return hook(attr, _val, this) + }, val) // ensure correct numeric values (also accepts NaN and Infinity) - if ( typeof val === 'number' ) { - - val = new SVGNumber( val ) - - } else if ( Color.isColor( val ) ) { - + if (typeof val === 'number') { + val = new SVGNumber(val) + } else if (Color.isColor(val)) { // ensure full hex color - val = new Color( val ) - - } else if ( val.constructor === Array ) { - + val = new Color(val) + } else if (val.constructor === Array) { // Check for plain arrays and parse array values - val = new SVGArray( val ) - + val = new SVGArray(val) } // if the passed attribute is leading... - if ( attr === 'leading' ) { - + if (attr === 'leading') { // ... call the leading method instead - if ( this.leading ) { - - this.leading( val ) - + if (this.leading) { + this.leading(val) } - } else { - // set given attribute on node - typeof ns === 'string' ? this.node.setAttributeNS( ns, attr, val.toString() ) - : this.node.setAttribute( attr, val.toString() ) - + typeof ns === 'string' ? this.node.setAttributeNS(ns, attr, val.toString()) + : this.node.setAttribute(attr, val.toString()) } // rebuild if required - if ( this.rebuild && ( attr === 'font-size' || attr === 'x' ) ) { - + if (this.rebuild && (attr === 'font-size' || attr === 'x')) { this.rebuild() - } - } return this - } diff --git a/src/modules/core/circled.js b/src/modules/core/circled.js index ad901b9..597d252 100644 --- a/src/modules/core/circled.js +++ b/src/modules/core/circled.js @@ -1,69 +1,53 @@ import SVGNumber from '../../types/SVGNumber.js' // Radius x value -export function rx ( rx ) { - - return this.attr( 'rx', rx ) - +export function rx (rx) { + return this.attr('rx', rx) } // Radius y value -export function ry ( ry ) { - - return this.attr( 'ry', ry ) - +export function ry (ry) { + return this.attr('ry', ry) } // Move over x-axis -export function x ( x ) { - +export function x (x) { return x == null ? this.cx() - this.rx() - : this.cx( x + this.rx() ) - + : this.cx(x + this.rx()) } // Move over y-axis -export function y ( y ) { - +export function y (y) { return y == null ? this.cy() - this.ry() - : this.cy( y + this.ry() ) - + : this.cy(y + this.ry()) } // Move by center over x-axis -export function cx ( x ) { - +export function cx (x) { return x == null - ? this.attr( 'cx' ) - : this.attr( 'cx', x ) - + ? this.attr('cx') + : this.attr('cx', x) } // Move by center over y-axis -export function cy ( y ) { - +export function cy (y) { return y == null - ? this.attr( 'cy' ) - : this.attr( 'cy', y ) - + ? this.attr('cy') + : this.attr('cy', y) } // Set width of element -export function width ( width ) { - +export function width (width) { return width == null ? this.rx() * 2 - : this.rx( new SVGNumber( width ).divide( 2 ) ) - + : this.rx(new SVGNumber(width).divide(2)) } // Set height of element -export function height ( height ) { - +export function height (height) { return height == null ? this.ry() * 2 - : this.ry( new SVGNumber( height ).divide( 2 ) ) - + : this.ry(new SVGNumber(height).divide(2)) } diff --git a/src/modules/core/event.js b/src/modules/core/event.js index 23459fb..507e91f 100644 --- a/src/modules/core/event.js +++ b/src/modules/core/event.js @@ -4,48 +4,38 @@ import { globals } from '../../utils/window.js' let listenerId = 0 -function getEvents ( node ) { - - const n = makeInstance( node ).getEventHolder() - if ( !n.events ) n.events = {} +function getEvents (node) { + const n = makeInstance(node).getEventHolder() + if (!n.events) n.events = {} return n.events - } -function getEventTarget ( node ) { - - return makeInstance( node ).getEventTarget() - +function getEventTarget (node) { + return makeInstance(node).getEventTarget() } -function clearEvents ( node ) { - - const n = makeInstance( node ).getEventHolder() - if ( n.events ) n.events = {} - +function clearEvents (node) { + const n = makeInstance(node).getEventHolder() + if (n.events) n.events = {} } // Add event binder in the SVG namespace -export function on ( node, events, listener, binding, options ) { - - var l = listener.bind( binding || node ) - var bag = getEvents( node ) - var n = getEventTarget( node ) +export function on (node, events, listener, binding, options) { + var l = listener.bind(binding || node) + var bag = getEvents(node) + var n = getEventTarget(node) // events can be an array of events or a string of events - events = Array.isArray( events ) ? events : events.split( delimiter ) + events = Array.isArray(events) ? events : events.split(delimiter) // add id to listener - if ( !listener._svgjsListenerId ) { - + if (!listener._svgjsListenerId) { listener._svgjsListenerId = ++listenerId - } - events.forEach( function ( event ) { - - var ev = event.split( '.' )[0] - var ns = event.split( '.' )[1] || '*' + events.forEach(function (event) { + var ev = event.split('.')[0] + var ns = event.split('.')[1] || '*' // ensure valid object bag[ev] = bag[ev] || {} @@ -55,126 +45,84 @@ export function on ( node, events, listener, binding, options ) { bag[ev][ns][listener._svgjsListenerId] = l // add listener - n.addEventListener( ev, l, options || false ) - - } ) - + n.addEventListener(ev, l, options || false) + }) } // Add event unbinder in the SVG namespace -export function off ( node, events, listener, options ) { - - var bag = getEvents( node ) - var n = getEventTarget( node ) +export function off (node, events, listener, options) { + var bag = getEvents(node) + var n = getEventTarget(node) // listener can be a function or a number - if ( typeof listener === 'function' ) { - + if (typeof listener === 'function') { listener = listener._svgjsListenerId - if ( !listener ) return - + if (!listener) return } // events can be an array of events or a string or undefined - events = Array.isArray( events ) ? events : ( events || '' ).split( delimiter ) + events = Array.isArray(events) ? events : (events || '').split(delimiter) - events.forEach( function ( event ) { - - var ev = event && event.split( '.' )[0] - var ns = event && event.split( '.' )[1] + events.forEach(function (event) { + var ev = event && event.split('.')[0] + var ns = event && event.split('.')[1] var namespace, l - if ( listener ) { - + if (listener) { // remove listener reference - if ( bag[ev] && bag[ev][ns || '*'] ) { - + if (bag[ev] && bag[ev][ns || '*']) { // removeListener - n.removeEventListener( ev, bag[ev][ns || '*'][listener], options || false ) + n.removeEventListener(ev, bag[ev][ns || '*'][listener], options || false) delete bag[ev][ns || '*'][listener] - } - - } else if ( ev && ns ) { - + } else if (ev && ns) { // remove all listeners for a namespaced event - if ( bag[ev] && bag[ev][ns] ) { - - for ( l in bag[ev][ns] ) { - - off( n, [ ev, ns ].join( '.' ), l ) - + if (bag[ev] && bag[ev][ns]) { + for (l in bag[ev][ns]) { + off(n, [ ev, ns ].join('.'), l) } delete bag[ev][ns] - } - - } else if ( ns ) { - + } else if (ns) { // remove all listeners for a specific namespace - for ( event in bag ) { - - for ( namespace in bag[event] ) { - - if ( ns === namespace ) { - - off( n, [ event, ns ].join( '.' ) ) - + for (event in bag) { + for (namespace in bag[event]) { + if (ns === namespace) { + off(n, [ event, ns ].join('.')) } - } - } - - } else if ( ev ) { - + } else if (ev) { // remove all listeners for the event - if ( bag[ev] ) { - - for ( namespace in bag[ev] ) { - - off( n, [ ev, namespace ].join( '.' ) ) - + if (bag[ev]) { + for (namespace in bag[ev]) { + off(n, [ ev, namespace ].join('.')) } delete bag[ev] - } - } else { - // remove all listeners on a given node - for ( event in bag ) { - - off( n, event ) - + for (event in bag) { + off(n, event) } - clearEvents( node ) - + clearEvents(node) } - - } ) - + }) } -export function dispatch ( node, event, data ) { - - var n = getEventTarget( node ) +export function dispatch (node, event, data) { + var n = getEventTarget(node) // Dispatch event - if ( event instanceof globals.window.Event ) { - - n.dispatchEvent( event ) - + if (event instanceof globals.window.Event) { + n.dispatchEvent(event) } else { - - event = new globals.window.CustomEvent( event, { detail: data, cancelable: true } ) - n.dispatchEvent( event ) - + event = new globals.window.CustomEvent(event, { detail: data, cancelable: true }) + n.dispatchEvent(event) } return event - } diff --git a/src/modules/core/gradiented.js b/src/modules/core/gradiented.js index dd9c46f..6c744e4 100644 --- a/src/modules/core/gradiented.js +++ b/src/modules/core/gradiented.js @@ -1,17 +1,13 @@ import SVGNumber from '../../types/SVGNumber.js' -export function from ( x, y ) { - - return ( this._element || this ).type === 'radialGradient' - ? this.attr( { fx: new SVGNumber( x ), fy: new SVGNumber( y ) } ) - : this.attr( { x1: new SVGNumber( x ), y1: new SVGNumber( y ) } ) - +export function from (x, y) { + return (this._element || this).type === 'radialGradient' + ? this.attr({ fx: new SVGNumber(x), fy: new SVGNumber(y) }) + : this.attr({ x1: new SVGNumber(x), y1: new SVGNumber(y) }) } -export function to ( x, y ) { - - return ( this._element || this ).type === 'radialGradient' - ? this.attr( { cx: new SVGNumber( x ), cy: new SVGNumber( y ) } ) - : this.attr( { x2: new SVGNumber( x ), y2: new SVGNumber( y ) } ) - +export function to (x, y) { + return (this._element || this).type === 'radialGradient' + ? this.attr({ cx: new SVGNumber(x), cy: new SVGNumber(y) }) + : this.attr({ x2: new SVGNumber(x), y2: new SVGNumber(y) }) } diff --git a/src/modules/core/parser.js b/src/modules/core/parser.js index 12c9728..1ff2380 100644 --- a/src/modules/core/parser.js +++ b/src/modules/core/parser.js @@ -2,32 +2,26 @@ import { globals } from '../../utils/window.js' import { makeInstance } from '../../utils/adopter.js' export default function parser () { - // Reuse cached element if possible - if ( !parser.nodes ) { - - let svg = makeInstance().size( 2, 0 ) + if (!parser.nodes) { + let svg = makeInstance().size(2, 0) svg.node.cssText = [ 'opacity: 0', 'position: absolute', 'left: -100%', 'top: -100%', 'overflow: hidden' - ].join( ';' ) + ].join(';') let path = svg.path().node parser.nodes = { svg, path } - } - if ( !parser.nodes.svg.node.parentNode ) { - + if (!parser.nodes.svg.node.parentNode) { let b = globals.document.body || globals.document.documentElement - parser.nodes.svg.addTo( b ) - + parser.nodes.svg.addTo(b) } return parser.nodes - } diff --git a/src/modules/core/pointed.js b/src/modules/core/pointed.js index 813b0e3..95e6819 100644 --- a/src/modules/core/pointed.js +++ b/src/modules/core/pointed.js @@ -3,31 +3,23 @@ import PointArray from '../../types/PointArray.js' export let MorphArray = PointArray // Move by left top corner over x-axis -export function x ( x ) { - - return x == null ? this.bbox().x : this.move( x, this.bbox().y ) - +export function x (x) { + return x == null ? this.bbox().x : this.move(x, this.bbox().y) } // Move by left top corner over y-axis -export function y ( y ) { - - return y == null ? this.bbox().y : this.move( this.bbox().x, y ) - +export function y (y) { + return y == null ? this.bbox().y : this.move(this.bbox().x, y) } // Set width of element -export function width ( width ) { - +export function width (width) { let b = this.bbox() - return width == null ? b.width : this.size( width, b.height ) - + return width == null ? b.width : this.size(width, b.height) } // Set height of element -export function height ( height ) { - +export function height (height) { let b = this.bbox() - return height == null ? b.height : this.size( b.width, height ) - + return height == null ? b.height : this.size(b.width, height) } diff --git a/src/modules/core/poly.js b/src/modules/core/poly.js index 56703a5..f23b70b 100644 --- a/src/modules/core/poly.js +++ b/src/modules/core/poly.js @@ -3,39 +3,29 @@ import PointArray from '../../types/PointArray.js' // Get array export function array () { - - return this._array || ( this._array = new PointArray( this.attr( 'points' ) ) ) - + return this._array || (this._array = new PointArray(this.attr('points'))) } // Plot new path -export function plot ( p ) { - - return ( p == null ) ? this.array() - : this.clear().attr( 'points', typeof p === 'string' ? p - : ( this._array = new PointArray( p ) ) ) - +export function plot (p) { + return (p == null) ? this.array() + : this.clear().attr('points', typeof p === 'string' ? p + : (this._array = new PointArray(p))) } // Clear array cache export function clear () { - delete this._array return this - } // Move by left top corner -export function move ( x, y ) { - - return this.attr( 'points', this.array().move( x, y ) ) - +export function move (x, y) { + return this.attr('points', this.array().move(x, y)) } // Set element size to given width and height -export function size ( width, height ) { - - let p = proportionalSize( this, width, height ) - return this.attr( 'points', this.array().size( p.width, p.height ) ) - +export function size (width, height) { + let p = proportionalSize(this, width, height) + return this.attr('points', this.array().size(p.width, p.height)) } diff --git a/src/modules/core/selector.js b/src/modules/core/selector.js index a60df02..24841c5 100644 --- a/src/modules/core/selector.js +++ b/src/modules/core/selector.js @@ -3,19 +3,13 @@ import { globals } from '../../utils/window.js' import { map } from '../../utils/utils.js' import List from '../../types/List.js' -export default function baseFind ( query, parent ) { - - return new List( map( ( parent || globals.document ).querySelectorAll( query ), function ( node ) { - - return adopt( node ) - - } ) ) - +export default function baseFind (query, parent) { + return new List(map((parent || globals.document).querySelectorAll(query), function (node) { + return adopt(node) + })) } // Scoped find method -export function find ( query ) { - - return baseFind( query, this.node ) - +export function find (query) { + return baseFind(query, this.node) } diff --git a/src/modules/core/textable.js b/src/modules/core/textable.js index b0a0993..55df7c6 100644 --- a/src/modules/core/textable.js +++ b/src/modules/core/textable.js @@ -1,25 +1,19 @@ import { globals } from '../../utils/window.js' // Create plain text node -export function plain ( text ) { - +export function plain (text) { // clear if build mode is disabled - if ( this._build === false ) { - + if (this._build === false) { this.clear() - } // create text node - this.node.appendChild( globals.document.createTextNode( text ) ) + this.node.appendChild(globals.document.createTextNode(text)) return this - } // Get length of text element export function length () { - return this.node.getComputedTextLength() - } diff --git a/src/modules/optional/arrange.js b/src/modules/optional/arrange.js index 51e8605..6ce2eea 100644 --- a/src/modules/optional/arrange.js +++ b/src/modules/optional/arrange.js @@ -3,141 +3,109 @@ import { registerMethods } from '../../utils/methods.js' // Get all siblings, including myself export function siblings () { - return this.parent().children() - } // Get the curent position siblings export function position () { - - return this.parent().index( this ) - + return this.parent().index(this) } // Get the next element (will return null if there is none) export function next () { - return this.siblings()[this.position() + 1] - } // Get the next element (will return null if there is none) export function prev () { - return this.siblings()[this.position() - 1] - } // Send given element one step forward export function forward () { - var i = this.position() + 1 var p = this.parent() // move node one step forward - p.removeElement( this ).add( this, i ) + p.removeElement(this).add(this, i) // make sure defs node is always at the top - if ( typeof p.isRoot === 'function' && p.isRoot() ) { - - p.node.appendChild( p.defs().node ) - + if (typeof p.isRoot === 'function' && p.isRoot()) { + p.node.appendChild(p.defs().node) } return this - } // Send given element one step backward export function backward () { - var i = this.position() - if ( i > 0 ) { - - this.parent().removeElement( this ).add( this, i - 1 ) - + if (i > 0) { + this.parent().removeElement(this).add(this, i - 1) } return this - } // Send given element all the way to the front export function front () { - var p = this.parent() // Move node forward - p.node.appendChild( this.node ) + p.node.appendChild(this.node) // Make sure defs node is always at the top - if ( typeof p.isRoot === 'function' && p.isRoot() ) { - - p.node.appendChild( p.defs().node ) - + if (typeof p.isRoot === 'function' && p.isRoot()) { + p.node.appendChild(p.defs().node) } return this - } // Send given element all the way to the back export function back () { - - if ( this.position() > 0 ) { - - this.parent().removeElement( this ).add( this, 0 ) - + if (this.position() > 0) { + this.parent().removeElement(this).add(this, 0) } return this - } // Inserts a given element before the targeted element -export function before ( element ) { - - element = makeInstance( element ) +export function before (element) { + element = makeInstance(element) element.remove() var i = this.position() - this.parent().add( element, i ) + this.parent().add(element, i) return this - } // Inserts a given element after the targeted element -export function after ( element ) { - - element = makeInstance( element ) +export function after (element) { + element = makeInstance(element) element.remove() var i = this.position() - this.parent().add( element, i + 1 ) + this.parent().add(element, i + 1) return this - } -export function insertBefore ( element ) { - - element = makeInstance( element ) - element.before( this ) - +export function insertBefore (element) { + element = makeInstance(element) + element.before(this) } -export function insertAfter ( element ) { - - element = makeInstance( element ) - element.after( this ) - +export function insertAfter (element) { + element = makeInstance(element) + element.after(this) } -registerMethods( 'Dom', { +registerMethods('Dom', { siblings, position, next, prev, forward, backward, front, back, before, after -} ) +}) diff --git a/src/modules/optional/class.js b/src/modules/optional/class.js index 93ccd0e..b08c82b 100644 --- a/src/modules/optional/class.js +++ b/src/modules/optional/class.js @@ -3,58 +3,42 @@ import { registerMethods } from '../../utils/methods.js' // Return array of classes on the node export function classes () { - - var attr = this.attr( 'class' ) - return attr == null ? [] : attr.trim().split( delimiter ) - + var attr = this.attr('class') + return attr == null ? [] : attr.trim().split(delimiter) } // Return true if class exists on the node, false otherwise -export function hasClass ( name ) { - - return this.classes().indexOf( name ) !== -1 - +export function hasClass (name) { + return this.classes().indexOf(name) !== -1 } // Add class to the node -export function addClass ( name ) { - - if ( !this.hasClass( name ) ) { - +export function addClass (name) { + if (!this.hasClass(name)) { var array = this.classes() - array.push( name ) - this.attr( 'class', array.join( ' ' ) ) - + array.push(name) + this.attr('class', array.join(' ')) } return this - } // Remove class from the node -export function removeClass ( name ) { - - if ( this.hasClass( name ) ) { - - this.attr( 'class', this.classes().filter( function ( c ) { - +export function removeClass (name) { + if (this.hasClass(name)) { + this.attr('class', this.classes().filter(function (c) { return c !== name - - } ).join( ' ' ) ) - + }).join(' ')) } return this - } // Toggle the presence of a class on the node -export function toggleClass ( name ) { - - return this.hasClass( name ) ? this.removeClass( name ) : this.addClass( name ) - +export function toggleClass (name) { + return this.hasClass(name) ? this.removeClass(name) : this.addClass(name) } -registerMethods( 'Dom', { +registerMethods('Dom', { classes, hasClass, addClass, removeClass, toggleClass -} ) +}) diff --git a/src/modules/optional/css.js b/src/modules/optional/css.js index d5378f4..2c97f3e 100644 --- a/src/modules/optional/css.js +++ b/src/modules/optional/css.js @@ -3,98 +3,70 @@ import { isBlank } from '../core/regex.js' import { registerMethods } from '../../utils/methods.js' // Dynamic style generator -export function css ( style, val ) { - +export function css (style, val) { let ret = {} - if ( arguments.length === 0 ) { - + if (arguments.length === 0) { // get full style as object - this.node.style.cssText.split( /\s*;\s*/ ) - .filter( function ( el ) { - + this.node.style.cssText.split(/\s*;\s*/) + .filter(function (el) { return !!el.length - - } ) - .forEach( function ( el ) { - - let t = el.split( /\s*:\s*/ ) + }) + .forEach(function (el) { + let t = el.split(/\s*:\s*/) ret[t[0]] = t[1] - - } ) + }) return ret - } - if ( arguments.length < 2 ) { - + if (arguments.length < 2) { // get style properties in the array - if ( Array.isArray( style ) ) { - - for ( let name of style ) { - - let cased = camelCase( name ) + if (Array.isArray(style)) { + for (let name of style) { + let cased = camelCase(name) ret[cased] = this.node.style[cased] - } return ret - } // get style for property - if ( typeof style === 'string' ) { - - return this.node.style[camelCase( style )] - + if (typeof style === 'string') { + return this.node.style[camelCase(style)] } // set styles in object - if ( typeof style === 'object' ) { - - for ( let name in style ) { - + if (typeof style === 'object') { + for (let name in style) { // set empty string if null/undefined/'' was given - this.node.style[camelCase( name )] - = ( style[name] == null || isBlank.test( style[name] ) ) ? '' : style[name] - + this.node.style[camelCase(name)] + = (style[name] == null || isBlank.test(style[name])) ? '' : style[name] } - } - } // set style for property - if ( arguments.length === 2 ) { - - this.node.style[camelCase( style )] - = ( val == null || isBlank.test( val ) ) ? '' : val - + if (arguments.length === 2) { + this.node.style[camelCase(style)] + = (val == null || isBlank.test(val)) ? '' : val } return this - } // Show element export function show () { - - return this.css( 'display', '' ) - + return this.css('display', '') } // Hide element export function hide () { - - return this.css( 'display', 'none' ) - + return this.css('display', 'none') } // Is element visible? export function visible () { - - return this.css( 'display' ) !== 'none' - + return this.css('display') !== 'none' } -registerMethods( 'Dom', { +registerMethods('Dom', { css, show, hide, visible -} ) +}) diff --git a/src/modules/optional/data.js b/src/modules/optional/data.js index 498e65a..4c163c0 100644 --- a/src/modules/optional/data.js +++ b/src/modules/optional/data.js @@ -1,40 +1,26 @@ import { registerMethods } from '../../utils/methods.js' // Store data values on svg nodes -export function data ( a, v, r ) { - - if ( typeof a === 'object' ) { - - for ( v in a ) { - - this.data( v, a[v] ) - +export function data (a, v, r) { + if (typeof a === 'object') { + for (v in a) { + this.data(v, a[v]) } - - } else if ( arguments.length < 2 ) { - + } else if (arguments.length < 2) { try { - - return JSON.parse( this.attr( 'data-' + a ) ) - - } catch ( e ) { - - return this.attr( 'data-' + a ) - + return JSON.parse(this.attr('data-' + a)) + } catch (e) { + return this.attr('data-' + a) } - } else { - - this.attr( 'data-' + a, + this.attr('data-' + a, v === null ? null : r === true || typeof v === 'string' || typeof v === 'number' ? v - : JSON.stringify( v ) + : JSON.stringify(v) ) - } return this - } -registerMethods( 'Dom', { data } ) +registerMethods('Dom', { data }) diff --git a/src/modules/optional/memory.js b/src/modules/optional/memory.js index 7c599f0..6478367 100644 --- a/src/modules/optional/memory.js +++ b/src/modules/optional/memory.js @@ -1,60 +1,40 @@ import { registerMethods } from '../../utils/methods.js' // Remember arbitrary data -export function remember ( k, v ) { - +export function remember (k, v) { // remember every item in an object individually - if ( typeof arguments[0] === 'object' ) { - - for ( var key in k ) { - - this.remember( key, k[key] ) - + if (typeof arguments[0] === 'object') { + for (var key in k) { + this.remember(key, k[key]) } - - } else if ( arguments.length === 1 ) { - + } else if (arguments.length === 1) { // retrieve memory return this.memory()[k] - } else { - // store memory this.memory()[k] = v - } return this - } // Erase a given memory export function forget () { - - if ( arguments.length === 0 ) { - + if (arguments.length === 0) { this._memory = {} - } else { - - for ( var i = arguments.length - 1; i >= 0; i-- ) { - + for (var i = arguments.length - 1; i >= 0; i--) { delete this.memory()[arguments[i]] - } - } return this - } // This triggers creation of a new hidden class which is not performant // However, this function is not rarely used so it will not happen frequently // Return local memory object export function memory () { - - return ( this._memory = this._memory || {} ) - + return (this._memory = this._memory || {}) } -registerMethods( 'Dom', { remember, forget, memory } ) +registerMethods('Dom', { remember, forget, memory }) diff --git a/src/modules/optional/sugar.js b/src/modules/optional/sugar.js index 4b6e6f3..3bd61fb 100644 --- a/src/modules/optional/sugar.js +++ b/src/modules/optional/sugar.js @@ -10,225 +10,167 @@ import SVGNumber from '../../types/SVGNumber.js' var sugar = { stroke: [ 'color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset' ], fill: [ 'color', 'opacity', 'rule' ], - prefix: function ( t, a ) { - + prefix: function (t, a) { return a === 'color' ? t : t + '-' + a - } } // Add sugar for fill and stroke -;[ 'fill', 'stroke' ].forEach( function ( m ) { - +;[ 'fill', 'stroke' ].forEach(function (m) { var extension = {} var i - extension[m] = function ( o ) { - - if ( typeof o === 'undefined' ) { - - return this.attr( m ) - + extension[m] = function (o) { + if (typeof o === 'undefined') { + return this.attr(m) } - if ( typeof o === 'string' || Color.isRgb( o ) || ( o instanceof Element ) ) { - - this.attr( m, o ) - + if (typeof o === 'string' || Color.isRgb(o) || (o instanceof Element)) { + 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]] ) - + 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( [ 'Shape', 'Runner' ], extension ) + registerMethods([ 'Shape', 'Runner' ], extension) +}) -} ) - -registerMethods( [ 'Element', 'Runner' ], { +registerMethods([ 'Element', 'Runner' ], { // 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 - if ( mat == null ) { - - return new Matrix( this ) - + 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 ) ) - + return this.attr('transform', new Matrix(mat, b, c, d, e, f)) }, // Map rotation to transform - rotate: function ( angle, cx, cy ) { - - return this.transform( { rotate: angle, ox: cx, oy: cy }, true ) - + rotate: function (angle, cx, cy) { + return this.transform({ rotate: angle, ox: cx, oy: cy }, true) }, // Map skew to transform - skew: function ( x, y, cx, cy ) { - + skew: function (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 ) - + ? this.transform({ skew: x, ox: y, oy: cx }, true) + : this.transform({ skew: [ x, y ], ox: cx, oy: cy }, true) }, - shear: function ( lam, cx, cy ) { - - return this.transform( { shear: lam, ox: cx, oy: cy }, true ) - + shear: function (lam, cx, cy) { + return this.transform({ shear: lam, ox: cx, oy: cy }, true) }, // Map scale to transform - scale: function ( x, y, cx, cy ) { - + scale: function (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 ) - + ? 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 ( x, y ) { - - return this.transform( { translate: [ x, y ] }, true ) - + translate: function (x, y) { + return this.transform({ translate: [ x, y ] }, true) }, // Map relative translations to transform - relative: function ( x, y ) { - - return this.transform( { relative: [ x, y ] }, true ) - + relative: function (x, y) { + return this.transform({ relative: [ x, y ] }, true) }, // Map flip to transform - flip: function ( direction, around ) { - + flip: function (direction, around) { var directionString = typeof direction === 'string' ? direction - : isFinite( direction ) ? 'both' + : isFinite(direction) ? 'both' : 'both' - var origin = ( direction === 'both' && isFinite( around ) ) ? [ around, around ] - : ( direction === 'x' ) ? [ around, 0 ] - : ( direction === 'y' ) ? [ 0, around ] - : isFinite( direction ) ? [ direction, direction ] + 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 ) - + this.transform({ flip: directionString, origin: origin }, true) }, // Opacity - opacity: function ( value ) { - - return this.attr( 'opacity', value ) - + opacity: function (value) { + return this.attr('opacity', value) }, // Relative move over x and y axes - dmove: function ( x, y ) { - - return this.dx( x ).dy( y ) - + dmove: function (x, y) { + return this.dx(x).dy(y) } -} ) +}) -registerMethods( 'Element', { +registerMethods('Element', { // Relative move over x axis - dx: function ( x ) { - - return this.x( new SVGNumber( x ).plus( this.x() ) ) - + dx: function (x) { + return this.x(new SVGNumber(x).plus(this.x())) }, // Relative move over y axis - dy: function ( y ) { - - return this.y( new SVGNumber( y ).plus( this.y() ) ) - + dy: function (y) { + return this.y(new SVGNumber(y).plus(this.y())) } -} ) +}) -registerMethods( 'radius', { +registerMethods('radius', { // Add x and y radius - radius: function ( x, y ) { - - var type = ( this._element || this ).type + radius: function (x, y) { + var type = (this._element || this).type return type === 'radialGradient' || type === 'radialGradient' - ? this.attr( 'r', new SVGNumber( x ) ) - : this.rx( x ).ry( y == null ? x : y ) - + ? this.attr('r', new SVGNumber(x)) + : this.rx(x).ry(y == null ? x : y) } -} ) +}) -registerMethods( 'Path', { +registerMethods('Path', { // Get path length length: function () { - return this.node.getTotalLength() - }, // Get point at length - pointAt: function ( length ) { - - return new Point( this.node.getPointAtLength( length ) ) - + pointAt: function (length) { + return new Point(this.node.getPointAtLength(length)) } -} ) +}) -registerMethods( [ 'Element', 'Runner' ], { +registerMethods([ 'Element', 'Runner' ], { // Set font - font: function ( a, v ) { - - if ( typeof a === 'object' ) { - - for ( v in a ) this.font( v, a[v] ) - + font: function (a, v) { + if (typeof a === 'object') { + for (v in a) this.font(v, a[v]) } return a === 'leading' - ? this.leading( v ) + ? this.leading(v) : a === 'anchor' - ? this.attr( 'text-anchor', v ) + ? 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 ) - + ? this.attr('font-' + a, v) + : this.attr(a, v) } -} ) - -registerMethods( 'Text', { - ax ( x ) { - - return this.attr( 'x', x ) +}) +registerMethods('Text', { + ax (x) { + return this.attr('x', x) }, - ay ( y ) { - - return this.attr( 'y', y ) - + ay (y) { + return this.attr('y', y) }, - amove ( x, y ) { - - return this.ax( x ).ay( y ) - + amove (x, y) { + return this.ax(x).ay(y) } -} ) +}) // Add events to elements const methods = [ 'click', @@ -244,27 +186,19 @@ const methods = [ 'click', 'touchmove', 'touchleave', 'touchend', - 'touchcancel' ].reduce( function ( last, event ) { - + 'touchcancel' ].reduce(function (last, event) { // add event to Element - const fn = function ( f ) { - - if ( f === null ) { - - off( this, event ) - + const fn = function (f) { + if (f === null) { + off(this, event) } else { - - on( this, event, f ) - + on(this, event, f) } return this - } last[event] = fn return last +}, {}) -}, {} ) - -registerMethods( 'Element', methods ) +registerMethods('Element', methods) diff --git a/src/modules/optional/transform.js b/src/modules/optional/transform.js index 717fbf3..0d0c7e3 100644 --- a/src/modules/optional/transform.js +++ b/src/modules/optional/transform.js @@ -5,92 +5,70 @@ import Matrix from '../../types/Matrix.js' // Reset all transformations export function untransform () { - - return this.attr( 'transform', null ) - + return this.attr('transform', null) } // merge the whole transformation chain into one matrix and returns it export function matrixify () { - - var matrix = ( this.attr( 'transform' ) || '' ) + var matrix = (this.attr('transform') || '') // split transformations - .split( transforms ).slice( 0, -1 ).map( function ( str ) { - + .split(transforms).slice(0, -1).map(function (str) { // generate key => value pairs - var kv = str.trim().split( '(' ) + var kv = str.trim().split('(') return [ kv[0], - kv[1].split( delimiter ) - .map( function ( str ) { - - return parseFloat( str ) - - } ) + kv[1].split(delimiter) + .map(function (str) { + return parseFloat(str) + }) ] - - } ) + }) .reverse() // merge every transformation into one matrix - .reduce( function ( matrix, transform ) { - - if ( transform[0] === 'matrix' ) { - - return matrix.lmultiply( Matrix.fromArray( transform[1] ) ) - + .reduce(function (matrix, transform) { + if (transform[0] === 'matrix') { + return matrix.lmultiply(Matrix.fromArray(transform[1])) } - return matrix[transform[0]].apply( matrix, transform[1] ) - - }, new Matrix() ) + return matrix[transform[0]].apply(matrix, transform[1]) + }, new Matrix()) return matrix - } // add an element to another parent without changing the visual representation on the screen -export function toParent ( parent ) { - - if ( this === parent ) return this +export function toParent (parent) { + if (this === parent) return this var ctm = this.screenCTM() var pCtm = parent.screenCTM().inverse() - this.addTo( parent ).untransform().transform( pCtm.multiply( ctm ) ) + this.addTo(parent).untransform().transform(pCtm.multiply(ctm)) return this - } // same as above with parent equals root-svg export function toRoot () { - - return this.toParent( this.root() ) - + return this.toParent(this.root()) } // Add transformations -export function transform ( o, relative ) { - +export function transform (o, relative) { // Act as a getter if no object was passed - if ( o == null || typeof o === 'string' ) { - - var decomposed = new Matrix( this ).decompose() + if (o == null || typeof o === 'string') { + var decomposed = new Matrix(this).decompose() return decomposed[o] || decomposed - } - if ( !Matrix.isMatrixLike( o ) ) { - + if (!Matrix.isMatrixLike(o)) { // Set the origin according to the defined transform - o = { ...o, origin: getOrigin( o, this ) } - + o = { ...o, origin: getOrigin(o, this) } } // The user can pass a boolean, an Element or an Matrix or nothing - var cleanRelative = relative === true ? this : ( relative || false ) - var result = new Matrix( cleanRelative ).transform( o ) - return this.attr( 'transform', result ) - + var cleanRelative = relative === true ? this : (relative || false) + var result = new Matrix(cleanRelative).transform(o) + return this.attr('transform', result) } -registerMethods( 'Element', { +registerMethods('Element', { untransform, matrixify, toParent, toRoot, transform -} ) +}) @@ -3,13 +3,11 @@ import * as regex from './modules/core/regex.js' import { makeInstance } from './utils/adopter' // The main wrapping element -export default function SVG ( element ) { - - return makeInstance( element ) - +export default function SVG (element) { + return makeInstance(element) } -Object.assign( SVG, svgMembers ) +Object.assign(SVG, svgMembers) SVG.utils = SVG SVG.regex = regex diff --git a/src/types/ArrayPolyfill.js b/src/types/ArrayPolyfill.js index 0ee29a5..4d2309f 100644 --- a/src/types/ArrayPolyfill.js +++ b/src/types/ArrayPolyfill.js @@ -1,10 +1,8 @@ /* eslint no-new-func: "off" */ -export const subClassArray = ( function () { - +export const subClassArray = (function () { try { - // try es6 subclassing - return Function( 'name', 'baseClass', '_constructor', [ + return Function('name', 'baseClass', '_constructor', [ 'baseClass = baseClass || Array', 'return {', ' [name]: class extends baseClass {', @@ -14,35 +12,25 @@ export const subClassArray = ( function () { ' }', ' }', '}[name]' - ].join( '\n' ) ) - - } catch ( e ) { - + ].join('\n')) + } catch (e) { // Use es5 approach - return ( name, baseClass = Array, _constructor ) => { - + return (name, baseClass = Array, _constructor) => { const Arr = function () { - - baseClass.apply( this, arguments ) - _constructor && _constructor.apply( this, arguments ) - + baseClass.apply(this, arguments) + _constructor && _constructor.apply(this, arguments) } - Arr.prototype = Object.create( baseClass.prototype ) + Arr.prototype = Object.create(baseClass.prototype) Arr.prototype.constructor = Arr - Arr.prototype.map = function ( fn ) { - + Arr.prototype.map = function (fn) { const arr = new Arr() - arr.push.apply( arr, Array.prototype.map.call( this, fn ) ) + arr.push.apply(arr, Array.prototype.map.call(this, fn)) return arr - } return Arr - } - } - -} )() +})() diff --git a/src/types/Box.js b/src/types/Box.js index 2fcb923..c90c7e0 100644 --- a/src/types/Box.js +++ b/src/types/Box.js @@ -4,44 +4,32 @@ import { globals } from '../utils/window.js' import Point from './Point.js' import parser from '../modules/core/parser.js' -function isNulledBox ( box ) { - +function isNulledBox (box) { return !box.w && !box.h && !box.x && !box.y - } -function domContains ( node ) { - - return ( globals.document.documentElement.contains || function ( node ) { - +function domContains (node) { + return (globals.document.documentElement.contains || function (node) { // This is IE - it does not support contains() for top-level SVGs - while ( node.parentNode ) { - + while (node.parentNode) { node = node.parentNode - } return node === document - - } ).call( globals.document.documentElement, node ) - + }).call(globals.document.documentElement, node) } export default class Box { - - constructor ( ...args ) { - - this.init( ...args ) - + constructor (...args) { + this.init(...args) } - init ( source ) { - + init (source) { var base = [ 0, 0, 0, 0 ] - source = typeof source === 'string' ? source.split( delimiter ).map( parseFloat ) - : Array.isArray( source ) ? source + source = typeof source === 'string' ? source.split(delimiter).map(parseFloat) + : Array.isArray(source) ? source : typeof source === 'object' ? [ source.left != null ? source.left : source.x, source.top != null ? source.top : source.y, source.width, source.height ] - : arguments.length === 4 ? [].slice.call( arguments ) + : arguments.length === 4 ? [].slice.call(arguments) : base this.x = source[0] || 0 @@ -56,139 +44,105 @@ export default class Box { this.cy = this.y + this.h / 2 return this - } // Merge rect box with another, return a new instance - merge ( box ) { - - let x = Math.min( this.x, box.x ) - let y = Math.min( this.y, box.y ) - let width = Math.max( this.x + this.width, box.x + box.width ) - x - let height = Math.max( this.y + this.height, box.y + box.height ) - y - - return new Box( x, y, width, height ) + merge (box) { + let x = Math.min(this.x, box.x) + let y = Math.min(this.y, box.y) + let width = Math.max(this.x + this.width, box.x + box.width) - x + let height = Math.max(this.y + this.height, box.y + box.height) - y + return new Box(x, y, width, height) } - transform ( m ) { - + transform (m) { let xMin = Infinity let xMax = -Infinity let yMin = Infinity let yMax = -Infinity let 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 ) + new Point(this.x, this.y), + new Point(this.x2, this.y), + new Point(this.x, this.y2), + new Point(this.x2, this.y2) ] - pts.forEach( function ( p ) { - - p = p.transform( m ) - xMin = Math.min( xMin, p.x ) - xMax = Math.max( xMax, p.x ) - yMin = Math.min( yMin, p.y ) - yMax = Math.max( yMax, p.y ) - - } ) + pts.forEach(function (p) { + p = p.transform(m) + xMin = Math.min(xMin, p.x) + xMax = Math.max(xMax, p.x) + yMin = Math.min(yMin, p.y) + yMax = Math.max(yMax, p.y) + }) return new Box( xMin, yMin, xMax - xMin, yMax - yMin ) - } addOffset () { - // offset by window scroll position, because getBoundingClientRect changes when window is scrolled this.x += globals.window.pageXOffset this.y += globals.window.pageYOffset return this - } toString () { - return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height - } toArray () { - return [ this.x, this.y, this.width, this.height ] - } isNulled () { - - return isNulledBox( this ) - + return isNulledBox(this) } - } -function getBox ( cb ) { - +function getBox (cb) { let box try { + box = cb(this.node) - box = cb( this.node ) - - if ( isNulledBox( box ) && !domContains( this.node ) ) { - - throw new Error( 'Element not in the dom' ) - + if (isNulledBox(box) && !domContains(this.node)) { + throw new Error('Element not in the dom') } - - } catch ( e ) { - + } catch (e) { try { - - let clone = this.clone().addTo( parser().svg ).show() - box = cb( clone.node ) + let clone = this.clone().addTo(parser().svg).show() + box = cb(clone.node) clone.remove() - - } catch ( e ) { - - throw new Error( 'Getting a bounding box of element "' + this.node.nodeName + '" is not possible' ) - + } catch (e) { + throw new Error('Getting a bounding box of element "' + this.node.nodeName + '" is not possible') } - } return box - } export function bbox () { - - return new Box( getBox.call( this, ( node ) => node.getBBox() ) ) - + return new Box(getBox.call(this, (node) => node.getBBox())) } -export function rbox ( el ) { - - let box = new Box( getBox.call( this, ( node ) => node.getBoundingClientRect() ) ) - if ( el ) return box.transform( el.screenCTM().inverse() ) +export function rbox (el) { + let box = new Box(getBox.call(this, (node) => node.getBoundingClientRect())) + if (el) return box.transform(el.screenCTM().inverse()) return box.addOffset() - } -registerMethods( { +registerMethods({ viewbox: { - viewbox ( x, y, width, height ) { - + viewbox (x, y, width, height) { // act as getter - if ( x == null ) return new Box( this.attr( 'viewBox' ) ) + if (x == null) return new Box(this.attr('viewBox')) // act as setter - return this.attr( 'viewBox', new Box( x, y, width, height ) ) - + return this.attr('viewBox', new Box(x, y, width, height)) } } -} ) +}) diff --git a/src/types/EventTarget.js b/src/types/EventTarget.js index 3d755bf..5a005fd 100644 --- a/src/types/EventTarget.js +++ b/src/types/EventTarget.js @@ -2,79 +2,57 @@ import { dispatch, off, on } from '../modules/core/event.js' import Base from './Base.js' export default class EventTarget extends Base { - - constructor ( { events = {} } = {} ) { - + constructor ({ events = {} } = {}) { super() this.events = events - } addEventListener () {} - dispatch ( event, data ) { - - return dispatch( this, event, data ) - + dispatch (event, data) { + return dispatch(this, event, data) } - dispatchEvent ( event ) { - + dispatchEvent (event) { const bag = this.getEventHolder().events - if ( !bag ) return true + if (!bag) return true const events = bag[event.type] - for ( let i in events ) { - - for ( let j in events[i] ) { - - events[i][j]( event ) - + for (let i in events) { + for (let j in events[i]) { + events[i][j](event) } - } return !event.defaultPrevented - } // Fire given event - fire ( event, data ) { - - this.dispatch( event, data ) + fire (event, data) { + this.dispatch(event, data) return this - } getEventHolder () { - return this - } getEventTarget () { - return this - } // Unbind event from listener - off ( event, listener ) { - - off( this, event, listener ) + off (event, listener) { + off(this, event, listener) return this - } // Bind given event to listener - on ( event, listener, binding, options ) { - - on( this, event, listener, binding, options ) + on (event, listener, binding, options) { + on(this, event, listener, binding, options) return this - } removeEventListener () {} - } diff --git a/src/types/List.js b/src/types/List.js index a2d2226..ccdf11d 100644 --- a/src/types/List.js +++ b/src/types/List.js @@ -1,62 +1,42 @@ import { extend } from '../utils/adopter.js' import { subClassArray } from './ArrayPolyfill.js' -const List = subClassArray( 'List', Array, function ( arr = [] ) { - +const List = subClassArray('List', Array, function (arr = []) { // This catches the case, that native map tries to create an array with new Array(1) - if ( typeof arr === 'number' ) return this + if (typeof arr === 'number') return this this.length = 0 - this.push( ...arr ) - -} ) + this.push(...arr) +}) export default List -extend( List, { - each ( fnOrMethodName, ...args ) { - - if ( typeof fnOrMethodName === 'function' ) { - - this.forEach( ( el ) => { - - fnOrMethodName.call( el, el ) - - } ) - +extend(List, { + each (fnOrMethodName, ...args) { + if (typeof fnOrMethodName === 'function') { + this.forEach((el) => { + fnOrMethodName.call(el, el) + }) } else { - - return this.map( el => { - - return el[fnOrMethodName]( ...args ) - - } ) - + return this.map(el => { + return el[fnOrMethodName](...args) + }) } return this - }, toArray () { - - return Array.prototype.concat.apply( [], this ) - + return Array.prototype.concat.apply([], this) } -} ) - -List.extend = function ( methods ) { - - methods = methods.reduce( ( obj, name ) => { - - obj[name] = function ( ...attrs ) { - - return this.each( name, ...attrs ) +}) +List.extend = function (methods) { + methods = methods.reduce((obj, name) => { + obj[name] = function (...attrs) { + return this.each(name, ...attrs) } return obj + }, {}) - }, {} ) - - extend( List, methods ) - + extend(List, methods) } diff --git a/src/types/Matrix.js b/src/types/Matrix.js index a9a311e..102192b 100644 --- a/src/types/Matrix.js +++ b/src/types/Matrix.js @@ -3,32 +3,26 @@ import { radians } from '../utils/utils.js' import Element from '../elements/Element.js' import Point from './Point.js' -function closeEnough ( a, b, threshold ) { - - return Math.abs( b - a ) < ( threshold || 1e-6 ) - +function closeEnough (a, b, threshold) { + return Math.abs(b - a) < (threshold || 1e-6) } export default class Matrix { - - constructor ( ...args ) { - - this.init( ...args ) - + constructor (...args) { + this.init(...args) } // Initialize - init ( source ) { - - var base = Matrix.fromArray( [ 1, 0, 0, 1, 0, 0 ] ) + init (source) { + var base = Matrix.fromArray([ 1, 0, 0, 1, 0, 0 ]) // ensure source as object source = source instanceof Element ? source.matrixify() - : typeof source === 'string' ? Matrix.fromArray( source.split( delimiter ).map( parseFloat ) ) - : Array.isArray( source ) ? Matrix.fromArray( source ) - : ( typeof source === 'object' && Matrix.isMatrixLike( source ) ) ? source - : ( typeof source === 'object' ) ? new Matrix().transform( source ) - : arguments.length === 6 ? Matrix.fromArray( [].slice.call( arguments ) ) + : typeof source === 'string' ? Matrix.fromArray(source.split(delimiter).map(parseFloat)) + : Array.isArray(source) ? Matrix.fromArray(source) + : (typeof source === 'object' && Matrix.isMatrixLike(source)) ? source + : (typeof source === 'object') ? new Matrix().transform(source) + : arguments.length === 6 ? Matrix.fromArray([].slice.call(arguments)) : base // Merge the source matrix with the base matrix @@ -40,68 +34,56 @@ export default class Matrix { this.f = source.f != null ? source.f : base.f return this - } // Clones this matrix clone () { - - return new Matrix( this ) - + return new Matrix(this) } // Transform a matrix into another matrix by manipulating the space - transform ( o ) { - + transform (o) { // Check if o is a matrix and then left multiply it directly - if ( Matrix.isMatrixLike( o ) ) { - - var matrix = new Matrix( o ) - return matrix.multiplyO( this ) - + if (Matrix.isMatrixLike(o)) { + var matrix = new Matrix(o) + return matrix.multiplyO(this) } // Get the proposed transformations and the current transformations - var t = Matrix.formatTransforms( o ) + var t = Matrix.formatTransforms(o) var current = this - let { x: ox, y: oy } = new Point( t.ox, t.oy ).transform( current ) + let { x: ox, y: oy } = new Point(t.ox, t.oy).transform(current) // 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 ) + .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 ) ) { - - const origin = new Point( ox, oy ).transform( transformer ) + if (isFinite(t.px) || isFinite(t.py)) { + const origin = new Point(ox, oy).transform(transformer) // TODO: Replace t.px with isFinite(t.px) const dx = t.px ? t.px - origin.x : 0 const dy = t.py ? t.py - origin.y : 0 - transformer.translateO( dx, dy ) - + transformer.translateO(dx, dy) } // Translate now after positioning - transformer.translateO( t.tx, t.ty ) + transformer.translateO(t.tx, t.ty) return transformer - } // Applies a matrix defined by its affine parameters - compose ( o ) { - - if ( o.origin ) { - + compose (o) { + if (o.origin) { o.originX = o.origin[0] o.originY = o.origin[1] - } // Get the parameters var ox = o.originX || 0 @@ -115,20 +97,18 @@ export default class Matrix { // Apply the standard matrix var result = new Matrix() - .translateO( -ox, -oy ) - .scaleO( sx, sy ) - .shearO( lam ) - .rotateO( theta ) - .translateO( tx, ty ) - .lmultiplyO( this ) - .translateO( ox, oy ) + .translateO(-ox, -oy) + .scaleO(sx, sy) + .shearO(lam) + .rotateO(theta) + .translateO(tx, ty) + .lmultiplyO(this) + .translateO(ox, oy) return result - } // Decomposes this matrix into its affine parameters - decompose ( cx = 0, cy = 0 ) { - + decompose (cx = 0, cy = 0) { // Get the parameters from the matrix var a = this.a var b = this.b @@ -143,20 +123,20 @@ export default class Matrix { // Since we only shear in x, we can use the x basis to get the x scale // and the rotation of the resulting matrix - var sx = ccw * Math.sqrt( a * a + b * b ) - var thetaRad = Math.atan2( ccw * b, ccw * a ) + var sx = ccw * Math.sqrt(a * a + b * b) + var thetaRad = Math.atan2(ccw * b, ccw * a) var theta = 180 / Math.PI * thetaRad - var ct = Math.cos( thetaRad ) - var st = Math.sin( thetaRad ) + var ct = Math.cos(thetaRad) + var st = Math.sin(thetaRad) // We can then solve the y basis vector simultaneously to get the other // two affine parameters directly from these parameters - var lam = ( a * c + b * d ) / determinant - var sy = ( ( c * sx ) / ( lam * a - b ) ) || ( ( d * sx ) / ( lam * b + a ) ) + var lam = (a * c + b * d) / determinant + var sy = ((c * sx) / (lam * a - b)) || ((d * sx) / (lam * b + a)) // Use the translations - let tx = e - cx + cx * ct * sx + cy * ( lam * ct * sx - st * sy ) - let ty = f - cy + cx * st * sx + cy * ( lam * st * sx + ct * sy ) + let tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy) + let ty = f - cy + cx * st * sx + cy * (lam * st * sx + ct * sy) // Construct the decomposition and return it return { @@ -178,48 +158,38 @@ export default class Matrix { e: this.e, f: this.f } - } // Left multiplies by the given matrix - multiply ( matrix ) { - - return this.clone().multiplyO( matrix ) - + multiply (matrix) { + return this.clone().multiplyO(matrix) } - multiplyO ( matrix ) { - + multiplyO (matrix) { // Get the matrices var l = this var r = matrix instanceof Matrix ? matrix - : new Matrix( matrix ) - - return Matrix.matrixMultiply( l, r, this ) + : new Matrix(matrix) + return Matrix.matrixMultiply(l, r, this) } - lmultiply ( matrix ) { - - return this.clone().lmultiplyO( matrix ) - + lmultiply (matrix) { + return this.clone().lmultiplyO(matrix) } - lmultiplyO ( matrix ) { - + lmultiplyO (matrix) { var r = this var l = matrix instanceof Matrix ? matrix - : new Matrix( matrix ) - - return Matrix.matrixMultiply( l, r, this ) + : new Matrix(matrix) + return Matrix.matrixMultiply(l, r, this) } // Inverses matrix inverseO () { - // Get the current parameters out of the matrix var a = this.a var b = this.b @@ -230,7 +200,7 @@ export default class Matrix { // Invert the 2x2 matrix in the top left var det = a * d - b * c - if ( !det ) throw new Error( 'Cannot invert ' + this ) + if (!det) throw new Error('Cannot invert ' + this) // Calculate the top 2x2 matrix var na = d / det @@ -239,8 +209,8 @@ export default class Matrix { var nd = a / det // Apply the inverted matrix to the top right - var ne = -( na * e + nc * f ) - var nf = -( nb * e + nd * f ) + var ne = -(na * e + nc * f) + var nf = -(nb * e + nd * f) // Construct the inverted matrix this.a = na @@ -251,46 +221,34 @@ export default class Matrix { this.f = nf return this - } inverse () { - return this.clone().inverseO() - } // Translate matrix - translate ( x, y ) { - - return this.clone().translateO( x, y ) - + translate (x, y) { + return this.clone().translateO(x, y) } - translateO ( x, y ) { - + translateO (x, y) { this.e += x || 0 this.f += y || 0 return this - } // Scale matrix - scale ( x, y, cx, cy ) { - - return this.clone().scaleO( ...arguments ) - + scale (x, y, cx, cy) { + return this.clone().scaleO(...arguments) } - scaleO ( x, y = x, cx = 0, cy = 0 ) { - + scaleO (x, y = x, cx = 0, cy = 0) { // Support uniform scaling - if ( arguments.length === 3 ) { - + if (arguments.length === 3) { cy = cx cx = y y = x - } let { a, b, c, d, e, f } = this @@ -303,23 +261,19 @@ export default class Matrix { this.f = f * y - cy * y + cy return this - } // Rotate matrix - rotate ( r, cx, cy ) { - - return this.clone().rotateO( r, cx, cy ) - + rotate (r, cx, cy) { + return this.clone().rotateO(r, cx, cy) } - rotateO ( r, cx = 0, cy = 0 ) { - + rotateO (r, cx = 0, cy = 0) { // Convert degrees to radians - r = radians( r ) + r = radians(r) - let cos = Math.cos( r ) - let sin = Math.sin( r ) + let cos = Math.cos(r) + let sin = Math.sin(r) let { a, b, c, d, e, f } = this @@ -331,33 +285,25 @@ export default class Matrix { this.f = f * cos + e * sin - cx * sin - cy * cos + cy return this - } // Flip matrix on x or y, at a given offset - flip ( axis, around ) { - - return this.clone().flipO( axis, around ) - + flip (axis, around) { + return this.clone().flipO(axis, around) } - flipO ( axis, around ) { - - return axis === 'x' ? this.scaleO( -1, 1, around, 0 ) - : axis === 'y' ? this.scaleO( 1, -1, 0, around ) - : this.scaleO( -1, -1, axis, around || axis ) // Define an x, y flip point - + flipO (axis, around) { + return axis === 'x' ? this.scaleO(-1, 1, around, 0) + : axis === 'y' ? this.scaleO(1, -1, 0, around) + : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point } // Shear matrix - shear ( a, cx, cy ) { - - return this.clone().shearO( a, cx, cy ) - + shear (a, cx, cy) { + return this.clone().shearO(a, cx, cy) } - shearO ( lx, cx = 0, cy = 0 ) { - + shearO (lx, cx = 0, cy = 0) { let { a, b, c, d, e, f } = this this.a = a + b * lx @@ -365,33 +311,27 @@ export default class Matrix { this.e = e + f * lx - cy * lx return this - } // Skew Matrix - skew ( x, y, cx, cy ) { - - return this.clone().skewO( ...arguments ) - + skew (x, y, cx, cy) { + return this.clone().skewO(...arguments) } - skewO ( x, y = x, cx = 0, cy = 0 ) { - + skewO (x, y = x, cx = 0, cy = 0) { // support uniformal skew - if ( arguments.length === 3 ) { - + if (arguments.length === 3) { cy = cx cx = y y = x - } // Convert degrees to radians - x = radians( x ) - y = radians( y ) + x = radians(x) + y = radians(y) - let lx = Math.tan( x ) - let ly = Math.tan( y ) + let lx = Math.tan(x) + let ly = Math.tan(y) let { a, b, c, d, e, f } = this @@ -403,75 +343,55 @@ export default class Matrix { this.f = f + e * ly - cx * ly return this - } // SkewX - skewX ( x, cx, cy ) { - - return this.skew( x, 0, cx, cy ) - + skewX (x, cx, cy) { + return this.skew(x, 0, cx, cy) } - skewXO ( x, cx, cy ) { - - return this.skewO( x, 0, cx, cy ) - + skewXO (x, cx, cy) { + return this.skewO(x, 0, cx, cy) } // SkewY - skewY ( y, cx, cy ) { - - return this.skew( 0, y, cx, cy ) - + skewY (y, cx, cy) { + return this.skew(0, y, cx, cy) } - skewYO ( y, cx, cy ) { - - return this.skewO( 0, y, cx, cy ) - + skewYO (y, cx, cy) { + return this.skewO(0, y, cx, cy) } // Transform around a center point - aroundO ( cx, cy, matrix ) { - + aroundO (cx, cy, matrix) { var dx = cx || 0 var dy = cy || 0 - return this.translateO( -dx, -dy ).lmultiplyO( matrix ).translateO( dx, dy ) - + return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy) } - around ( cx, cy, matrix ) { - - return this.clone().aroundO( cx, cy, matrix ) - + around (cx, cy, matrix) { + return this.clone().aroundO(cx, cy, matrix) } // Check if two matrices are equal - equals ( other ) { - - var comp = new Matrix( other ) - return closeEnough( this.a, comp.a ) && closeEnough( this.b, comp.b ) - && closeEnough( this.c, comp.c ) && closeEnough( this.d, comp.d ) - && closeEnough( this.e, comp.e ) && closeEnough( this.f, comp.f ) - + equals (other) { + var comp = new Matrix(other) + return closeEnough(this.a, comp.a) && closeEnough(this.b, comp.b) + && closeEnough(this.c, comp.c) && closeEnough(this.d, comp.d) + && closeEnough(this.e, comp.e) && closeEnough(this.f, comp.f) } // Convert matrix to string toString () { - return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')' - } toArray () { - return [ this.a, this.b, this.c, this.d, this.e, this.f ] - } valueOf () { - return { a: this.a, b: this.b, @@ -480,17 +400,13 @@ export default class Matrix { e: this.e, f: this.f } - } - static fromArray ( a ) { - + static fromArray (a) { return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] } - } - static isMatrixLike ( o ) { - + static isMatrixLike (o) { return ( o.a != null || o.b != null @@ -499,43 +415,41 @@ export default class Matrix { || o.e != null || o.f != null ) - } - static formatTransforms ( o ) { - + static formatTransforms (o) { // Get all of the parameters required to form the matrix var flipBoth = o.flip === 'both' || o.flip === true - var flipX = o.flip && ( flipBoth || o.flip === 'x' ) ? -1 : 1 - var flipY = o.flip && ( flipBoth || o.flip === 'y' ) ? -1 : 1 + var flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1 + var flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1 var skewX = o.skew && o.skew.length ? o.skew[0] - : isFinite( o.skew ) ? o.skew - : isFinite( o.skewX ) ? o.skewX + : isFinite(o.skew) ? o.skew + : isFinite(o.skewX) ? o.skewX : 0 var skewY = o.skew && o.skew.length ? o.skew[1] - : isFinite( o.skew ) ? o.skew - : isFinite( o.skewY ) ? o.skewY + : isFinite(o.skew) ? o.skew + : isFinite(o.skewY) ? o.skewY : 0 var scaleX = o.scale && o.scale.length ? o.scale[0] * flipX - : isFinite( o.scale ) ? o.scale * flipX - : isFinite( o.scaleX ) ? o.scaleX * flipX + : isFinite(o.scale) ? o.scale * flipX + : isFinite(o.scaleX) ? o.scaleX * flipX : flipX var scaleY = o.scale && o.scale.length ? o.scale[1] * flipY - : isFinite( o.scale ) ? o.scale * flipY - : isFinite( o.scaleY ) ? o.scaleY * flipY + : isFinite(o.scale) ? o.scale * flipY + : isFinite(o.scaleY) ? o.scaleY * flipY : flipY var shear = o.shear || 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(o.origin || o.around || o.ox || o.originX, o.oy || o.originY) var ox = origin.x var oy = origin.y - var position = new Point( o.position || o.px || o.positionX, o.py || o.positionY ) + var position = new Point(o.position || o.px || o.positionX, o.py || o.positionY) var px = position.x var py = position.y - var translate = new Point( o.translate || o.tx || o.translateX, o.ty || o.translateY ) + var translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY) var tx = translate.x var ty = translate.y - var relative = new Point( o.relative || o.rx || o.relativeX, o.ry || o.relativeY ) + var relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY) var rx = relative.x var ry = relative.y @@ -543,12 +457,10 @@ export default class Matrix { return { scaleX, scaleY, skewX, skewY, shear, theta, rx, ry, tx, ty, ox, oy, px, py } - } // left matrix, right matrix, target matrix which is overwritten - static matrixMultiply ( l, r, o ) { - + static matrixMultiply (l, r, o) { // Work out the product directly var a = l.a * r.a + l.c * r.b var b = l.b * r.a + l.d * r.b @@ -566,31 +478,23 @@ export default class Matrix { o.f = f return o - } - } export function ctm () { - - return new Matrix( this.node.getCTM() ) - + return new Matrix(this.node.getCTM()) } export function screenCTM () { - /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 This is needed because FF does not return the transformation matrix for the inner coordinate system when getScreenCTM() is called on nested svgs. However all other Browsers do that */ - if ( typeof this.isRoot === 'function' && !this.isRoot() ) { - - var rect = this.rect( 1, 1 ) + if (typeof this.isRoot === 'function' && !this.isRoot()) { + var rect = this.rect(1, 1) var m = rect.node.getScreenCTM() rect.remove() - return new Matrix( m ) - + return new Matrix(m) } - return new Matrix( this.node.getScreenCTM() ) - + return new Matrix(this.node.getScreenCTM()) } diff --git a/src/types/Morphable.js b/src/types/Morphable.js index 87fa800..240215b 100644 --- a/src/types/Morphable.js +++ b/src/types/Morphable.js @@ -11,200 +11,135 @@ import SVGArray from './SVGArray.js' import SVGNumber from './SVGNumber.js' export default class Morphable { - - constructor ( stepper ) { - - this._stepper = stepper || new Ease( '-' ) + constructor (stepper) { + this._stepper = stepper || new Ease('-') this._from = null this._to = null this._type = null this._context = null this._morphObj = null - } - from ( val ) { - - if ( val == null ) { - + from (val) { + if (val == null) { return this._from - } - this._from = this._set( val ) + this._from = this._set(val) return this - } - to ( val ) { - - if ( val == null ) { - + to (val) { + if (val == null) { return this._to - } - this._to = this._set( val ) + this._to = this._set(val) return this - } - type ( type ) { - + type (type) { // getter - if ( type == null ) { - + if (type == null) { return this._type - } // setter this._type = type return this - } - _set ( value ) { - - if ( !this._type ) { - + _set (value) { + if (!this._type) { var type = typeof value - if ( type === 'number' ) { - - this.type( SVGNumber ) - - } else if ( type === 'string' ) { - - if ( Color.isColor( value ) ) { - - this.type( Color ) - - } else if ( delimiter.test( value ) ) { - - this.type( pathLetters.test( value ) + if (type === 'number') { + this.type(SVGNumber) + } else if (type === 'string') { + if (Color.isColor(value)) { + this.type(Color) + } else if (delimiter.test(value)) { + this.type(pathLetters.test(value) ? PathArray : SVGArray ) - - } else if ( numberAndUnit.test( value ) ) { - - this.type( SVGNumber ) - + } else if (numberAndUnit.test(value)) { + this.type(SVGNumber) } else { - - this.type( NonMorphable ) - + this.type(NonMorphable) } - - } else if ( morphableTypes.indexOf( value.constructor ) > -1 ) { - - this.type( value.constructor ) - - } else if ( Array.isArray( value ) ) { - - this.type( SVGArray ) - - } else if ( type === 'object' ) { - - this.type( ObjectBag ) - + } else if (morphableTypes.indexOf(value.constructor) > -1) { + this.type(value.constructor) + } else if (Array.isArray(value)) { + this.type(SVGArray) + } else if (type === 'object') { + this.type(ObjectBag) } else { - - this.type( NonMorphable ) - + this.type(NonMorphable) } - } - var result = ( new this._type( value ) ).toArray() + var result = (new this._type(value)).toArray() this._morphObj = this._morphObj || new this._type() this._context = this._context - || Array.apply( null, Array( result.length ) ).map( Object ) + || Array.apply(null, Array(result.length)).map(Object) return result - } - stepper ( stepper ) { - - if ( stepper == null ) return this._stepper + stepper (stepper) { + if (stepper == null) return this._stepper this._stepper = stepper return this - } done () { - var complete = this._context - .map( this._stepper.done ) - .reduce( function ( last, curr ) { - + .map(this._stepper.done) + .reduce(function (last, curr) { return last && curr - - }, true ) + }, true) return complete - } - at ( pos ) { - + at (pos) { var _this = this return this._morphObj.fromArray( - this._from.map( function ( i, index ) { - - return _this._stepper.step( i, _this._to[index], pos, _this._context[index], _this._context ) - - } ) + this._from.map(function (i, index) { + return _this._stepper.step(i, _this._to[index], pos, _this._context[index], _this._context) + }) ) - } - } export class NonMorphable { - - constructor ( ...args ) { - - this.init( ...args ) - + constructor (...args) { + this.init(...args) } - init ( val ) { - - val = Array.isArray( val ) ? val[0] : val + init (val) { + val = Array.isArray(val) ? val[0] : val this.value = val return this - } valueOf () { - return this.value - } toArray () { - return [ this.value ] - } - } export class TransformBag { - - constructor ( ...args ) { - - this.init( ...args ) - + constructor (...args) { + this.init(...args) } - init ( obj ) { - - if ( Array.isArray( obj ) ) { - + init (obj) { + if (Array.isArray(obj)) { obj = { scaleX: obj[0], scaleY: obj[1], @@ -215,16 +150,13 @@ export class TransformBag { originX: obj[6], originY: obj[7] } - } - Object.assign( this, TransformBag.defaults, obj ) + Object.assign(this, TransformBag.defaults, obj) return this - } toArray () { - var v = this return [ @@ -237,9 +169,7 @@ export class TransformBag { v.originX, v.originY ] - } - } TransformBag.defaults = { @@ -254,56 +184,40 @@ TransformBag.defaults = { } export class ObjectBag { - - constructor ( ...args ) { - - this.init( ...args ) - + constructor (...args) { + this.init(...args) } - init ( objOrArr ) { - + init (objOrArr) { this.values = [] - if ( Array.isArray( objOrArr ) ) { - + if (Array.isArray(objOrArr)) { this.values = objOrArr return - } - var entries = Object.entries( objOrArr || {} ).sort( ( a, b ) => { - + var entries = Object.entries(objOrArr || {}).sort((a, b) => { return a[0] - b[0] + }) - } ) - - this.values = entries.reduce( ( last, curr ) => last.concat( curr ), [] ) + this.values = entries.reduce((last, curr) => last.concat(curr), []) return this - } valueOf () { - var obj = {} var arr = this.values - for ( var i = 0, len = arr.length; i < len; i += 2 ) { - + for (var i = 0, len = arr.length; i < len; i += 2) { obj[arr[i]] = arr[i + 1] - } return obj - } toArray () { - return this.values - } - } const morphableTypes = [ @@ -312,29 +226,21 @@ const morphableTypes = [ ObjectBag ] -export function registerMorphableType ( type = [] ) { - - morphableTypes.push( ...[].concat( type ) ) - +export function registerMorphableType (type = []) { + morphableTypes.push(...[].concat(type)) } export function makeMorphable () { - - extend( morphableTypes, { - to ( val ) { - + extend(morphableTypes, { + to (val) { return new Morphable() - .type( this.constructor ) - .from( this.valueOf() ) - .to( val ) - + .type(this.constructor) + .from(this.valueOf()) + .to(val) }, - fromArray ( arr ) { - - this.init( arr ) + fromArray (arr) { + this.init(arr) return this - } - } ) - + }) } diff --git a/src/types/PathArray.js b/src/types/PathArray.js index 739218d..764d05c 100644 --- a/src/types/PathArray.js +++ b/src/types/PathArray.js @@ -12,182 +12,131 @@ import Point from './Point.js' import SVGArray from './SVGArray.js' import parser from '../modules/core/parser.js' -const PathArray = subClassArray( 'PathArray', SVGArray ) +const PathArray = subClassArray('PathArray', SVGArray) export default PathArray -export function pathRegReplace ( a, b, c, d ) { - - return c + d.replace( dots, ' .' ) - +export function pathRegReplace (a, b, c, d) { + return c + d.replace(dots, ' .') } -function arrayToString ( a ) { - - for ( var i = 0, il = a.length, s = ''; i < il; i++ ) { - +function arrayToString (a) { + for (var i = 0, il = a.length, s = ''; i < il; i++) { s += a[i][0] - if ( a[i][1] != null ) { - + if (a[i][1] != null) { s += a[i][1] - if ( a[i][2] != null ) { - + if (a[i][2] != null) { s += ' ' s += a[i][2] - if ( a[i][3] != null ) { - + if (a[i][3] != null) { s += ' ' s += a[i][3] s += ' ' s += a[i][4] - if ( a[i][5] != null ) { - + if (a[i][5] != null) { s += ' ' s += a[i][5] s += ' ' s += a[i][6] - if ( a[i][7] != null ) { - + if (a[i][7] != null) { s += ' ' s += a[i][7] - } - } - } - } - } - } return s + ' ' - } const pathHandlers = { - M: function ( c, p, p0 ) { - + M: function (c, p, p0) { p.x = p0.x = c[0] p.y = p0.y = c[1] return [ 'M', p.x, p.y ] - }, - L: function ( c, p ) { - + L: function (c, p) { p.x = c[0] p.y = c[1] return [ 'L', c[0], c[1] ] - }, - H: function ( c, p ) { - + H: function (c, p) { p.x = c[0] return [ 'H', c[0] ] - }, - V: function ( c, p ) { - + V: function (c, p) { p.y = c[0] return [ 'V', c[0] ] - }, - C: function ( c, p ) { - + C: function (c, p) { p.x = c[4] p.y = c[5] return [ 'C', c[0], c[1], c[2], c[3], c[4], c[5] ] - }, - S: function ( c, p ) { - + S: function (c, p) { p.x = c[2] p.y = c[3] return [ 'S', c[0], c[1], c[2], c[3] ] - }, - Q: function ( c, p ) { - + Q: function (c, p) { p.x = c[2] p.y = c[3] return [ 'Q', c[0], c[1], c[2], c[3] ] - }, - T: function ( c, p ) { - + T: function (c, p) { p.x = c[0] p.y = c[1] return [ 'T', c[0], c[1] ] - }, - Z: function ( c, p, p0 ) { - + Z: function (c, p, p0) { p.x = p0.x p.y = p0.y return [ 'Z' ] - }, - A: function ( c, p ) { - + A: function (c, p) { p.x = c[5] p.y = c[6] return [ 'A', c[0], c[1], c[2], c[3], c[4], c[5], c[6] ] - } } -let mlhvqtcsaz = 'mlhvqtcsaz'.split( '' ) - -for ( var i = 0, il = mlhvqtcsaz.length; i < il; ++i ) { - - pathHandlers[mlhvqtcsaz[i]] = ( function ( i ) { - - return function ( c, p, p0 ) { - - if ( i === 'H' ) c[0] = c[0] + p.x - else if ( i === 'V' ) c[0] = c[0] + p.y - else if ( i === 'A' ) { +let mlhvqtcsaz = 'mlhvqtcsaz'.split('') +for (var i = 0, il = mlhvqtcsaz.length; i < il; ++i) { + pathHandlers[mlhvqtcsaz[i]] = (function (i) { + return function (c, p, p0) { + if (i === 'H') c[0] = c[0] + p.x + else if (i === 'V') c[0] = c[0] + p.y + else if (i === 'A') { c[5] = c[5] + p.x c[6] = c[6] + p.y - } else { - - for ( var j = 0, jl = c.length; j < jl; ++j ) { - - c[j] = c[j] + ( j % 2 ? p.y : p.x ) - + for (var j = 0, jl = c.length; j < jl; ++j) { + c[j] = c[j] + (j % 2 ? p.y : p.x) } - } - return pathHandlers[i]( c, p, p0 ) - + return pathHandlers[i](c, p, p0) } - - } )( mlhvqtcsaz[i].toUpperCase() ) - + })(mlhvqtcsaz[i].toUpperCase()) } -extend( PathArray, { +extend(PathArray, { // Convert array to string toString () { - - return arrayToString( this ) - + return arrayToString(this) }, // Move path string - move ( x, y ) { - + move (x, y) { // get bounding box of current situation var box = this.bbox() @@ -195,154 +144,110 @@ extend( PathArray, { x -= box.x y -= box.y - if ( !isNaN( x ) && !isNaN( y ) ) { - + if (!isNaN(x) && !isNaN(y)) { // move every point - for ( var l, i = this.length - 1; i >= 0; i-- ) { - + for (var l, i = this.length - 1; i >= 0; i--) { l = this[i][0] - if ( l === 'M' || l === 'L' || l === 'T' ) { - + if (l === 'M' || l === 'L' || l === 'T') { this[i][1] += x this[i][2] += y - - } else if ( l === 'H' ) { - + } else if (l === 'H') { this[i][1] += x - - } else if ( l === 'V' ) { - + } else if (l === 'V') { this[i][1] += y - - } else if ( l === 'C' || l === 'S' || l === 'Q' ) { - + } else if (l === 'C' || l === 'S' || l === 'Q') { this[i][1] += x this[i][2] += y this[i][3] += x this[i][4] += y - if ( l === 'C' ) { - + if (l === 'C') { this[i][5] += x this[i][6] += y - } - - } else if ( l === 'A' ) { - + } else if (l === 'A') { this[i][6] += x this[i][7] += y - } - } - } return this - }, // Resize path string - size ( width, height ) { - + size (width, height) { // get bounding box of current situation var box = this.bbox() var i, l // recalculate position of all points according to new size - for ( i = this.length - 1; i >= 0; i-- ) { - + for (i = this.length - 1; i >= 0; i--) { l = this[i][0] - if ( l === 'M' || l === 'L' || l === 'T' ) { - - this[i][1] = ( ( this[i][1] - box.x ) * width ) / box.width + box.x - this[i][2] = ( ( this[i][2] - box.y ) * height ) / box.height + box.y - - } else if ( l === 'H' ) { - - this[i][1] = ( ( this[i][1] - box.x ) * width ) / box.width + box.x - - } else if ( l === 'V' ) { - - this[i][1] = ( ( this[i][1] - box.y ) * height ) / box.height + box.y - - } else if ( l === 'C' || l === 'S' || l === 'Q' ) { - - this[i][1] = ( ( this[i][1] - box.x ) * width ) / box.width + box.x - this[i][2] = ( ( this[i][2] - box.y ) * height ) / box.height + box.y - this[i][3] = ( ( this[i][3] - box.x ) * width ) / box.width + box.x - this[i][4] = ( ( this[i][4] - box.y ) * height ) / box.height + box.y - - if ( l === 'C' ) { - - this[i][5] = ( ( this[i][5] - box.x ) * width ) / box.width + box.x - this[i][6] = ( ( this[i][6] - box.y ) * height ) / box.height + box.y - + if (l === 'M' || l === 'L' || l === 'T') { + this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x + this[i][2] = ((this[i][2] - box.y) * height) / box.height + box.y + } else if (l === 'H') { + this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x + } else if (l === 'V') { + this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y + } else if (l === 'C' || l === 'S' || l === 'Q') { + this[i][1] = ((this[i][1] - box.x) * width) / box.width + box.x + this[i][2] = ((this[i][2] - box.y) * height) / box.height + box.y + this[i][3] = ((this[i][3] - box.x) * width) / box.width + box.x + this[i][4] = ((this[i][4] - box.y) * height) / box.height + box.y + + if (l === 'C') { + this[i][5] = ((this[i][5] - box.x) * width) / box.width + box.x + this[i][6] = ((this[i][6] - box.y) * height) / box.height + box.y } - - } else if ( l === 'A' ) { - + } else if (l === 'A') { // resize radii - this[i][1] = ( this[i][1] * width ) / box.width - this[i][2] = ( this[i][2] * height ) / box.height + this[i][1] = (this[i][1] * width) / box.width + this[i][2] = (this[i][2] * height) / box.height // move position values - this[i][6] = ( ( this[i][6] - box.x ) * width ) / box.width + box.x - this[i][7] = ( ( this[i][7] - box.y ) * height ) / box.height + box.y - + this[i][6] = ((this[i][6] - box.x) * width) / box.width + box.x + this[i][7] = ((this[i][7] - box.y) * height) / box.height + box.y } - } return this - }, // Test if the passed path array use the same path data commands as this path array - equalCommands ( pathArray ) { - + equalCommands (pathArray) { var i, il, equalCommands - pathArray = new PathArray( pathArray ) + pathArray = new PathArray(pathArray) equalCommands = this.length === pathArray.length - for ( i = 0, il = this.length; equalCommands && i < il; i++ ) { - + for (i = 0, il = this.length; equalCommands && i < il; i++) { equalCommands = this[i][0] === pathArray[i][0] - } return equalCommands - }, // Make path array morphable - morph ( pathArray ) { - - pathArray = new PathArray( pathArray ) - - if ( this.equalCommands( pathArray ) ) { + morph (pathArray) { + pathArray = new PathArray(pathArray) + if (this.equalCommands(pathArray)) { this.destination = pathArray - } else { - this.destination = null - } return this - }, // Get morphed path array at given position - at ( pos ) { - + at (pos) { // make sure a destination is defined - if ( !this.destination ) return this + if (!this.destination) return this var sourceArray = this var destinationArray = this.destination.value @@ -352,61 +257,47 @@ extend( PathArray, { // Animate has specified in the SVG spec // See: https://www.w3.org/TR/SVG11/paths.html#PathElement - for ( i = 0, il = sourceArray.length; i < il; i++ ) { - + for (i = 0, il = sourceArray.length; i < il; i++) { array[i] = [ sourceArray[i][0] ] - for ( j = 1, jl = sourceArray[i].length; j < jl; j++ ) { - - array[i][j] = sourceArray[i][j] + ( destinationArray[i][j] - sourceArray[i][j] ) * pos - + for (j = 1, jl = sourceArray[i].length; j < jl; j++) { + array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos } // For the two flags of the elliptical arc command, the SVG spec say: // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true // Elliptical arc command as an array followed by corresponding indexes: // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] // 0 1 2 3 4 5 6 7 - if ( array[i][0] === 'A' ) { - - array[i][4] = +( array[i][4] !== 0 ) - array[i][5] = +( array[i][5] !== 0 ) - + if (array[i][0] === 'A') { + array[i][4] = +(array[i][4] !== 0) + array[i][5] = +(array[i][5] !== 0) } - } // Directly modify the value of a path array, this is done this way for performance pathArray.value = array return pathArray - }, // Absolutize and parse path to array - parse ( array = [ [ 'M', 0, 0 ] ] ) { - + parse (array = [ [ 'M', 0, 0 ] ]) { // if it's already a patharray, no need to parse it - if ( array instanceof PathArray ) return array + if (array instanceof PathArray) return array // prepare for parsing var s var paramCnt = { 'M': 2, 'L': 2, 'H': 1, 'V': 1, 'C': 6, 'S': 4, 'Q': 4, 'T': 2, 'A': 7, 'Z': 0 } - if ( typeof array === 'string' ) { - + if (typeof array === 'string') { array = array - .replace( numbersWithDots, pathRegReplace ) // convert 45.123.123 to 45.123 .123 - .replace( pathLetters, ' $& ' ) // put some room between letters and numbers - .replace( hyphen, '$1 -' ) // add space before hyphen + .replace(numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 + .replace(pathLetters, ' $& ') // put some room between letters and numbers + .replace(hyphen, '$1 -') // add space before hyphen .trim() // trim - .split( delimiter ) // split into array - + .split(delimiter) // split into array } else { - - array = array.reduce( function ( prev, curr ) { - - return [].concat.call( prev, curr ) - - }, [] ) - + array = array.reduce(function (prev, curr) { + return [].concat.call(prev, curr) + }, []) } // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] @@ -417,41 +308,30 @@ extend( PathArray, { var len = array.length do { - // Test if we have a path letter - if ( isPathLetter.test( array[index] ) ) { - + if (isPathLetter.test(array[index])) { s = array[index] ++index // If last letter was a move command and we got no new, it defaults to [L]ine - - } else if ( s === 'M' ) { - + } else if (s === 'M') { s = 'L' - - } else if ( s === 'm' ) { - + } else if (s === 'm') { s = 'l' - } - result.push( pathHandlers[s].call( null, - array.slice( index, ( index = index + paramCnt[s.toUpperCase()] ) ).map( parseFloat ), + result.push(pathHandlers[s].call(null, + array.slice(index, (index = index + paramCnt[s.toUpperCase()])).map(parseFloat), p, p0 ) ) - - } while ( len > index ) + } while (len > index) return result - }, // Get bounding box of path bbox () { - - parser().path.setAttribute( 'd', this.toString() ) + parser().path.setAttribute('d', this.toString()) return parser.nodes.path.getBBox() - } -} ) +}) diff --git a/src/types/Point.js b/src/types/Point.js index 16ae44d..f1c85a1 100644 --- a/src/types/Point.js +++ b/src/types/Point.js @@ -1,19 +1,15 @@ export default class Point { - // Initialize - constructor ( ...args ) { - - this.init( ...args ) - + constructor (...args) { + this.init(...args) } - init ( x, y ) { - + init (x, y) { let source let base = { x: 0, y: 0 } // ensure source as object - source = Array.isArray( x ) ? { x: x[0], y: x[1] } + source = Array.isArray(x) ? { x: x[0], y: x[1] } : typeof x === 'object' ? { x: x.x, y: x.y } : { x: x, y: y } @@ -22,38 +18,28 @@ export default class Point { this.y = source.y == null ? base.y : source.y return this - } // Clone point clone () { - - return new Point( this ) - + return new Point(this) } // transform point with matrix - transform ( m ) { - + transform (m) { // Perform the matrix multiplication var x = m.a * this.x + m.c * this.y + m.e var y = m.b * this.x + m.d * this.y + m.f // Return the required point - return new Point( x, y ) - + return new Point(x, y) } toArray () { - return [ this.x, this.y ] - } - } -export function point ( x, y ) { - - return new Point( x, y ).transform( this.screenCTM().inverse() ) - +export function point (x, y) { + return new Point(x, y).transform(this.screenCTM().inverse()) } diff --git a/src/types/PointArray.js b/src/types/PointArray.js index 581b7dc..9e7406d 100644 --- a/src/types/PointArray.js +++ b/src/types/PointArray.js @@ -3,97 +3,76 @@ import { extend } from '../utils/adopter.js' import { subClassArray } from './ArrayPolyfill.js' import SVGArray from './SVGArray.js' -const PointArray = subClassArray( 'PointArray', SVGArray ) +const PointArray = subClassArray('PointArray', SVGArray) export default PointArray -extend( PointArray, { +extend(PointArray, { // Convert array to string toString () { - // convert to a poly point string - for ( var i = 0, il = this.length, array = []; i < il; i++ ) { - - array.push( this[i].join( ',' ) ) - + for (var i = 0, il = this.length, array = []; i < il; i++) { + array.push(this[i].join(',')) } - return array.join( ' ' ) - + return array.join(' ') }, // Convert array to line object toLine () { - return { x1: this[0][0], y1: this[0][1], x2: this[1][0], y2: this[1][1] } - }, // Get morphed array at given position - at ( pos ) { - + at (pos) { // make sure a destination is defined - if ( !this.destination ) return this + if (!this.destination) return this // generate morphed point string - for ( var i = 0, il = this.length, array = []; i < il; i++ ) { - - array.push( [ - this[i][0] + ( this.destination[i][0] - this[i][0] ) * pos, - this[i][1] + ( this.destination[i][1] - this[i][1] ) * pos - ] ) - + for (var i = 0, il = this.length, array = []; i < il; i++) { + array.push([ + this[i][0] + (this.destination[i][0] - this[i][0]) * pos, + this[i][1] + (this.destination[i][1] - this[i][1]) * pos + ]) } - return new PointArray( array ) - + return new PointArray(array) }, // Parse point string and flat array - parse ( array = [ [ 0, 0 ] ] ) { - + parse (array = [ [ 0, 0 ] ]) { var points = [] // if it is an array - if ( array instanceof Array ) { - + if (array instanceof Array) { // and it is not flat, there is no need to parse it - if ( array[0] instanceof Array ) { - + if (array[0] instanceof Array) { return array - } - } else { // Else, it is considered as a string - // parse points - array = array.trim().split( delimiter ).map( parseFloat ) - + array = array.trim().split(delimiter).map(parseFloat) } // validate points - https://svgwg.org/svg2-draft/shapes.html#DataTypePoints // Odd number of coordinates is an error. In such cases, drop the last odd coordinate. - if ( array.length % 2 !== 0 ) array.pop() + if (array.length % 2 !== 0) array.pop() // wrap points in two-tuples and parse points as floats - for ( var i = 0, len = array.length; i < len; i = i + 2 ) { - - points.push( [ array[i], array[i + 1] ] ) - + for (var i = 0, len = array.length; i < len; i = i + 2) { + points.push([ array[i], array[i + 1] ]) } return points - }, // Move point string - move ( x, y ) { - + move (x, y) { var box = this.bbox() // get relative offset @@ -101,54 +80,41 @@ extend( PointArray, { y -= box.y // move every point - if ( !isNaN( x ) && !isNaN( y ) ) { - - for ( var i = this.length - 1; i >= 0; i-- ) { - + if (!isNaN(x) && !isNaN(y)) { + for (var i = this.length - 1; i >= 0; i--) { this[i] = [ this[i][0] + x, this[i][1] + y ] - } - } return this - }, // Resize poly string - size ( width, height ) { - + size (width, height) { var i var box = this.bbox() // recalculate position of all points according to new size - for ( i = this.length - 1; i >= 0; i-- ) { - - if ( box.width ) this[i][0] = ( ( this[i][0] - box.x ) * width ) / box.width + box.x - if ( box.height ) this[i][1] = ( ( this[i][1] - box.y ) * height ) / box.height + box.y - + for (i = this.length - 1; i >= 0; i--) { + if (box.width) this[i][0] = ((this[i][0] - box.x) * width) / box.width + box.x + if (box.height) this[i][1] = ((this[i][1] - box.y) * height) / box.height + box.y } return this - }, // Get bounding box of points bbox () { - var maxX = -Infinity var maxY = -Infinity var minX = Infinity var minY = Infinity - this.forEach( function ( el ) { - - maxX = Math.max( el[0], maxX ) - maxY = Math.max( el[1], maxY ) - minX = Math.min( el[0], minX ) - minY = Math.min( el[1], minY ) - - } ) + this.forEach(function (el) { + maxX = Math.max(el[0], maxX) + maxY = Math.max(el[1], maxY) + minX = Math.min(el[0], minX) + minY = Math.min(el[1], minY) + }) return { x: minX, y: minY, width: maxX - minX, height: maxY - minY } - } -} ) +}) diff --git a/src/types/SVGArray.js b/src/types/SVGArray.js index 7d59af1..7f27ec4 100644 --- a/src/types/SVGArray.js +++ b/src/types/SVGArray.js @@ -2,65 +2,49 @@ import { delimiter } from '../modules/core/regex.js' import { extend } from '../utils/adopter.js' import { subClassArray } from './ArrayPolyfill.js' -const SVGArray = subClassArray( 'SVGArray', Array, function ( arr ) { - - this.init( arr ) - -} ) +const SVGArray = subClassArray('SVGArray', Array, function (arr) { + this.init(arr) +}) export default SVGArray -extend( SVGArray, { - init ( arr ) { - +extend(SVGArray, { + init (arr) { // This catches the case, that native map tries to create an array with new Array(1) - if ( typeof arr === 'number' ) return this + if (typeof arr === 'number') return this this.length = 0 - this.push( ...this.parse( arr ) ) + this.push(...this.parse(arr)) return this - }, toArray () { - - return Array.prototype.concat.apply( [], this ) - + return Array.prototype.concat.apply([], this) }, toString () { - - return this.join( ' ' ) - + return this.join(' ') }, // Flattens the array if needed valueOf () { - const ret = [] - ret.push( ...this ) + ret.push(...this) return ret - }, // Parse whitespace separated string - parse ( array = [] ) { - + parse (array = []) { // If already is an array, no need to parse it - if ( array instanceof Array ) return array - - return array.trim().split( delimiter ).map( parseFloat ) + if (array instanceof Array) return array + return array.trim().split(delimiter).map(parseFloat) }, clone () { - - return new this.constructor( this ) - + return new this.constructor(this) }, toSet () { - - return new Set( this ) - + return new Set(this) } -} ) +}) diff --git a/src/types/SVGNumber.js b/src/types/SVGNumber.js index a35ed66..a152667 100644 --- a/src/types/SVGNumber.js +++ b/src/types/SVGNumber.js @@ -2,126 +2,90 @@ import { numberAndUnit } from '../modules/core/regex.js' // Module for unit convertions export default class SVGNumber { - // Initialize - constructor ( ...args ) { - - this.init( ...args ) - + constructor (...args) { + this.init(...args) } - init ( value, unit ) { - - unit = Array.isArray( value ) ? value[1] : unit - value = Array.isArray( value ) ? value[0] : value + init (value, unit) { + unit = Array.isArray(value) ? value[1] : unit + value = Array.isArray(value) ? value[0] : value // initialize defaults this.value = 0 this.unit = unit || '' // parse value - if ( typeof value === 'number' ) { - + if (typeof value === 'number') { // ensure a valid numeric value - this.value = isNaN( value ) ? 0 : !isFinite( value ) ? ( value < 0 ? -3.4e+38 : +3.4e+38 ) : value - - } else if ( typeof value === 'string' ) { - - unit = value.match( numberAndUnit ) - - if ( unit ) { + this.value = isNaN(value) ? 0 : !isFinite(value) ? (value < 0 ? -3.4e+38 : +3.4e+38) : value + } else if (typeof value === 'string') { + unit = value.match(numberAndUnit) + if (unit) { // make value numeric - this.value = parseFloat( unit[1] ) + this.value = parseFloat(unit[1]) // normalize - if ( unit[5] === '%' ) { - + if (unit[5] === '%') { this.value /= 100 - - } else if ( unit[5] === 's' ) { - + } else if (unit[5] === 's') { this.value *= 1000 - } // store unit this.unit = unit[5] - } - } else { - - if ( value instanceof SVGNumber ) { - + if (value instanceof SVGNumber) { this.value = value.valueOf() this.unit = value.unit - } - } return this - } toString () { - - return ( this.unit === '%' ? ~~( this.value * 1e8 ) / 1e6 + return (this.unit === '%' ? ~~(this.value * 1e8) / 1e6 : this.unit === 's' ? this.value / 1e3 : this.value ) + this.unit - } toJSON () { - return this.toString() - } toArray () { - return [ this.value, this.unit ] - } valueOf () { - return this.value - } // Add number - plus ( number ) { - - number = new SVGNumber( number ) - return new SVGNumber( this + number, this.unit || number.unit ) - + plus (number) { + number = new SVGNumber(number) + return new SVGNumber(this + number, this.unit || number.unit) } // Subtract number - minus ( number ) { - - number = new SVGNumber( number ) - return new SVGNumber( this - number, this.unit || number.unit ) - + minus (number) { + number = new SVGNumber(number) + return new SVGNumber(this - number, this.unit || number.unit) } // Multiply number - times ( number ) { - - number = new SVGNumber( number ) - return new SVGNumber( this * number, this.unit || number.unit ) - + times (number) { + number = new SVGNumber(number) + return new SVGNumber(this * number, this.unit || number.unit) } // Divide number - divide ( number ) { - - number = new SVGNumber( number ) - return new SVGNumber( this / number, this.unit || number.unit ) - + divide (number) { + number = new SVGNumber(number) + return new SVGNumber(this / number, this.unit || number.unit) } - } diff --git a/src/utils/adopter.js b/src/utils/adopter.js index 6e526e3..ec6b2e5 100644 --- a/src/utils/adopter.js +++ b/src/utils/adopter.js @@ -5,190 +5,136 @@ import { globals } from '../utils/window.js' import Base from '../types/Base.js' const elements = {} -export const root = Symbol( 'root' ) +export const root = Symbol('root') // Method for element creation -export function makeNode ( name ) { - +export function makeNode (name) { // create element - return globals.document.createElementNS( ns, name ) - + return globals.document.createElementNS(ns, name) } -export function makeInstance ( element ) { - - if ( element instanceof Base ) return element - - if ( typeof element === 'object' ) { - - return adopt( element ) +export function makeInstance (element) { + if (element instanceof Base) return element + if (typeof element === 'object') { + return adopt(element) } - if ( element == null ) { - + if (element == null) { return new elements[root]() - } - if ( typeof element === 'string' && element.charAt( 0 ) !== '<' ) { - - return adopt( globals.document.querySelector( element ) ) - + if (typeof element === 'string' && element.charAt(0) !== '<') { + return adopt(globals.document.querySelector(element)) } - var node = makeNode( 'svg' ) + var node = makeNode('svg') node.innerHTML = element // We can use firstChild here because we know, // that the first char is < and thus an element - element = adopt( node.firstChild ) + element = adopt(node.firstChild) return element - } -export function nodeOrNew ( name, node ) { - - return node instanceof globals.window.Node ? node : makeNode( name ) - +export function nodeOrNew (name, node) { + return node instanceof globals.window.Node ? node : makeNode(name) } // Adopt existing svg elements -export function adopt ( node ) { - +export function adopt (node) { // check for presence of node - if ( !node ) return null + if (!node) return null // make sure a node isn't already adopted - if ( node.instance instanceof Base ) return node.instance - - if ( !( node instanceof globals.window.SVGElement ) ) { - - return new elements.HtmlNode( node ) + if (node.instance instanceof Base) return node.instance + if (!(node instanceof globals.window.SVGElement)) { + return new elements.HtmlNode(node) } // initialize variables var element // adopt with element-specific settings - if ( node.nodeName === 'svg' ) { - - element = new elements[root]( node ) - - } else if ( node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient' ) { - - element = new elements.Gradient( node ) - - } else if ( elements[capitalize( node.nodeName )] ) { - - element = new elements[capitalize( node.nodeName )]( node ) - + if (node.nodeName === 'svg') { + element = new elements[root](node) + } else if (node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient') { + element = new elements.Gradient(node) + } else if (elements[capitalize(node.nodeName)]) { + element = new elements[capitalize(node.nodeName)](node) } else { - - element = new elements.Bare( node ) - + element = new elements.Bare(node) } return element - } -export function register ( element, name = element.name, asRoot = false ) { - +export function register (element, name = element.name, asRoot = false) { elements[name] = element - if ( asRoot ) elements[root] = element + if (asRoot) elements[root] = element - addMethodNames( Object.keys( element.prototype ) ) + addMethodNames(Object.keys(element.prototype)) return element - } -export function getClass ( name ) { - +export function getClass (name) { return elements[name] - } // Element id sequence let did = 1000 // Get next named element id -export function eid ( name ) { - - return 'Svgjs' + capitalize( name ) + ( did++ ) - +export function eid (name) { + return 'Svgjs' + capitalize(name) + (did++) } // Deep new id assignment -export function assignNewId ( node ) { - +export function assignNewId (node) { // do the same for SVG child nodes as well - for ( var i = node.children.length - 1; i >= 0; i-- ) { - - assignNewId( node.children[i] ) - + for (var i = node.children.length - 1; i >= 0; i--) { + assignNewId(node.children[i]) } - if ( node.id ) { - - return adopt( node ).id( eid( node.nodeName ) ) - + if (node.id) { + return adopt(node).id(eid(node.nodeName)) } - return adopt( node ) - + return adopt(node) } // Method for extending objects -export function extend ( modules, methods, attrCheck ) { - +export function extend (modules, methods, attrCheck) { var key, i - modules = Array.isArray( modules ) ? modules : [ modules ] - - for ( i = modules.length - 1; i >= 0; i-- ) { - - for ( key in methods ) { + modules = Array.isArray(modules) ? modules : [ modules ] + for (i = modules.length - 1; i >= 0; i--) { + for (key in methods) { let method = methods[key] - if ( attrCheck ) { - - method = wrapWithAttrCheck( methods[key] ) - + if (attrCheck) { + method = wrapWithAttrCheck(methods[key]) } modules[i].prototype[key] = method - } - } - } -export function extendWithAttrCheck ( ...args ) { - - extend( ...args, true ) - +export function extendWithAttrCheck (...args) { + extend(...args, true) } -export function wrapWithAttrCheck ( fn ) { - - return function ( ...args ) { - +export function wrapWithAttrCheck (fn) { + return function (...args) { let o = args[args.length - 1] - if ( o && o.constructor === Object && !( o instanceof Array ) ) { - - return fn.apply( this, args.slice( 0, -1 ) ).attr( o ) - + if (o && o.constructor === Object && !(o instanceof Array)) { + return fn.apply(this, args.slice(0, -1)).attr(o) } else { - - return fn.apply( this, args ) - + return fn.apply(this, args) } - } - } diff --git a/src/utils/methods.js b/src/utils/methods.js index 4973d13..527e7b7 100644 --- a/src/utils/methods.js +++ b/src/utils/methods.js @@ -2,61 +2,41 @@ const methods = {} const constructors = {} const names = [] -export function registerMethods ( name, m ) { - - if ( Array.isArray( name ) ) { - - for ( let _name of name ) { - - 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' ) { - - for ( let [ _name, _m ] of Object.entries( name ) ) { - - registerMethods( _name, _m ) - + if (typeof name === 'object') { + for (let [ _name, _m ] of Object.entries(name)) { + registerMethods(_name, _m) } return - } - addMethodNames( Object.keys( m ) ) - methods[name] = Object.assign( methods[name] || {}, m ) - + addMethodNames(Object.keys(m)) + methods[name] = Object.assign(methods[name] || {}, m) } -export function getMethodsFor ( name ) { - +export function getMethodsFor (name) { return methods[name] || {} - } export function getMethodNames () { - - return [ ...new Set( names ) ] - + return [ ...new Set(names) ] } -export function addMethodNames ( _names ) { - - names.push( ..._names ) - +export function addMethodNames (_names) { + names.push(..._names) } -export function registerConstructor ( name, setup ) { - +export function registerConstructor (name, setup) { constructors[name] = setup - } -export function getConstructor ( name ) { - +export function getConstructor (name) { return constructors[name] ? { setup: constructors[name], name } : {} - } diff --git a/src/utils/utils.js b/src/utils/utils.js index 01cd49f..3bac0de 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -1,143 +1,105 @@ // Map function -export function map ( array, block ) { - +export function map (array, block) { var i var il = array.length var result = [] - for ( i = 0; i < il; i++ ) { - - result.push( block( array[i] ) ) - + for (i = 0; i < il; i++) { + result.push(block(array[i])) } return result - } // Filter function -export function filter ( array, block ) { - +export function filter (array, block) { var i var il = array.length var result = [] - for ( i = 0; i < il; i++ ) { - - if ( block( array[i] ) ) { - - result.push( array[i] ) - + for (i = 0; i < il; i++) { + if (block(array[i])) { + result.push(array[i]) } - } return result - } // Degrees to radians -export function radians ( d ) { - +export function radians (d) { return d % 360 * Math.PI / 180 - } // Radians to degrees -export function degrees ( r ) { - +export function degrees (r) { return r * 180 / Math.PI % 360 - } // Convert dash-separated-string to camelCase -export function camelCase ( s ) { - - return s.toLowerCase().replace( /-(.)/g, function ( m, g ) { - +export function camelCase (s) { + return s.toLowerCase().replace(/-(.)/g, function (m, g) { return g.toUpperCase() - - } ) - + }) } // Convert camel cased string to string seperated -export function unCamelCase ( s ) { - - return s.replace( /([A-Z])/g, function ( m, g ) { - +export function unCamelCase (s) { + return s.replace(/([A-Z])/g, function (m, g) { return '-' + g.toLowerCase() - - } ) - + }) } // Capitalize first letter of a string -export function capitalize ( s ) { - - return s.charAt( 0 ).toUpperCase() + s.slice( 1 ) - +export function capitalize (s) { + return s.charAt(0).toUpperCase() + s.slice(1) } // Calculate proportional width and height values when necessary -export function proportionalSize ( element, width, height ) { - - if ( width == null || height == null ) { - +export function proportionalSize (element, width, height) { + if (width == null || height == null) { var box = element.bbox() - if ( width == null ) { - + if (width == null) { width = box.width / box.height * height - - } else if ( height == null ) { - + } else if (height == null) { height = box.height / box.width * width - } - } return { width: width, height: height } - } -export function getOrigin ( o, element ) { - +export function getOrigin (o, element) { // Allow origin or around as the names let origin = o.origin // o.around == null ? o.origin : o.around let ox, oy // Allow the user to pass a string to rotate around a given point - if ( typeof origin === 'string' || origin == null ) { - + if (typeof origin === 'string' || origin == null) { // Get the bounding box of the element with no transformations applied - const string = ( origin || 'center' ).toLowerCase().trim() + const string = (origin || 'center').toLowerCase().trim() const { height, width, x, y } = element.bbox() // Calculate the transformed x and y coordinates - let bx = string.includes( 'left' ) ? x - : string.includes( 'right' ) ? x + width + let bx = string.includes('left') ? x + : string.includes('right') ? x + width : x + width / 2 - let by = string.includes( 'top' ) ? y - : string.includes( 'bottom' ) ? y + height + let by = string.includes('top') ? y + : string.includes('bottom') ? y + height : y + height / 2 // Set the bounds eg : "bottom-left", "Top right", "middle" etc... ox = o.ox != null ? o.ox : bx oy = o.oy != null ? o.oy : by - } else { - ox = origin[0] oy = origin[1] - } // Return the origin as it is if it wasn't a string return [ ox, oy ] - } diff --git a/src/utils/window.js b/src/utils/window.js index 55f0bb6..9e51339 100644 --- a/src/utils/window.js +++ b/src/utils/window.js @@ -3,9 +3,7 @@ export const globals = { document: typeof document === 'undefined' ? null : document } -export function registerWindow ( win = null, doc = null ) { - +export function registerWindow (win = null, doc = null) { globals.window = win globals.document = doc - } |