diff options
Diffstat (limited to 'src')
73 files changed, 1396 insertions, 1196 deletions
diff --git a/src/animation/Animator.js b/src/animation/Animator.js index fc3df10..11cca54 100644 --- a/src/animation/Animator.js +++ b/src/animation/Animator.js @@ -9,7 +9,7 @@ const Animator = { timer: () => globals.window.performance || globals.window.Date, transforms: [], - frame (fn) { + frame(fn) { // Store the node const node = Animator.frames.push({ run: fn }) @@ -22,7 +22,7 @@ const Animator = { return node }, - timeout (fn, delay) { + timeout(fn, delay) { delay = delay || 0 // Work out when the event should fire @@ -39,7 +39,7 @@ const Animator = { return node }, - immediate (fn) { + immediate(fn) { // Add the immediate fn to the end of the queue const node = Animator.immediates.push(fn) // Request another animation frame if we need one @@ -50,19 +50,19 @@ const Animator = { return node }, - cancelFrame (node) { + cancelFrame(node) { node != null && Animator.frames.remove(node) }, - clearTimeout (node) { + clearTimeout(node) { node != null && Animator.timeouts.remove(node) }, - cancelImmediate (node) { + cancelImmediate(node) { node != null && Animator.immediates.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]) let nextTimeout = null @@ -82,7 +82,7 @@ const Animator = { // Run all of the animation frames let nextFrame = null const lastFrame = Animator.frames.last() - while ((nextFrame !== lastFrame) && (nextFrame = Animator.frames.shift())) { + while (nextFrame !== lastFrame && (nextFrame = Animator.frames.shift())) { nextFrame.run(now) } @@ -92,9 +92,10 @@ const Animator = { } // 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) - : null + Animator.nextDraw = + Animator.timeouts.first() || Animator.frames.first() + ? globals.window.requestAnimationFrame(Animator._draw) + : null } } diff --git a/src/animation/Controller.js b/src/animation/Controller.js index 303fb71..1cf879d 100644 --- a/src/animation/Controller.js +++ b/src/animation/Controller.js @@ -7,7 +7,7 @@ Base Class The base stepper class that will be ***/ -function makeSetterGetter (k, f) { +function makeSetterGetter(k, f) { return function (v) { if (v == null) return this[k] this[k] = v @@ -24,27 +24,27 @@ export const easing = { return -Math.cos(pos * Math.PI) / 2 + 0.5 }, '>': function (pos) { - return Math.sin(pos * Math.PI / 2) + return Math.sin((pos * Math.PI) / 2) }, '<': function (pos) { - return -Math.cos(pos * Math.PI / 2) + 1 + return -Math.cos((pos * Math.PI) / 2) + 1 }, 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 y1 / x1 * t + return (y1 / x1) * t } else if (x2 > 0) { - return y2 / x2 * t + return (y2 / x2) * t } else { return 0 } } else if (t > 1) { if (x2 < 1) { - return (1 - y2) / (1 - x2) * t + (y2 - x2) / (1 - x2) + return ((1 - y2) / (1 - x2)) * t + (y2 - x2) / (1 - x2) } else if (x1 < 1) { - return (1 - y1) / (1 - x1) * t + (y1 - x1) / (1 - x1) + return ((1 - y1) / (1 - x1)) * t + (y1 - x1) / (1 - x1) } else { return 1 } @@ -93,7 +93,7 @@ export const easing = { } export class Stepper { - done () { + done() { return false } } @@ -104,12 +104,12 @@ Easing Functions ***/ export class Ease extends Stepper { - constructor (fn = timeline.ease) { + constructor(fn = timeline.ease) { super() this.ease = easing[fn] || fn } - step (from, to, pos) { + step(from, to, pos) { if (typeof from !== 'number') { return pos < 1 ? from : to } @@ -123,22 +123,21 @@ Controller Types ***/ export class Controller extends Stepper { - constructor (fn) { + constructor(fn) { super() this.stepper = fn } - done (c) { + done(c) { return c.done } - step (current, target, dt, c) { + step(current, target, dt, c) { return this.stepper(current, target, dt, c) } - } -function recalculate () { +function recalculate() { // Apply the default parameters const duration = (this._duration || 500) / 1000 const overshoot = this._overshoot || 0 @@ -156,13 +155,12 @@ function recalculate () { } export class Spring extends Controller { - constructor (duration = 500, overshoot = 0) { + constructor(duration = 500, overshoot = 0) { super() - this.duration(duration) - .overshoot(overshoot) + this.duration(duration).overshoot(overshoot) } - step (current, target, dt, c) { + step(current, target, dt, c) { if (typeof current === 'string') return current c.done = dt === Infinity if (dt === Infinity) return target @@ -177,9 +175,7 @@ export class Spring extends Controller { // Apply the control to get the new position and store it const acceleration = -this.d * velocity - this.k * (current - target) - const newPosition = current - + velocity * dt - + acceleration * dt * dt / 2 + const newPosition = current + velocity * dt + (acceleration * dt * dt) / 2 // Store the velocity c.velocity = velocity + acceleration * dt @@ -196,12 +192,12 @@ extend(Spring, { }) export class PID extends Controller { - constructor (p = 0.1, i = 0.01, d = 0, windup = 1000) { + constructor(p = 0.1, i = 0.01, d = 0, windup = 1000) { super() this.p(p).i(i).d(d).windup(windup) } - step (current, target, dt, c) { + step(current, target, dt, c) { if (typeof current === 'string') return current c.done = dt === Infinity diff --git a/src/animation/Morphable.js b/src/animation/Morphable.js index e9b3ff8..240ca7b 100644 --- a/src/animation/Morphable.js +++ b/src/animation/Morphable.js @@ -19,9 +19,7 @@ const getClassForType = (value) => { if (Color.isColor(value)) { return Color } else if (delimiter.test(value)) { - return isPathLetter.test(value) - ? PathArray - : SVGArray + return isPathLetter.test(value) ? PathArray : SVGArray } else if (numberAndUnit.test(value)) { return SVGNumber } else { @@ -39,7 +37,7 @@ const getClassForType = (value) => { } export default class Morphable { - constructor (stepper) { + constructor(stepper) { this._stepper = stepper || new Ease('-') this._from = null @@ -49,12 +47,17 @@ export default class Morphable { this._morphObj = null } - at (pos) { - return this._morphObj.morph(this._from, this._to, pos, this._stepper, this._context) - + at(pos) { + return this._morphObj.morph( + this._from, + this._to, + pos, + this._stepper, + this._context + ) } - done () { + done() { const complete = this._context .map(this._stepper.done) .reduce(function (last, curr) { @@ -63,7 +66,7 @@ export default class Morphable { return complete } - from (val) { + from(val) { if (val == null) { return this._from } @@ -72,13 +75,13 @@ export default class Morphable { return this } - stepper (stepper) { + stepper(stepper) { if (stepper == null) return this._stepper this._stepper = stepper return this } - to (val) { + to(val) { if (val == null) { return this._to } @@ -87,7 +90,7 @@ export default class Morphable { return this } - type (type) { + type(type) { // getter if (type == null) { return this._type @@ -98,33 +101,34 @@ export default class Morphable { return this } - _set (value) { + _set(value) { if (!this._type) { this.type(getClassForType(value)) } - let result = (new this._type(value)) + let result = new this._type(value) if (this._type === Color) { result = this._to ? result[this._to[4]]() : this._from - ? result[this._from[4]]() - : result + ? result[this._from[4]]() + : result } if (this._type === ObjectBag) { result = this._to ? result.align(this._to) : this._from - ? result.align(this._from) - : result + ? result.align(this._from) + : result } result = result.toConsumable() this._morphObj = this._morphObj || new this._type() - this._context = this._context - || Array.apply(null, Array(result.length)) + this._context = + this._context || + Array.apply(null, Array(result.length)) .map(Object) .map(function (o) { o.done = true @@ -132,36 +136,34 @@ export default class Morphable { }) return result } - } export class NonMorphable { - constructor (...args) { + constructor(...args) { this.init(...args) } - init (val) { + init(val) { val = Array.isArray(val) ? val[0] : val this.value = val return this } - toArray () { - return [ this.value ] + toArray() { + return [this.value] } - valueOf () { + valueOf() { return this.value } - } export class TransformBag { - constructor (...args) { + constructor(...args) { this.init(...args) } - init (obj) { + init(obj) { if (Array.isArray(obj)) { obj = { scaleX: obj[0], @@ -179,7 +181,7 @@ export class TransformBag { return this } - toArray () { + toArray() { const v = this return [ @@ -207,23 +209,24 @@ TransformBag.defaults = { } const sortByKey = (a, b) => { - return (a[0] < b[0] ? -1 : (a[0] > b[0] ? 1 : 0)) + return a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0 } export class ObjectBag { - constructor (...args) { + constructor(...args) { this.init(...args) } - align (other) { + align(other) { const values = this.values for (let i = 0, il = values.length; i < il; ++i) { - // If the type is the same we only need to check if the color is in the correct format if (values[i + 1] === other[i + 1]) { if (values[i + 1] === Color && other[i + 7] !== values[i + 7]) { const space = other[i + 7] - const color = new Color(this.values.splice(i + 3, 5))[space]().toArray() + const color = new Color(this.values.splice(i + 3, 5)) + [space]() + .toArray() this.values.splice(i + 3, 0, ...color) } @@ -237,19 +240,26 @@ export class ObjectBag { // The types differ, so we overwrite the new type with the old one // And initialize it with the types default (e.g. black for color or 0 for number) - const defaultObject = new (other[i + 1])().toArray() + const defaultObject = new other[i + 1]().toArray() // Than we fix the values array - const toDelete = (values[i + 2]) + 3 + const toDelete = values[i + 2] + 3 - values.splice(i, toDelete, other[i], other[i + 1], other[i + 2], ...defaultObject) + values.splice( + i, + toDelete, + other[i], + other[i + 1], + other[i + 2], + ...defaultObject + ) i += values[i + 2] + 2 } return this } - init (objOrArr) { + init(objOrArr) { this.values = [] if (Array.isArray(objOrArr)) { @@ -263,7 +273,7 @@ export class ObjectBag { for (const i in objOrArr) { const Type = getClassForType(objOrArr[i]) const val = new Type(objOrArr[i]).toArray() - entries.push([ i, Type, val.length, ...val ]) + entries.push([i, Type, val.length, ...val]) } entries.sort(sortByKey) @@ -272,11 +282,11 @@ export class ObjectBag { return this } - toArray () { + toArray() { return this.values } - valueOf () { + valueOf() { const obj = {} const arr = this.values @@ -286,40 +296,35 @@ export class ObjectBag { const Type = arr.shift() const num = arr.shift() const values = arr.splice(0, num) - obj[key] = new Type(values)// .valueOf() + obj[key] = new Type(values) // .valueOf() } return obj } - } -const morphableTypes = [ - NonMorphable, - TransformBag, - ObjectBag -] +const morphableTypes = [NonMorphable, TransformBag, ObjectBag] -export function registerMorphableType (type = []) { +export function registerMorphableType(type = []) { morphableTypes.push(...[].concat(type)) } -export function makeMorphable () { +export function makeMorphable() { extend(morphableTypes, { - to (val) { + to(val) { return new Morphable() .type(this.constructor) - .from(this.toArray())// this.valueOf()) + .from(this.toArray()) // this.valueOf()) .to(val) }, - fromArray (arr) { + fromArray(arr) { this.init(arr) return this }, - toConsumable () { + toConsumable() { return this.toArray() }, - morph (from, to, pos, stepper, context) { + morph(from, to, pos, stepper, context) { const mapper = function (i, index) { return stepper.step(i, to[index], pos, context[index], context) } diff --git a/src/animation/Queue.js b/src/animation/Queue.js index ba484dc..65108f3 100644 --- a/src/animation/Queue.js +++ b/src/animation/Queue.js @@ -1,22 +1,25 @@ export default class Queue { - constructor () { + constructor() { this._first = null this._last = null } // Shows us the first item in the list - first () { + first() { return this._first && this._first.value } // Shows us the last item in the list - last () { + last() { return this._last && this._last.value } - push (value) { + push(value) { // An item stores an id and the provided value - const item = typeof value.next !== 'undefined' ? value : { value: value, next: null, prev: null } + const item = + typeof value.next !== 'undefined' + ? value + : { value: value, next: null, prev: null } // Deal with the queue being empty or populated if (this._last) { @@ -33,7 +36,7 @@ export default class Queue { } // 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 @@ -45,7 +48,7 @@ export default class Queue { item.next = null } - shift () { + shift() { // Check if we have a value const remove = this._first if (!remove) return null @@ -56,5 +59,4 @@ export default class Queue { this._last = this._first ? this._last : null return remove.value } - } diff --git a/src/animation/Runner.js b/src/animation/Runner.js index 9d50042..a83a02f 100644 --- a/src/animation/Runner.js +++ b/src/animation/Runner.js @@ -15,21 +15,17 @@ 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 this.id = Runner.id++ // Ensure a default value - options = options == null - ? timeline.duration - : options + options = options == null ? timeline.duration : options // Ensure that we get a controller - options = typeof options === 'function' - ? new Controller(options) - : options + options = typeof options === 'function' ? new Controller(options) : options // Declare all of the variables this._element = null @@ -71,7 +67,7 @@ export default class Runner extends EventTarget { this._persist = this._isDeclarative ? true : null } - static sanitise (duration, delay, when) { + static sanitise(duration, delay, when) { // Initialise the default parameters let times = 1 let swing = false @@ -100,7 +96,7 @@ export default class Runner extends EventTarget { } } - active (enabled) { + active(enabled) { if (enabled == null) return this.enabled this.enabled = enabled return this @@ -111,16 +107,16 @@ export default class Runner extends EventTarget { =============== Methods that shouldn't be used externally */ - addTransform (transform, index) { + addTransform(transform) { this.transforms.lmultiplyO(transform) return this } - after (fn) { + after(fn) { return this.on('finished', fn) } - animate (duration, delay, when) { + animate(duration, delay, when) { const o = Runner.sanitise(duration, delay, when) const runner = new Runner(o.duration) if (this._timeline) runner.timeline(this._timeline) @@ -128,33 +124,37 @@ export default class Runner extends EventTarget { return runner.loop(o).schedule(o.delay, o.when) } - clearTransform () { + clearTransform() { this.transforms = new Matrix() return this } // TODO: Keep track of all transformations so that deletion is faster - clearTransformsFromQueue () { - if (!this.done || !this._timeline || !this._timeline._runnerIds.includes(this.id)) { + clearTransformsFromQueue() { + if ( + !this.done || + !this._timeline || + !this._timeline._runnerIds.includes(this.id) + ) { this._queue = this._queue.filter((item) => { return !item.isTransform }) } } - delay (delay) { + delay(delay) { return this.animate(0, delay) } - duration () { + duration() { return this._times * (this._wait + this._duration) - this._wait } - during (fn) { + during(fn) { return this.queue(null, fn) } - ease (fn) { + ease(fn) { this._stepper = new Ease(fn) return this } @@ -165,18 +165,18 @@ export default class Runner extends EventTarget { help us make new runners from the current runner */ - element (element) { + element(element) { if (element == null) return this._element this._element = element element._prepareRunner() return this } - finish () { + finish() { return this.step(Infinity) } - loop (times, swing, wait) { + loop(times, swing, wait) { // Deal with the user passing in an object if (typeof times === 'object') { swing = times.swing @@ -190,16 +190,18 @@ export default class Runner extends EventTarget { this._wait = wait || 0 // Allow true to be passed - if (this._times === true) { this._times = Infinity } + if (this._times === true) { + this._times = Infinity + } return this } - loops (p) { + loops(p) { const loopDuration = this._duration + this._wait if (p == null) { const loopsDone = Math.floor(this._time / loopDuration) - const relativeTime = (this._time - loopsDone * loopDuration) + const relativeTime = this._time - loopsDone * loopDuration const position = relativeTime / this._duration return Math.min(loopsDone + position, this._times) } @@ -209,13 +211,13 @@ export default class Runner extends EventTarget { return this.time(time) } - persist (dtOrForever) { + persist(dtOrForever) { if (dtOrForever == null) return this._persist this._persist = dtOrForever return this } - position (p) { + position(p) { // Get all of the variables we need const x = this._time const d = this._duration @@ -235,18 +237,20 @@ export default class Runner extends EventTarget { // Figure out the value without thinking about the start or end time const f = function (x) { - const swinging = s * Math.floor(x % (2 * (w + d)) / (w + d)) + const swinging = s * Math.floor((x % (2 * (w + d))) / (w + d)) const backwards = (swinging && !r) || (!swinging && r) - const uncliped = Math.pow(-1, backwards) * (x % (w + d)) / d + backwards + const uncliped = + (Math.pow(-1, backwards) * (x % (w + d))) / d + backwards const clipped = Math.max(Math.min(uncliped, 1), 0) return clipped } // Figure out the value by incorporating the start time const endTime = t * (w + d) - w - position = x <= 0 - ? Math.round(f(1e-5)) - : x < endTime + position = + x <= 0 + ? Math.round(f(1e-5)) + : x < endTime ? f(x) : Math.round(f(endTime - 1e-5)) return position @@ -254,13 +258,13 @@ export default class Runner extends EventTarget { // Work out the loops done and add the position to the loops done const loopsDone = Math.floor(this.loops()) - const swingForward = s && (loopsDone % 2 === 0) + const swingForward = s && loopsDone % 2 === 0 const forwards = (swingForward && !r) || (r && swingForward) position = loopsDone + (forwards ? p : 1 - p) return this.loops(position) } - progress (p) { + progress(p) { if (p == null) { return Math.min(1, this._time / this.duration()) } @@ -272,7 +276,7 @@ export default class Runner extends EventTarget { =================== These methods allow us to attach basic functions to the runner directly */ - queue (initFn, runFn, retargetFn, isTransform) { + queue(initFn, runFn, retargetFn, isTransform) { this._queue.push({ initialiser: initFn || noop, runner: runFn || noop, @@ -286,19 +290,19 @@ export default class Runner extends EventTarget { return this } - reset () { + reset() { if (this._reseted) return this this.time(0) this._reseted = true return this } - reverse (reverse) { + reverse(reverse) { this._reverse = reverse == null ? !this._reverse : reverse return this } - 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)) { when = delay @@ -316,7 +320,7 @@ export default class Runner extends EventTarget { return this } - step (dt) { + step(dt) { // If we are inactive, this stepper just gets skipped if (!this.enabled) return this @@ -373,7 +377,7 @@ export default class Runner extends EventTarget { ======================== Control how the animation plays */ - time (time) { + time(time) { if (time == null) { return this._time } @@ -382,21 +386,21 @@ export default class Runner extends EventTarget { 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 this._timeline = timeline return this } - unschedule () { + unschedule() { const timeline = this.timeline() timeline && timeline.unschedule(this) return this } // 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 @@ -418,7 +422,7 @@ 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] @@ -438,7 +442,7 @@ export default class Runner extends EventTarget { // Try to set the target for a morpher if the morpher exists, otherwise // Run each run function for the position or dt given - _run (positionOrDt) { + _run(positionOrDt) { // Run all of the _queue directly let allfinished = true for (let i = 0, len = this._queue.length; i < len; ++i) { @@ -448,7 +452,7 @@ export default class Runner extends EventTarget { // Run the function if its not finished, we keep track of the finished // flag for the sake of declarative _queue const converged = current.runner.call(this, positionOrDt) - current.finished = current.finished || (converged === true) + current.finished = current.finished || converged === true allfinished = allfinished && current.finished } @@ -457,7 +461,7 @@ export default class Runner extends EventTarget { } // do nothing and return false - _tryRetarget (method, target, extra) { + _tryRetarget(method, target, extra) { if (this._history[method]) { // if the last method wasn't even initialised, throw it away if (!this._history[method].caller.initialised) { @@ -482,23 +486,22 @@ export default class Runner extends EventTarget { } return false } - } Runner.id = 0 export 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 () { } + clearTransformsFromQueue() {} } -extend([ Runner, FakeRunner ], { - mergeWith (runner) { +extend([Runner, FakeRunner], { + mergeWith(runner) { return new FakeRunner( runner.transforms.lmultiply(this.transforms), runner.id @@ -511,7 +514,7 @@ extend([ Runner, FakeRunner ], { const lmultiply = (last, curr) => last.lmultiplyO(curr) const getRunnerTransform = (runner) => runner.transforms -function mergeTransforms () { +function mergeTransforms() { // Find the matrix to apply to the element and apply it const runners = this._transformationRunners.runners const netTransform = runners @@ -528,12 +531,12 @@ function mergeTransforms () { } export class RunnerArray { - constructor () { + constructor() { this.runners = [] this.ids = [] } - add (runner) { + add(runner) { if (this.runners.includes(runner)) return const id = runner.id + 1 @@ -543,39 +546,44 @@ export class RunnerArray { return this } - clearBefore (id) { + clearBefore(id) { const deleteCnt = this.ids.indexOf(id + 1) || 1 this.ids.splice(0, deleteCnt, 0) - this.runners.splice(0, deleteCnt, new FakeRunner()) + this.runners + .splice(0, deleteCnt, new FakeRunner()) .forEach((r) => r.clearTransformsFromQueue()) return this } - edit (id, newRunner) { + edit(id, newRunner) { const index = this.ids.indexOf(id + 1) this.ids.splice(index, 1, id + 1) this.runners.splice(index, 1, newRunner) return this } - getByID (id) { + getByID(id) { return this.runners[this.ids.indexOf(id + 1)] } - length () { + length() { return this.ids.length } - merge () { + merge() { let lastRunner = null for (let i = 0; i < this.runners.length; ++i) { const runner = this.runners[i] - const condition = lastRunner - && runner.done && lastRunner.done + const condition = + lastRunner && + runner.done && + lastRunner.done && // don't merge runner when persisted on timeline - && (!runner._timeline || !runner._timeline._runnerIds.includes(runner.id)) - && (!lastRunner._timeline || !lastRunner._timeline._runnerIds.includes(lastRunner.id)) + (!runner._timeline || + !runner._timeline._runnerIds.includes(runner.id)) && + (!lastRunner._timeline || + !lastRunner._timeline._runnerIds.includes(lastRunner.id)) if (condition) { // the +1 happens in the function @@ -592,18 +600,17 @@ export class RunnerArray { return this } - remove (id) { + remove(id) { const index = this.ids.indexOf(id + 1) this.ids.splice(index, 1) this.runners.splice(index, 1) return this } - } registerMethods({ Element: { - animate (duration, delay, when) { + animate(duration, delay, when) { const o = Runner.sanitise(duration, delay, when) const timeline = this.timeline() return new Runner(o.duration) @@ -613,7 +620,7 @@ registerMethods({ .schedule(o.delay, o.when) }, - delay (by, when) { + delay(by, when) { return this.animate(0, by, when) }, @@ -621,21 +628,23 @@ registerMethods({ // which run before the current one. This is because absolute transformations // overwrite anything anyway so there is no need to waste time computing // other runners - _clearTransformRunnersBefore (currentRunner) { + _clearTransformRunnersBefore(currentRunner) { this._transformationRunners.clearBefore(currentRunner.id) }, - _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()) + _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()) + ) }, - _addRunner (runner) { + _addRunner(runner) { this._transformationRunners.add(runner) // Make sure that the runner merge is executed at the very end of @@ -645,29 +654,30 @@ registerMethods({ this._frameId = Animator.immediate(mergeTransforms.bind(this)) }, - _prepareRunner () { + _prepareRunner() { if (this._frameId == null) { - this._transformationRunners = new RunnerArray() - .add(new FakeRunner(new Matrix(this))) + this._transformationRunners = new RunnerArray().add( + new FakeRunner(new Matrix(this)) + ) } } } }) // Will output the elements from array A that are not in the array B -const difference = (a, b) => a.filter(x => !b.includes(x)) +const difference = (a, b) => a.filter((x) => !b.includes(x)) extend(Runner, { - attr (a, v) { + attr(a, v) { return this.styleAttr('attr', a, v) }, // Add animatable styles - css (s, v) { + css(s, v) { return this.styleAttr('css', s, v) }, - styleAttr (type, nameOrAttrs, val) { + styleAttr(type, nameOrAttrs, val) { if (typeof nameOrAttrs === 'string') { return this.styleAttr(type, { [nameOrAttrs]: val }) } @@ -678,62 +688,69 @@ extend(Runner, { let morpher = new Morphable(this._stepper).to(attrs) let keys = Object.keys(attrs) - this.queue(function () { - morpher = morpher.from(this.element()[type](keys)) - }, function (pos) { - this.element()[type](morpher.at(pos).valueOf()) - return morpher.done() - }, function (newToAttrs) { + this.queue( + function () { + morpher = morpher.from(this.element()[type](keys)) + }, + function (pos) { + this.element()[type](morpher.at(pos).valueOf()) + return morpher.done() + }, + function (newToAttrs) { + // Check if any new keys were added + const newKeys = Object.keys(newToAttrs) + const differences = difference(newKeys, keys) + + // If their are new keys, initialize them and add them to morpher + if (differences.length) { + // Get the values + const addedFromAttrs = this.element()[type](differences) + + // Get the already initialized values + const oldFromAttrs = new ObjectBag(morpher.from()).valueOf() + + // Merge old and new + Object.assign(oldFromAttrs, addedFromAttrs) + morpher.from(oldFromAttrs) + } - // Check if any new keys were added - const newKeys = Object.keys(newToAttrs) - const differences = difference(newKeys, keys) + // Get the object from the morpher + const oldToAttrs = new ObjectBag(morpher.to()).valueOf() - // If their are new keys, initialize them and add them to morpher - if (differences.length) { - // Get the values - const addedFromAttrs = this.element()[type](differences) + // Merge in new attributes + Object.assign(oldToAttrs, newToAttrs) - // Get the already initialized values - const oldFromAttrs = new ObjectBag(morpher.from()).valueOf() + // Change morpher target + morpher.to(oldToAttrs) - // Merge old and new - Object.assign(oldFromAttrs, addedFromAttrs) - morpher.from(oldFromAttrs) + // Make sure that we save the work we did so we don't need it to do again + keys = newKeys + attrs = newToAttrs } - - // Get the object from the morpher - const oldToAttrs = new ObjectBag(morpher.to()).valueOf() - - // Merge in new attributes - Object.assign(oldToAttrs, newToAttrs) - - // Change morpher target - morpher.to(oldToAttrs) - - // Make sure that we save the work we did so we don't need it to do again - keys = newKeys - attrs = newToAttrs - }) + ) this._rememberMorpher(type, morpher) return this }, - zoom (level, point) { + zoom(level, point) { if (this._tryRetarget('zoom', level, point)) return this let morpher = new Morphable(this._stepper).to(new SVGNumber(level)) - this.queue(function () { - morpher = morpher.from(this.element().zoom()) - }, function (pos) { - this.element().zoom(morpher.at(pos), point) - return morpher.done() - }, function (newLevel, newPoint) { - point = newPoint - morpher.to(newLevel) - }) + this.queue( + function () { + morpher = morpher.from(this.element().zoom()) + }, + function (pos) { + this.element().zoom(morpher.at(pos), point) + return morpher.done() + }, + function (newLevel, newPoint) { + point = newPoint + morpher.to(newLevel) + } + ) this._rememberMorpher('zoom', morpher) return this @@ -756,22 +773,30 @@ 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 const isMatrix = Matrix.isMatrixLike(transforms) - affine = transforms.affine != null - ? transforms.affine - : (affine != null ? affine : !isMatrix) + affine = + transforms.affine != null + ? transforms.affine + : affine != null + ? affine + : !isMatrix // Create a morpher 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 @@ -779,7 +804,7 @@ extend(Runner, { let currentAngle let startTransform - function setup () { + function setup() { // make sure element and origin is defined element = element || this.element() origin = origin || getOrigin(transforms, element) @@ -795,17 +820,17 @@ extend(Runner, { } } - 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() - const { x, y } = new Point(origin).transform(element._currentTransform(this)) + const { x, y } = new Point(origin).transform( + element._currentTransform(this) + ) - let target = new Matrix({ ...transforms, origin: [ x, y ] }) - let start = this._isDeclarative && current - ? current - : startTransform + let target = new Matrix({ ...transforms, origin: [x, y] }) + let start = this._isDeclarative && current ? current : startTransform if (affine) { target = target.decompose(x, y) @@ -816,8 +841,8 @@ extend(Runner, { const rCurrent = start.rotate // 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 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) target.rotate = possibilities[index] @@ -846,11 +871,11 @@ extend(Runner, { 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(newTransforms, element) } @@ -865,28 +890,28 @@ extend(Runner, { }, // Animatable x-axis - x (x, relative) { + x(x) { return this._queueNumber('x', x) }, // Animatable y-axis - y (y) { + y(y) { return this._queueNumber('y', y) }, - dx (x = 0) { + dx(x = 0) { return this._queueNumberDelta('x', x) }, - dy (y = 0) { + dy(y = 0) { return this._queueNumberDelta('y', y) }, - dmove (x, y) { + dmove(x, y) { return this.dx(x).dy(y) }, - _queueNumberDelta (method, to) { + _queueNumberDelta(method, to) { to = new SVGNumber(to) // Try to change the target if we have this method already registered @@ -895,66 +920,73 @@ extend(Runner, { // Make a morpher and queue the animation const morpher = new Morphable(this._stepper).to(to) let from = null - this.queue(function () { - from = this.element()[method]() - 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)) - }) + this.queue( + function () { + from = this.element()[method]() + 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)) + } + ) // Register the morpher so that if it is changed again, we can retarget it this._rememberMorpher(method, morpher) return this }, - _queueObject (method, to) { + _queueObject(method, to) { // Try to change the target if we have this method already registered if (this._tryRetarget(method, to)) return this // Make a morpher and queue the animation const 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() - }) + 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) return this }, - _queueNumber (method, value) { + _queueNumber(method, value) { return this._queueObject(method, new SVGNumber(value)) }, // Animatable center x-axis - cx (x) { + cx(x) { return this._queueNumber('cx', x) }, // Animatable center y-axis - cy (y) { + cy(y) { return this._queueNumber('cy', y) }, // Add animatable move - move (x, y) { + move(x, y) { return this.x(x).y(y) }, // Add animatable center - center (x, 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 let box @@ -963,62 +995,64 @@ extend(Runner, { } if (!width) { - width = box.width / box.height * height + width = (box.width / box.height) * height } if (!height) { - height = box.height / box.width * width + height = (box.height / box.width) * width } - return this - .width(width) - .height(height) + return this.width(width).height(height) }, // Add animatable width - width (width) { + width(width) { return this._queueNumber('width', width) }, // Add animatable height - 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 ]) + return this.plot([a, b, c, d]) } if (this._tryRetarget('plot', a)) return this const morpher = new Morphable(this._stepper) - .type(this._element.MorphArray).to(a) - - this.queue(function () { - morpher.from(this._element.array()) - }, function (pos) { - this._element.plot(morpher.at(pos)) - return morpher.done() - }) + .type(this._element.MorphArray) + .to(a) + + this.queue( + function () { + morpher.from(this._element.array()) + }, + function (pos) { + this._element.plot(morpher.at(pos)) + return morpher.done() + } + ) this._rememberMorpher('plot', morpher) return this }, // Add leading method - leading (value) { + leading(value) { return this._queueNumber('leading', value) }, // Add animatable viewbox - viewbox (x, y, width, height) { + viewbox(x, y, width, height) { return this._queueObject('viewbox', new Box(x, y, width, height)) }, - update (o) { + update(o) { if (typeof o !== 'object') { return this.update({ offset: arguments[0], diff --git a/src/animation/Timeline.js b/src/animation/Timeline.js index 3f81b66..39e0f1a 100644 --- a/src/animation/Timeline.js +++ b/src/animation/Timeline.js @@ -7,7 +7,12 @@ const makeSchedule = function (runnerInfo) { const start = runnerInfo.start const duration = runnerInfo.runner.duration() const end = start + duration - return { start: start, duration: duration, end: end, runner: runnerInfo.runner } + return { + start: start, + duration: duration, + end: end, + runner: runnerInfo.runner + } } const defaultSource = function () { @@ -17,7 +22,7 @@ const defaultSource = function () { export default class Timeline extends EventTarget { // Construct a new timeline on the given element - constructor (timeSource = defaultSource) { + constructor(timeSource = defaultSource) { super() this._timeSource = timeSource @@ -44,55 +49,55 @@ export default class Timeline extends EventTarget { this._stepImmediate = this._stepFn.bind(this, true) } - active () { + active() { return !!this._nextFrame } - finish () { + finish() { // Go to end and pause this.time(this.getEndTimeOfTimeline() + 1) return this.pause() } // Calculates the end of the timeline - getEndTime () { + getEndTime() { const lastRunnerInfo = this.getLastRunnerInfo() const lastDuration = lastRunnerInfo ? lastRunnerInfo.runner.duration() : 0 const lastStartTime = lastRunnerInfo ? lastRunnerInfo.start : this._time return lastStartTime + lastDuration } - getEndTimeOfTimeline () { + getEndTimeOfTimeline() { const endTimes = this._runners.map((i) => i.start + i.runner.duration()) return Math.max(0, ...endTimes) } - getLastRunnerInfo () { + getLastRunnerInfo() { return this.getRunnerInfoById(this._lastRunnerId) } - getRunnerInfoById (id) { + getRunnerInfoById(id) { return this._runners[this._runnerIds.indexOf(id)] || null } - pause () { + pause() { this._paused = true return this._continue() } - persist (dtOrForever) { + persist(dtOrForever) { if (dtOrForever == null) return this._persist this._persist = dtOrForever return this } - play () { + play() { // Now make sure we are not paused and continue the animation this._paused = false return this.updateTime()._continue() } - reverse (yes) { + reverse(yes) { const currentSpeed = this.speed() if (yes == null) return this.speed(-currentSpeed) @@ -101,7 +106,7 @@ export default class Timeline extends EventTarget { } // schedules a runner on the timeline - schedule (runner, delay, when) { + schedule(runner, delay, when) { if (runner == null) { return this._runners.map(makeSchedule) } @@ -152,42 +157,42 @@ export default class Timeline extends EventTarget { this._runners.push(runnerInfo) this._runners.sort((a, b) => a.start - b.start) - this._runnerIds = this._runners.map(info => info.runner.id) + this._runnerIds = this._runners.map((info) => info.runner.id) this.updateTime()._continue() return this } - seek (dt) { + seek(dt) { return this.time(this._time + dt) } - source (fn) { + source(fn) { if (fn == null) return this._timeSource this._timeSource = fn return this } - speed (speed) { + speed(speed) { if (speed == null) return this._speed this._speed = speed return this } - stop () { + stop() { // Go to start and pause this.time(0) return this.pause() } - time (time) { + time(time) { if (time == null) return this._time this._time = time return this._continue(true) } // Remove the runner from this timeline - unschedule (runner) { + unschedule(runner) { const index = this._runnerIds.indexOf(runner.id) if (index < 0) return this @@ -199,7 +204,7 @@ export default class Timeline extends EventTarget { } // Makes sure, that after pausing the time doesn't jump - updateTime () { + updateTime() { if (!this.active()) { this._lastSourceTime = this._timeSource() } @@ -207,7 +212,7 @@ export default class Timeline extends EventTarget { } // Checks if we are running and continues the animation - _continue (immediateStep = false) { + _continue(immediateStep = false) { Animator.cancelFrame(this._nextFrame) this._nextFrame = null @@ -218,7 +223,7 @@ export default class Timeline extends EventTarget { return this } - _stepFn (immediateStep = false) { + _stepFn(immediateStep = false) { // Get the time delta from the last time and update the time const time = this._timeSource() let dtSource = time - this._lastSourceTime @@ -249,7 +254,7 @@ export default class Timeline extends EventTarget { // runner always wins the reset even if the other runner started earlier // and therefore should win the attribute battle // this can be solved by resetting them backwards - for (let k = this._runners.length; k--;) { + for (let k = this._runners.length; k--; ) { // Get and run the current runner and ignore it if its inactive const runnerInfo = this._runners[k] const runner = runnerInfo.runner @@ -309,7 +314,10 @@ export default class Timeline extends EventTarget { // Basically: we continue when there are runners right from us in time // when -->, and when runners are left from us when <-- - if ((runnersLeft && !(this._speed < 0 && this._time === 0)) || (this._runnerIds.length && this._speed < 0 && this._time > 0)) { + if ( + (runnersLeft && !(this._speed < 0 && this._time === 0)) || + (this._runnerIds.length && this._speed < 0 && this._time > 0) + ) { this._continue() } else { this.pause() @@ -318,14 +326,13 @@ export default class Timeline extends EventTarget { return this } - } registerMethods({ Element: { timeline: function (timeline) { if (timeline == null) { - this._timeline = (this._timeline || new Timeline()) + this._timeline = this._timeline || new Timeline() return this._timeline } else { this._timeline = timeline diff --git a/src/elements/A.js b/src/elements/A.js index 173fc92..231954f 100644 --- a/src/elements/A.js +++ b/src/elements/A.js @@ -1,24 +1,28 @@ -import { nodeOrNew, register, wrapWithAttrCheck, extend } from '../utils/adopter.js' +import { + nodeOrNew, + register, + wrapWithAttrCheck, + extend +} from '../utils/adopter.js' import { registerMethods } from '../utils/methods.js' import { xlink } from '../modules/core/namespaces.js' import Container from './Container.js' import * as containerGeometry from '../modules/core/containerGeometry.js' export default class A extends Container { - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('a', node), attrs) } // Link target attribute - target (target) { + target(target) { return this.attr('target', target) } // Link url - to (url) { + to(url) { return this.attr('href', url, xlink) } - } extend(A, containerGeometry) @@ -31,7 +35,7 @@ registerMethods({ }) }, Element: { - unlink () { + unlink() { const link = this.linker() if (!link) return this @@ -48,7 +52,7 @@ registerMethods({ link.remove() return this }, - linkTo (url) { + linkTo(url) { // reuse old link if possible let link = this.linker() @@ -65,7 +69,7 @@ registerMethods({ return this }, - linker () { + linker() { const link = this.parent() if (link && link.node.nodeName.toLowerCase() === 'a') { return link diff --git a/src/elements/Circle.js b/src/elements/Circle.js index 6981b05..5dae51e 100644 --- a/src/elements/Circle.js +++ b/src/elements/Circle.js @@ -10,25 +10,25 @@ import SVGNumber from '../types/SVGNumber.js' import Shape from './Shape.js' export default class Circle extends Shape { - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('circle', node), attrs) } - radius (r) { + radius(r) { return this.attr('r', r) } // Radius x value - rx (rx) { + rx(rx) { return this.attr('r', rx) } // Alias radius x value - ry (ry) { + ry(ry) { return this.rx(ry) } - size (size) { + size(size) { return this.radius(new SVGNumber(size).divide(2)) } } @@ -39,9 +39,7 @@ registerMethods({ Container: { // Create circle element circle: wrapWithAttrCheck(function (size = 0) { - return this.put(new Circle()) - .size(size) - .move(0, 0) + return this.put(new Circle()).size(size).move(0, 0) }) } }) diff --git a/src/elements/ClipPath.js b/src/elements/ClipPath.js index f17428f..747059d 100644 --- a/src/elements/ClipPath.js +++ b/src/elements/ClipPath.js @@ -4,12 +4,12 @@ import Container from './Container.js' import baseFind from '../modules/core/selector.js' export default class ClipPath extends Container { - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('clipPath', node), attrs) } // Unclip all clipped elements and remove itself - remove () { + remove() { // unclip all targets this.targets().forEach(function (el) { el.unclip() @@ -19,7 +19,7 @@ export default class ClipPath extends Container { return super.remove() } - targets () { + targets() { return baseFind('svg [clip-path*=' + this.id() + ']') } } @@ -33,22 +33,23 @@ registerMethods({ }, Element: { // Distribute clipPath to svg element - clipper () { + clipper() { return this.reference('clip-path') }, - clipWith (element) { + clipWith(element) { // use given clip or create a new one - const clipper = element instanceof ClipPath - ? element - : this.parent().clip().add(element) + const clipper = + element instanceof ClipPath + ? element + : this.parent().clip().add(element) // apply mask return this.attr('clip-path', 'url(#' + clipper.id() + ')') }, // Unclip element - unclip () { + unclip() { return this.attr('clip-path', null) } } diff --git a/src/elements/Container.js b/src/elements/Container.js index 9278435..0f45b6d 100644 --- a/src/elements/Container.js +++ b/src/elements/Container.js @@ -2,7 +2,7 @@ import { register } from '../utils/adopter.js' import Element from './Element.js' export default class Container extends Element { - flatten (parent = this, index) { + flatten() { this.each(function () { if (this instanceof Container) { return this.flatten().ungroup() @@ -12,7 +12,7 @@ export default class Container extends Element { return this } - ungroup (parent = this.parent(), index = parent.index(this)) { + ungroup(parent = this.parent(), index = parent.index(this)) { // when parent != this, we want append all elements to the end index = index === -1 ? parent.children().length : index diff --git a/src/elements/Defs.js b/src/elements/Defs.js index 7491ba0..6d9f725 100644 --- a/src/elements/Defs.js +++ b/src/elements/Defs.js @@ -2,15 +2,15 @@ import { nodeOrNew, register } from '../utils/adopter.js' import Container from './Container.js' export default class Defs extends Container { - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('defs', node), attrs) } - flatten () { + flatten() { return this } - ungroup () { + ungroup() { return this } } diff --git a/src/elements/Dom.js b/src/elements/Dom.js index 2584a43..604a1ee 100644 --- a/src/elements/Dom.js +++ b/src/elements/Dom.js @@ -16,7 +16,7 @@ import List from '../types/List.js' import attr from '../modules/core/attr.js' export default class Dom extends EventTarget { - constructor (node, attrs) { + constructor(node, attrs) { super() this.node = node this.type = node.nodeName @@ -27,11 +27,14 @@ export default class Dom extends EventTarget { } // Add given element at a position - add (element, i) { + add(element, i) { element = makeInstance(element) // If non-root svg nodes are added we have to remove their namespaces - if (element.removeNamespace && this.node instanceof globals.window.SVGElement) { + if ( + element.removeNamespace && + this.node instanceof globals.window.SVGElement + ) { element.removeNamespace() } @@ -45,19 +48,21 @@ export default class Dom extends EventTarget { } // Add element to given container and return self - addTo (parent, i) { + addTo(parent, i) { return makeInstance(parent).put(this, i) } // Returns all child elements - children () { - return new List(map(this.node.children, function (node) { - return adopt(node) - })) + children() { + return new List( + map(this.node.children, function (node) { + return adopt(node) + }) + ) } // Remove all elements in this container - clear () { + clear() { // remove children while (this.node.hasChildNodes()) { this.node.removeChild(this.node.lastChild) @@ -67,7 +72,7 @@ export default class Dom extends EventTarget { } // Clone element - clone (deep = true, assignNewIds = true) { + clone(deep = true, assignNewIds = true) { // write dom data to the dom so the clone can pickup the data this.writeDataToDom() @@ -81,12 +86,12 @@ export default class Dom extends EventTarget { } // Iterates over all children and invokes a given block - each (block, deep) { + each(block, deep) { const children = this.children() let i, il for (i = 0, il = children.length; i < il; i++) { - block.apply(children[i], [ i, children ]) + block.apply(children[i], [i, children]) if (deep) { children[i].each(block, deep) @@ -96,39 +101,39 @@ export default class Dom extends EventTarget { return this } - element (nodeName, attrs) { + element(nodeName, attrs) { return this.put(new Dom(create(nodeName), attrs)) } // Get first child - first () { + first() { return adopt(this.node.firstChild) } // Get a element at the given index - get (i) { + get(i) { return adopt(this.node.childNodes[i]) } - getEventHolder () { + getEventHolder() { return this.node } - getEventTarget () { + getEventTarget() { return this.node } // Checks if the given element is a child - has (element) { + has(element) { return this.index(element) >= 0 } - html (htmlOrFn, outerHTML) { + html(htmlOrFn, outerHTML) { return this.xml(htmlOrFn, outerHTML, html) } // 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) @@ -139,24 +144,31 @@ export default class Dom extends EventTarget { } // Gets index of given element - index (element) { + index(element) { return [].slice.call(this.node.childNodes).indexOf(element.node) } // Get the last child - last () { + last() { return adopt(this.node.lastChild) } // matches the element vs a css selector - matches (selector) { + matches(selector) { const el = this.node - const matcher = el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector || null + const matcher = + el.matches || + el.matchesSelector || + el.msMatchesSelector || + el.mozMatchesSelector || + el.webkitMatchesSelector || + el.oMatchesSelector || + null return matcher && matcher.call(el, selector) } // Returns the parent element instance - parent (type) { + parent(type) { let parent = this // check for parent @@ -169,26 +181,29 @@ export default class Dom extends EventTarget { // loop through ancestors if type is given do { - if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent + if ( + typeof type === 'string' ? parent.matches(type) : parent instanceof type + ) + return parent } while ((parent = adopt(parent.node.parentNode))) return parent } // Basically does the same as `add()` but returns the added element instead - put (element, i) { + put(element, i) { element = makeInstance(element) this.add(element, i) return element } // Add element to given container and return container - putIn (parent, i) { + putIn(parent, i) { return makeInstance(parent).add(this, i) } // Remove element - remove () { + remove() { if (this.parent()) { this.parent().removeElement(this) } @@ -197,14 +212,14 @@ export default class Dom extends EventTarget { } // Remove a given child - removeElement (element) { + removeElement(element) { this.node.removeChild(element.node) return this } // Replace this with element - replace (element) { + replace(element) { element = makeInstance(element) if (this.node.parentNode) { @@ -214,7 +229,7 @@ export default class Dom extends EventTarget { return element } - round (precision = 2, map = null) { + round(precision = 2, map = null) { const factor = 10 ** precision const attrs = this.attr(map) @@ -229,22 +244,22 @@ export default class Dom extends EventTarget { } // Import / Export raw svg - svg (svgOrFn, outerSVG) { + svg(svgOrFn, outerSVG) { return this.xml(svgOrFn, outerSVG, svg) } // Return id on string conversion - toString () { + toString() { return this.id() } - words (text) { + words(text) { // This is faster than removing all children and adding a new one this.node.textContent = text return this } - wrap (node) { + wrap(node) { const parent = this.parent() if (!parent) { @@ -256,7 +271,7 @@ export default class Dom extends EventTarget { } // write svgjs data to the dom - writeDataToDom () { + writeDataToDom() { // dump variables recursively this.each(function () { this.writeDataToDom() @@ -266,7 +281,7 @@ export default class Dom extends EventTarget { } // Import / Export raw svg - xml (xmlOrFn, outerXML, ns) { + xml(xmlOrFn, outerXML, ns) { if (typeof xmlOrFn === 'boolean') { ns = outerXML outerXML = xmlOrFn @@ -312,9 +327,7 @@ export default class Dom extends EventTarget { } // Return outer or inner content - return outerXML - ? current.node.outerHTML - : current.node.innerHTML + return outerXML ? current.node.outerHTML : current.node.innerHTML } // Act as setter if we got a string @@ -330,16 +343,14 @@ export default class Dom extends EventTarget { well.innerHTML = xmlOrFn // Transplant nodes into the fragment - for (let len = well.children.length; len--;) { + for (let len = well.children.length; len--; ) { fragment.appendChild(well.firstElementChild) } const parent = this.parent() // Add the whole fragment at once - return outerXML - ? this.replace(fragment) && parent - : this.add(fragment) + return outerXML ? this.replace(fragment) && parent : this.add(fragment) } } diff --git a/src/elements/Element.js b/src/elements/Element.js index 2aaeab5..61db7b7 100644 --- a/src/elements/Element.js +++ b/src/elements/Element.js @@ -16,7 +16,7 @@ import List from '../types/List.js' import SVGNumber from '../types/SVGNumber.js' export default class Element extends Dom { - constructor (node, attrs) { + constructor(node, attrs) { super(node, attrs) // initialize data object @@ -32,61 +32,61 @@ export default class Element extends Dom { } // Move element by its center - center (x, y) { + center(x, y) { return this.cx(x).cy(y) } // Move by center over x-axis - cx (x) { + 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) } // Get defs - defs () { + defs() { const root = this.root() return root && root.defs() } // Relative move over x and y axes - dmove (x, y) { + dmove(x, y) { return this.dx(x).dy(y) } // Relative move over x axis - dx (x = 0) { + dx(x = 0) { return this.x(new SVGNumber(x).plus(this.x())) } // Relative move over y axis - dy (y = 0) { + dy(y = 0) { return this.y(new SVGNumber(y).plus(this.y())) } - getEventHolder () { + getEventHolder() { return this } // Set height of element - height (height) { + height(height) { return this.attr('height', height) } // Move element to given x and y values - move (x, 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 = this.root()) { + parents(until = this.root()) { const isSelector = typeof until === 'string' if (!isSelector) { until = makeInstance(until) @@ -95,13 +95,13 @@ export default class Element extends Dom { let parent = this while ( - (parent = parent.parent()) - && parent.node !== globals.document - && parent.nodeName !== '#document-fragment') { - + (parent = parent.parent()) && + parent.node !== globals.document && + parent.nodeName !== '#document-fragment' + ) { parents.push(parent) - if (!isSelector && (parent.node === until.node)) { + if (!isSelector && parent.node === until.node) { break } if (isSelector && parent.matches(until)) { @@ -117,7 +117,7 @@ export default class Element extends Dom { } // Get referenced element form attribute value - reference (attr) { + reference(attr) { attr = this.attr(attr) if (!attr) return null @@ -126,33 +126,31 @@ export default class Element extends Dom { } // Get parent document - root () { + root() { const p = this.parent(getClass(root)) return p && p.root() } // 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) { + size(width, height) { const p = proportionalSize(this, width, height) - return this - .width(new SVGNumber(p.width)) - .height(new SVGNumber(p.height)) + return this.width(new SVGNumber(p.width)).height(new SVGNumber(p.height)) } // Set width of element - width (width) { + width(width) { return this.attr('width', width) } // write svgjs data to the dom - writeDataToDom () { + writeDataToDom() { // remove previously set data this.node.removeAttribute('svgjs:data') @@ -164,18 +162,23 @@ export default class Element extends Dom { } // Move over x-axis - x (x) { + x(x) { return this.attr('x', x) } // Move over y-axis - y (y) { + y(y) { return this.attr('y', y) } } extend(Element, { - bbox, rbox, inside, point, ctm, screenCTM + bbox, + rbox, + inside, + point, + ctm, + screenCTM }) register(Element, 'Element') diff --git a/src/elements/Ellipse.js b/src/elements/Ellipse.js index 7f4e853..3f8b04b 100644 --- a/src/elements/Ellipse.js +++ b/src/elements/Ellipse.js @@ -11,16 +11,16 @@ import Shape from './Shape.js' import * as circled from '../modules/core/circled.js' export default class Ellipse extends Shape { - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('ellipse', node), attrs) } - size (width, height) { + size(width, height) { const p = proportionalSize(this, width, height) - return this - .rx(new SVGNumber(p.width).divide(2)) - .ry(new SVGNumber(p.height).divide(2)) + return this.rx(new SVGNumber(p.width).divide(2)).ry( + new SVGNumber(p.height).divide(2) + ) } } diff --git a/src/elements/ForeignObject.js b/src/elements/ForeignObject.js index 0a417b0..a4148d5 100644 --- a/src/elements/ForeignObject.js +++ b/src/elements/ForeignObject.js @@ -3,7 +3,7 @@ import { registerMethods } from '../utils/methods.js' import Element from './Element.js' export default class ForeignObject extends Element { - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('foreignObject', node), attrs) } } diff --git a/src/elements/Fragment.js b/src/elements/Fragment.js index d2c4764..ece3046 100644 --- a/src/elements/Fragment.js +++ b/src/elements/Fragment.js @@ -3,12 +3,12 @@ import { globals } from '../utils/window.js' import { register, create } from '../utils/adopter.js' class Fragment extends Dom { - constructor (node = globals.document.createDocumentFragment()) { + constructor(node = globals.document.createDocumentFragment()) { super(node) } // Import / Export raw xml - xml (xmlOrFn, outerXML, ns) { + xml(xmlOrFn, outerXML, ns) { if (typeof xmlOrFn === 'boolean') { ns = outerXML outerXML = xmlOrFn @@ -27,7 +27,6 @@ class Fragment extends Dom { // Act as setter if we got a string return super.xml(xmlOrFn, false, ns) } - } register(Fragment, 'Fragment') diff --git a/src/elements/G.js b/src/elements/G.js index b3a999e..4d3b03c 100644 --- a/src/elements/G.js +++ b/src/elements/G.js @@ -1,10 +1,15 @@ -import { nodeOrNew, register, wrapWithAttrCheck, extend } from '../utils/adopter.js' +import { + nodeOrNew, + register, + wrapWithAttrCheck, + extend +} from '../utils/adopter.js' import { registerMethods } from '../utils/methods.js' import Container from './Container.js' import * as containerGeometry from '../modules/core/containerGeometry.js' export default class G extends Container { - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('g', node), attrs) } } diff --git a/src/elements/Gradient.js b/src/elements/Gradient.js index d3fa15b..1631c14 100644 --- a/src/elements/Gradient.js +++ b/src/elements/Gradient.js @@ -11,7 +11,7 @@ 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), attrs @@ -19,26 +19,26 @@ export default class Gradient extends Container { } // custom attr to handle transform - attr (a, b, c) { + attr(a, b, c) { if (a === 'transform') a = 'gradientTransform' return super.attr(a, b, c) } - bbox () { + bbox() { return new Box() } - targets () { + targets() { return baseFind('svg [fill*=' + this.id() + ']') } // Alias string conversion to fill - toString () { + toString() { return this.url() } // Update gradient - update (block) { + update(block) { // remove all stops this.clear() @@ -51,7 +51,7 @@ export default class Gradient extends Container { } // Return the fill id - url () { + url() { return 'url(#' + this.id() + ')' } } @@ -61,7 +61,7 @@ extend(Gradient, gradiented) registerMethods({ Container: { // Create gradient element in defs - gradient (...args) { + gradient(...args) { return this.defs().gradient(...args) } }, diff --git a/src/elements/Image.js b/src/elements/Image.js index c51bc9a..080da16 100644 --- a/src/elements/Image.js +++ b/src/elements/Image.js @@ -9,35 +9,40 @@ import Shape from './Shape.js' import { globals } from '../utils/window.js' export default class Image extends Shape { - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('image', node), attrs) } // (re)load image - load (url, callback) { + load(url, callback) { if (!url) return this const img = new globals.window.Image() - on(img, 'load', function (e) { - const p = this.parent(Pattern) + on( + img, + 'load', + function (e) { + const p = this.parent(Pattern) - // ensure image size - if (this.width() === 0 && this.height() === 0) { - this.size(img.width, img.height) - } + // ensure image size + if (this.width() === 0 && this.height() === 0) { + this.size(img.width, img.height) + } - 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 instanceof Pattern) { + // ensure pattern size if not set + if (p.width() === 0 && p.height() === 0) { + p.size(this.width(), this.height()) + } } - } - if (typeof callback === 'function') { - callback.call(this, e) - } - }, this) + if (typeof callback === 'function') { + callback.call(this, e) + } + }, + this + ) on(img, 'load error', function () { // dont forget to unbind memory leaking events @@ -57,9 +62,12 @@ registerAttrHook(function (attr, val, _this) { } if (val instanceof Image) { - val = _this.root().defs().pattern(0, 0, (pattern) => { - pattern.add(val) - }) + val = _this + .root() + .defs() + .pattern(0, 0, (pattern) => { + pattern.add(val) + }) } return val diff --git a/src/elements/Line.js b/src/elements/Line.js index 9350a23..0dab35d 100644 --- a/src/elements/Line.js +++ b/src/elements/Line.js @@ -12,25 +12,25 @@ import * as pointed from '../modules/core/pointed.js' export default class Line extends Shape { // Initialize node - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('line', node), attrs) } // Get array - array () { + array() { return new PointArray([ - [ this.attr('x1'), this.attr('y1') ], - [ this.attr('x2'), this.attr('y2') ] + [this.attr('x1'), this.attr('y1')], + [this.attr('x2'), this.attr('y2')] ]) } // Move by left top corner - move (x, y) { + move(x, y) { return this.attr(this.array().move(x, y).toLine()) } // Overwrite native plot() method - plot (x1, y1, x2, y2) { + plot(x1, y1, x2, y2) { if (x1 == null) { return this.array() } else if (typeof y1 !== 'undefined') { @@ -43,7 +43,7 @@ export default class Line extends Shape { } // Set element size to given width and height - size (width, height) { + size(width, height) { const p = proportionalSize(this, width, height) return this.attr(this.array().size(p.width, p.height).toLine()) } @@ -58,8 +58,8 @@ registerMethods({ // 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()) - , args[0] != null ? args : [ 0, 0, 0, 0 ] + this.put(new Line()), + args[0] != null ? args : [0, 0, 0, 0] ) }) } diff --git a/src/elements/Marker.js b/src/elements/Marker.js index d6f98c8..5ddf802 100644 --- a/src/elements/Marker.js +++ b/src/elements/Marker.js @@ -4,31 +4,31 @@ import Container from './Container.js' export default class Marker extends Container { // Initialize node - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('marker', node), attrs) } // Set height of element - height (height) { + height(height) { return this.attr('markerHeight', height) } - orient (orient) { + orient(orient) { return this.attr('orient', orient) } // Set marker refX and refY - ref (x, y) { + ref(x, y) { return this.attr('refX', x).attr('refY', y) } // Return the fill id - toString () { + toString() { return 'url(#' + this.id() + ')' } // Update marker - update (block) { + update(block) { // remove all content this.clear() @@ -41,15 +41,14 @@ export default class Marker extends Container { } // Set width of element - width (width) { + width(width) { return this.attr('markerWidth', width) } - } registerMethods({ Container: { - marker (...args) { + marker(...args) { // Create marker element in defs return this.defs().marker(...args) } @@ -68,17 +67,18 @@ registerMethods({ }, marker: { // Create and attach markers - marker (marker, width, height, block) { - let attr = [ 'marker' ] + marker(marker, width, height, block) { + let attr = ['marker'] // Build attribute name 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) + marker = + arguments[1] instanceof Marker + ? arguments[1] + : this.defs().marker(width, height, block) return this.attr(attr, marker) } diff --git a/src/elements/Mask.js b/src/elements/Mask.js index 5b462f7..b8a2c99 100644 --- a/src/elements/Mask.js +++ b/src/elements/Mask.js @@ -5,12 +5,12 @@ import baseFind from '../modules/core/selector.js' export default class Mask extends Container { // Initialize node - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('mask', node), attrs) } // Unmask all masked elements and remove itself - remove () { + remove() { // unmask all targets this.targets().forEach(function (el) { el.unmask() @@ -20,7 +20,7 @@ export default class Mask extends Container { return super.remove() } - targets () { + targets() { return baseFind('svg [mask*=' + this.id() + ']') } } @@ -33,22 +33,21 @@ registerMethods({ }, Element: { // Distribute mask to svg element - masker () { + masker() { return this.reference('mask') }, - maskWith (element) { + maskWith(element) { // use given mask or create a new one - const masker = element instanceof Mask - ? element - : this.parent().mask().add(element) + const masker = + element instanceof Mask ? element : this.parent().mask().add(element) // apply mask return this.attr('mask', 'url(#' + masker.id() + ')') }, // Unmask element - unmask () { + unmask() { return this.attr('mask', null) } } diff --git a/src/elements/Path.js b/src/elements/Path.js index 2aa0a51..ec9a19f 100644 --- a/src/elements/Path.js +++ b/src/elements/Path.js @@ -6,59 +6,65 @@ import Shape from './Shape.js' export default class Path extends Shape { // Initialize node - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('path', node), attrs) } // Get array - array () { + array() { return this._array || (this._array = new PathArray(this.attr('d'))) } // Clear array cache - clear () { + clear() { delete this._array return this } // 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) } // Move by left top corner - move (x, y) { + move(x, y) { return this.attr('d', this.array().move(x, y)) } // Plot new path - plot (d) { - return (d == null) + plot(d) { + return d == null ? this.array() - : this.clear().attr('d', typeof d === 'string' ? d : (this._array = new PathArray(d))) + : this.clear().attr( + 'd', + typeof d === 'string' ? d : (this._array = new PathArray(d)) + ) } // Set element size to given width and height - size (width, height) { + size(width, height) { const 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) } // Move by left top corner over x-axis - x (x) { + x(x) { return x == null ? this.bbox().x : this.move(x, this.bbox().y) } // Move by left top corner over y-axis - y (y) { + y(y) { return y == null ? this.bbox().y : this.move(this.bbox().x, y) } - } // Define morphable array diff --git a/src/elements/Pattern.js b/src/elements/Pattern.js index 18a75e8..b42a83a 100644 --- a/src/elements/Pattern.js +++ b/src/elements/Pattern.js @@ -6,31 +6,31 @@ import baseFind from '../modules/core/selector.js' export default class Pattern extends Container { // Initialize node - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('pattern', node), attrs) } // custom attr to handle transform - attr (a, b, c) { + attr(a, b, c) { if (a === 'transform') a = 'patternTransform' return super.attr(a, b, c) } - bbox () { + bbox() { return new Box() } - targets () { + targets() { return baseFind('svg [fill*=' + this.id() + ']') } // Alias string conversion to fill - toString () { + toString() { return this.url() } // Update pattern by rebuilding - update (block) { + update(block) { // remove content this.clear() @@ -43,16 +43,15 @@ export default class Pattern extends Container { } // Return the fill id - url () { + url() { return 'url(#' + this.id() + ')' } - } registerMethods({ Container: { // Create pattern element in defs - pattern (...args) { + pattern(...args) { return this.defs().pattern(...args) } }, diff --git a/src/elements/Polygon.js b/src/elements/Polygon.js index 0c99aa7..d64dcb3 100644 --- a/src/elements/Polygon.js +++ b/src/elements/Polygon.js @@ -12,7 +12,7 @@ import * as poly from '../modules/core/poly.js' export default class Polygon extends Shape { // Initialize node - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('polygon', node), attrs) } } diff --git a/src/elements/Polyline.js b/src/elements/Polyline.js index e390da3..2f063f2 100644 --- a/src/elements/Polyline.js +++ b/src/elements/Polyline.js @@ -12,7 +12,7 @@ import * as poly from '../modules/core/poly.js' export default class Polyline extends Shape { // Initialize node - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('polyline', node), attrs) } } diff --git a/src/elements/Rect.js b/src/elements/Rect.js index 0ed85fc..749cf6d 100644 --- a/src/elements/Rect.js +++ b/src/elements/Rect.js @@ -10,7 +10,7 @@ import Shape from './Shape.js' export default class Rect extends Shape { // Initialize node - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('rect', node), attrs) } } diff --git a/src/elements/Stop.js b/src/elements/Stop.js index d29090c..193256e 100644 --- a/src/elements/Stop.js +++ b/src/elements/Stop.js @@ -4,12 +4,12 @@ import SVGNumber from '../types/SVGNumber.js' import { registerMethods } from '../utils/methods.js' export default class Stop extends Element { - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('stop', node), attrs) } // add color stops - update (o) { + update(o) { if (typeof o === 'number' || o instanceof SVGNumber) { o = { offset: arguments[0], diff --git a/src/elements/Style.js b/src/elements/Style.js index f7c3c57..fc1a27e 100644 --- a/src/elements/Style.js +++ b/src/elements/Style.js @@ -3,7 +3,7 @@ import { registerMethods } from '../utils/methods.js' import { unCamelCase } from '../utils/utils.js' import Element from './Element.js' -function cssRule (selector, rule) { +function cssRule(selector, rule) { if (!selector) return '' if (!rule) return selector @@ -19,16 +19,16 @@ function cssRule (selector, rule) { } export default class Style extends Element { - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('style', node), attrs) } - addText (w = '') { + addText(w = '') { this.node.textContent += w return this } - font (name, src, params = {}) { + font(name, src, params = {}) { return this.rule('@font-face', { fontFamily: name, src: src, @@ -36,16 +36,16 @@ export default class Style extends Element { }) } - rule (selector, obj) { + rule(selector, obj) { return this.addText(cssRule(selector, obj)) } } registerMethods('Dom', { - style (selector, obj) { + style(selector, obj) { return this.put(new Style()).rule(selector, obj) }, - fontface (name, src, params) { + fontface(name, src, params) { return this.put(new Style()).font(name, src, params) } }) diff --git a/src/elements/Svg.js b/src/elements/Svg.js index acddf34..7b36daa 100644 --- a/src/elements/Svg.js +++ b/src/elements/Svg.js @@ -11,34 +11,35 @@ import Defs from './Defs.js' import { globals } from '../utils/window.js' export default class Svg extends Container { - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('svg', node), attrs) this.namespace() } // Creates and returns defs element - defs () { + defs() { if (!this.isRoot()) return this.root().defs() - return adopt(this.node.querySelector('defs')) - || this.put(new Defs()) + return adopt(this.node.querySelector('defs')) || this.put(new Defs()) } - isRoot () { - return !this.node.parentNode - || (!(this.node.parentNode instanceof globals.window.SVGElement) && this.node.parentNode.nodeName !== '#document-fragment') + isRoot() { + return ( + !this.node.parentNode || + (!(this.node.parentNode instanceof globals.window.SVGElement) && + this.node.parentNode.nodeName !== '#document-fragment') + ) } // Add namespaces - namespace () { + namespace() { if (!this.isRoot()) return this.root().namespace() - return this - .attr({ xmlns: svg, version: '1.1' }) + return this.attr({ xmlns: svg, version: '1.1' }) .attr('xmlns:xlink', xlink, xmlns) .attr('xmlns:svgjs', svgjs, xmlns) } - removeNamespace () { + removeNamespace() { return this.attr({ xmlns: null, version: null }) .attr('xmlns:xlink', null, xmlns) .attr('xmlns:svgjs', null, xmlns) @@ -46,11 +47,10 @@ export default class Svg extends Container { // Check if this is a root svg // If not, call root() from this element - root () { + root() { if (this.isRoot()) return this return super.root() } - } registerMethods({ diff --git a/src/elements/Symbol.js b/src/elements/Symbol.js index d2a98ac..28ad206 100644 --- a/src/elements/Symbol.js +++ b/src/elements/Symbol.js @@ -4,7 +4,7 @@ import Container from './Container.js' export default class Symbol extends Container { // Initialize node - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('symbol', node), attrs) } } diff --git a/src/elements/Text.js b/src/elements/Text.js index f716f83..39371f6 100644 --- a/src/elements/Text.js +++ b/src/elements/Text.js @@ -13,7 +13,7 @@ import * as textable from '../modules/core/textable.js' export default class Text extends Shape { // Initialize node - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('text', node), attrs) this.dom.leading = new SVGNumber(1.3) // store leading value for rebuilding @@ -22,7 +22,7 @@ export default class Text extends Shape { } // Set / get leading - leading (value) { + leading(value) { // act as getter if (value == null) { return this.dom.leading @@ -35,7 +35,7 @@ export default class Text extends Shape { } // Rebuild appearance type - rebuild (rebuild) { + rebuild(rebuild) { // store new rebuild flag if given if (typeof rebuild === 'boolean') { this._rebuild = rebuild @@ -48,7 +48,8 @@ export default class Text extends Shape { const leading = this.dom.leading this.each(function (i) { - const fontSize = globals.window.getComputedStyle(this.node) + const fontSize = globals.window + .getComputedStyle(this.node) .getPropertyValue('font-size') const dy = leading * new SVGNumber(fontSize) @@ -72,14 +73,14 @@ export default class Text extends Shape { } // overwrite method from parent to set data properly - setData (o) { + setData(o) { this.dom = o this.dom.leading = new SVGNumber(o.leading || 1.3) return this } // Set the text content - text (text) { + text(text) { // act as getter if (text === undefined) { const children = this.node.childNodes @@ -94,7 +95,11 @@ export default class Text extends Shape { } // 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' } @@ -124,7 +129,6 @@ export default class Text extends Shape { // disable build mode and rebuild lines return this.build(false).rebuild() } - } extend(Text, textable) diff --git a/src/elements/TextPath.js b/src/elements/TextPath.js index 2af73e7..89c6c42 100644 --- a/src/elements/TextPath.js +++ b/src/elements/TextPath.js @@ -8,19 +8,19 @@ import baseFind from '../modules/core/selector.js' export default class TextPath extends Text { // Initialize node - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('textPath', node), attrs) } // return the array of the path track element - array () { + array() { const track = this.track() return track ? track.array() : null } // Plot path if any - plot (d) { + plot(d) { const track = this.track() let pathArray = null @@ -28,11 +28,11 @@ export default class TextPath extends Text { pathArray = track.plot(d) } - return (d == null) ? pathArray : this + return d == null ? pathArray : this } // Get the path element - track () { + track() { return this.reference('href') } } @@ -75,7 +75,7 @@ registerMethods({ }), // Get the textPath children - textPath () { + textPath() { return this.findOne('textPath') } }, @@ -91,7 +91,7 @@ registerMethods({ return text.path(this) }), - targets () { + targets() { return baseFind('svg textPath').filter((node) => { return (node.attr('href') || '').includes(this.id()) }) diff --git a/src/elements/Tspan.js b/src/elements/Tspan.js index 73cd52d..12b49f8 100644 --- a/src/elements/Tspan.js +++ b/src/elements/Tspan.js @@ -13,23 +13,23 @@ import * as textable from '../modules/core/textable.js' export default class Tspan extends Shape { // Initialize node - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('tspan', node), attrs) this._build = false // disable build mode for adding multiple lines } // Shortcut dx - dx (dx) { + dx(dx) { return this.attr('dx', dx) } // Shortcut dy - dy (dy) { + dy(dy) { return this.attr('dy', dy) } // Create new line - newLine () { + newLine() { // mark new line this.dom.newLined = true @@ -43,7 +43,8 @@ export default class Tspan extends Shape { const i = text.index(this) - const fontSize = globals.window.getComputedStyle(this.node) + const fontSize = globals.window + .getComputedStyle(this.node) .getPropertyValue('font-size') const dy = text.dom.leading * new SVGNumber(fontSize) @@ -52,8 +53,9 @@ export default class Tspan extends Shape { } // 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' : '') if (typeof text === 'function') { this.clear().build(true) @@ -65,7 +67,6 @@ export default class Tspan extends Shape { return this } - } extend(Tspan, textable) diff --git a/src/elements/Use.js b/src/elements/Use.js index 30d9436..e92dd48 100644 --- a/src/elements/Use.js +++ b/src/elements/Use.js @@ -4,12 +4,12 @@ import { xlink } from '../modules/core/namespaces.js' import Shape from './Shape.js' export default class Use extends Shape { - constructor (node, attrs = node) { + constructor(node, attrs = node) { super(nodeOrNew('use', node), attrs) } // Use element as a reference - use (element, file) { + use(element, file) { // Set lined element return this.attr('href', (file || '') + '#' + element, xlink) } diff --git a/src/main.js b/src/main.js index 1ef1f27..5b652c4 100644 --- a/src/main.js +++ b/src/main.js @@ -77,7 +77,13 @@ export { /* Animation Modules */ export { default as Animator } from './animation/Animator.js' -export { Controller, Ease, PID, Spring, easing } from './animation/Controller.js' +export { + Controller, + Ease, + PID, + Spring, + easing +} from './animation/Controller.js' export { default as Queue } from './animation/Queue.js' export { default as Runner } from './animation/Runner.js' export { default as Timeline } from './animation/Timeline.js' @@ -126,43 +132,24 @@ 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([ - Svg, - Symbol, - Image, - Pattern, - Marker -], getMethodsFor('viewbox')) - -extend([ - Line, - Polyline, - Polygon, - Path -], getMethodsFor('marker')) +extend([Svg, Symbol, Image, Pattern, Marker], getMethodsFor('viewbox')) + +extend([Line, Polyline, Polygon, Path], getMethodsFor('marker')) extend(Text, getMethodsFor('Text')) extend(Path, getMethodsFor('Path')) extend(Defs, getMethodsFor('Defs')) -extend([ - Text, - Tspan -], getMethodsFor('Tspan')) +extend([Text, Tspan], getMethodsFor('Tspan')) -extend([ - Rect, - Ellipse, - Gradient, - Runner -], getMethodsFor('radius')) +extend([Rect, Ellipse, Gradient, Runner], getMethodsFor('radius')) extend(EventTarget, getMethodsFor('EventTarget')) extend(Dom, getMethodsFor('Dom')) extend(Element, getMethodsFor('Element')) extend(Shape, getMethodsFor('Shape')) -extend([ Container, Fragment ], getMethodsFor('Container')) +extend([Container, Fragment], getMethodsFor('Container')) extend(Gradient, getMethodsFor('Gradient')) extend(Runner, getMethodsFor('Runner')) diff --git a/src/modules/core/attr.js b/src/modules/core/attr.js index d54b235..a96f706 100644 --- a/src/modules/core/attr.js +++ b/src/modules/core/attr.js @@ -5,12 +5,12 @@ import SVGArray from '../../types/SVGArray.js' import SVGNumber from '../../types/SVGNumber.js' const hooks = [] -export function registerAttrHook (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) { // get an object of attributes @@ -42,8 +42,8 @@ export default function attr (attr, val, ns) { return val == null ? defaults[attr] : isNumber.test(val) - ? parseFloat(val) - : val + ? parseFloat(val) + : val } else { // Loop through hooks and execute them to convert value val = hooks.reduce((_val, hook) => { diff --git a/src/modules/core/circled.js b/src/modules/core/circled.js index a03e29b..3c3a65f 100644 --- a/src/modules/core/circled.js +++ b/src/modules/core/circled.js @@ -1,48 +1,42 @@ import SVGNumber from '../../types/SVGNumber.js' // Radius x value -export function rx (rx) { +export function rx(rx) { return this.attr('rx', rx) } // Radius y value -export function ry (ry) { +export function ry(ry) { return this.attr('ry', ry) } // Move over x-axis -export function x (x) { - return x == null - ? this.cx() - this.rx() - : this.cx(x + this.rx()) +export function x(x) { + return x == null ? this.cx() - this.rx() : this.cx(x + this.rx()) } // Move over y-axis -export function y (y) { - return y == null - ? this.cy() - this.ry() - : this.cy(y + this.ry()) +export function y(y) { + return y == null ? this.cy() - this.ry() : this.cy(y + this.ry()) } // Move by center over x-axis -export function cx (x) { +export function cx(x) { return this.attr('cx', x) } // Move by center over y-axis -export function cy (y) { +export function cy(y) { return this.attr('cy', y) } // Set width of element -export function width (width) { - return width == null - ? this.rx() * 2 - : this.rx(new SVGNumber(width).divide(2)) +export function width(width) { + return width == null ? this.rx() * 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)) diff --git a/src/modules/core/containerGeometry.js b/src/modules/core/containerGeometry.js index 908bb27..21139e8 100644 --- a/src/modules/core/containerGeometry.js +++ b/src/modules/core/containerGeometry.js @@ -2,9 +2,8 @@ import Matrix from '../../types/Matrix.js' import Point from '../../types/Point.js' import { proportionalSize } from '../../utils/utils.js' -export function dmove (dx, dy) { - this.children().forEach((child, i) => { - +export function dmove(dx, dy) { + this.children().forEach((child) => { let bbox // We have to wrap this for elements that dont have a bbox @@ -30,32 +29,32 @@ export function dmove (dx, dy) { return this } -export function dx (dx) { +export function dx(dx) { return this.dmove(dx, 0) } -export function dy (dy) { +export function dy(dy) { return this.dmove(0, dy) } -export function height (height, box = this.bbox()) { +export function height(height, box = this.bbox()) { if (height == null) return box.height return this.size(box.width, height, box) } -export function move (x = 0, y = 0, box = this.bbox()) { +export function move(x = 0, y = 0, box = this.bbox()) { const dx = x - box.x const dy = y - box.y return this.dmove(dx, dy) } -export function size (width, height, box = this.bbox()) { +export function size(width, height, box = this.bbox()) { const p = proportionalSize(this, width, height, box) const scaleX = p.width / box.width const scaleY = p.height / box.height - this.children().forEach((child, i) => { + this.children().forEach((child) => { const o = new Point(box).transform(new Matrix(child).inverse()) child.scale(scaleX, scaleY, o.x, o.y) }) @@ -63,17 +62,17 @@ export function size (width, height, box = this.bbox()) { return this } -export function width (width, box = this.bbox()) { +export function width(width, box = this.bbox()) { if (width == null) return box.width return this.size(width, box.height, box) } -export function x (x, box = this.bbox()) { +export function x(x, box = this.bbox()) { if (x == null) return box.x return this.move(x, box.y, box) } -export function y (y, box = this.bbox()) { +export function y(y, box = this.bbox()) { if (y == null) return box.y return this.move(box.x, y, box) } diff --git a/src/modules/core/defaults.js b/src/modules/core/defaults.js index e8e65b6..2c346a7 100644 --- a/src/modules/core/defaults.js +++ b/src/modules/core/defaults.js @@ -1,5 +1,4 @@ - -export function noop () {} +export function noop() {} // Default animation values export const timeline = { @@ -10,7 +9,6 @@ export const timeline = { // Default attribute values export const attrs = { - // fill and stroke 'fill-opacity': 1, 'stroke-opacity': 1, diff --git a/src/modules/core/event.js b/src/modules/core/event.js index 3594fc4..8e08716 100644 --- a/src/modules/core/event.js +++ b/src/modules/core/event.js @@ -5,7 +5,7 @@ import { globals } from '../../utils/window.js' let listenerId = 0 export const windowEvents = {} -export function getEvents (instance) { +export function getEvents(instance) { let n = instance.getEventHolder() // We dont want to save events in global space @@ -14,18 +14,18 @@ export function getEvents (instance) { return n.events } -export function getEventTarget (instance) { +export function getEventTarget(instance) { return instance.getEventTarget() } -export function clearEvents (instance) { +export function clearEvents(instance) { let n = instance.getEventHolder() if (n === globals.window) n = windowEvents if (n.events) n.events = {} } // Add event binder in the SVG namespace -export function on (node, events, listener, binding, options) { +export function on(node, events, listener, binding, options) { const l = listener.bind(binding || node) const instance = makeInstance(node) const bag = getEvents(instance) @@ -56,7 +56,7 @@ export function on (node, events, listener, binding, options) { } // Add event unbinder in the SVG namespace -export function off (node, events, listener, options) { +export function off(node, events, listener, options) { const instance = makeInstance(node) const bag = getEvents(instance) const n = getEventTarget(instance) @@ -79,7 +79,11 @@ export function off (node, events, listener, options) { // remove listener reference 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] } @@ -87,7 +91,7 @@ export function off (node, events, listener, options) { // 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) + off(n, [ev, ns].join('.'), l) } delete bag[ev][ns] @@ -97,7 +101,7 @@ export function off (node, events, listener, options) { for (event in bag) { for (namespace in bag[event]) { if (ns === namespace) { - off(n, [ event, ns ].join('.')) + off(n, [event, ns].join('.')) } } } @@ -105,7 +109,7 @@ export function off (node, events, listener, options) { // remove all listeners for the event if (bag[ev]) { for (namespace in bag[ev]) { - off(n, [ ev, namespace ].join('.')) + off(n, [ev, namespace].join('.')) } delete bag[ev] @@ -121,14 +125,18 @@ export function off (node, events, listener, options) { }) } -export function dispatch (node, event, data, options) { +export function dispatch(node, event, data, options) { const n = getEventTarget(node) // Dispatch event if (event instanceof globals.window.Event) { n.dispatchEvent(event) } else { - event = new globals.window.CustomEvent(event, { detail: data, cancelable: true, ...options }) + event = new globals.window.CustomEvent(event, { + detail: data, + cancelable: true, + ...options + }) n.dispatchEvent(event) } return event diff --git a/src/modules/core/gradiented.js b/src/modules/core/gradiented.js index 6c744e4..cd0a512 100644 --- a/src/modules/core/gradiented.js +++ b/src/modules/core/gradiented.js @@ -1,12 +1,12 @@ import SVGNumber from '../../types/SVGNumber.js' -export function from (x, 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) { +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 4f92657..fc48c3b 100644 --- a/src/modules/core/parser.js +++ b/src/modules/core/parser.js @@ -1,7 +1,7 @@ import { globals } from '../../utils/window.js' import { makeInstance } from '../../utils/adopter.js' -export default function parser () { +export default function parser() { // Reuse cached element if possible if (!parser.nodes) { const svg = makeInstance().size(2, 0) diff --git a/src/modules/core/pointed.js b/src/modules/core/pointed.js index 540e5f8..0d4ef7a 100644 --- a/src/modules/core/pointed.js +++ b/src/modules/core/pointed.js @@ -3,23 +3,23 @@ import PointArray from '../../types/PointArray.js' export const MorphArray = PointArray // Move by left top corner over x-axis -export function x (x) { +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) { +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) { const b = this.bbox() return width == null ? b.width : this.size(width, b.height) } // Set height of element -export function height (height) { +export function height(height) { const b = this.bbox() 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 d422028..0640735 100644 --- a/src/modules/core/poly.js +++ b/src/modules/core/poly.js @@ -2,32 +2,33 @@ import { proportionalSize } from '../../utils/utils.js' import PointArray from '../../types/PointArray.js' // Get array -export function array () { +export function array() { return this._array || (this._array = new PointArray(this.attr('points'))) } // Clear array cache -export function clear () { +export function clear() { delete this._array return this } // Move by left top corner -export function move (x, y) { +export function move(x, y) { return this.attr('points', this.array().move(x, y)) } // Plot new path -export function plot (p) { - return (p == null) +export function plot(p) { + return p == null ? this.array() - : this.clear().attr('points', typeof p === 'string' - ? p - : (this._array = new PointArray(p))) + : this.clear().attr( + 'points', + typeof p === 'string' ? p : (this._array = new PointArray(p)) + ) } // Set element size to given width and height -export function size (width, height) { +export function size(width, height) { const p = proportionalSize(this, width, height) return this.attr('points', this.array().size(p.width, p.height)) } diff --git a/src/modules/core/regex.js b/src/modules/core/regex.js index a18c692..03d1fa3 100644 --- a/src/modules/core/regex.js +++ b/src/modules/core/regex.js @@ -1,5 +1,6 @@ // Parse unit value -export const numberAndUnit = /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i +export const numberAndUnit = + /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i // Parse hex value export const hex = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i diff --git a/src/modules/core/selector.js b/src/modules/core/selector.js index 1667d4d..7dec4e4 100644 --- a/src/modules/core/selector.js +++ b/src/modules/core/selector.js @@ -3,17 +3,19 @@ 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) { +export function find(query) { return baseFind(query, this.node) } -export function findOne (query) { +export function findOne(query) { return adopt(this.node.querySelector(query)) } diff --git a/src/modules/core/textable.js b/src/modules/core/textable.js index 28b13cb..44a1ee5 100644 --- a/src/modules/core/textable.js +++ b/src/modules/core/textable.js @@ -1,7 +1,7 @@ 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) { this.clear() @@ -14,14 +14,14 @@ export function plain (text) { } // Get length of text element -export function length () { +export function length() { return this.node.getComputedTextLength() } // Move over x-axis // Text is moved by its bounding box // text-anchor does NOT matter -export function x (x, box = this.bbox()) { +export function x(x, box = this.bbox()) { if (x == null) { return box.x } @@ -30,7 +30,7 @@ export function x (x, box = this.bbox()) { } // Move over y-axis -export function y (y, box = this.bbox()) { +export function y(y, box = this.bbox()) { if (y == null) { return box.y } @@ -38,12 +38,12 @@ export function y (y, box = this.bbox()) { return this.attr('y', this.attr('y') + y - box.y) } -export function move (x, y, box = this.bbox()) { +export function move(x, y, box = this.bbox()) { return this.x(x, box).y(y, box) } // Move center over x-axis -export function cx (x, box = this.bbox()) { +export function cx(x, box = this.bbox()) { if (x == null) { return box.cx } @@ -52,7 +52,7 @@ export function cx (x, box = this.bbox()) { } // Move center over y-axis -export function cy (y, box = this.bbox()) { +export function cy(y, box = this.bbox()) { if (y == null) { return box.cy } @@ -60,24 +60,24 @@ export function cy (y, box = this.bbox()) { return this.attr('y', this.attr('y') + y - box.cy) } -export function center (x, y, box = this.bbox()) { +export function center(x, y, box = this.bbox()) { return this.cx(x, box).cy(y, box) } -export function ax (x) { +export function ax(x) { return this.attr('x', x) } -export function ay (y) { +export function ay(y) { return this.attr('y', y) } -export function amove (x, y) { +export function amove(x, y) { return this.ax(x).ay(y) } // Enable / disable build mode -export function build (build) { +export function build(build) { this._build = !!build return this } diff --git a/src/modules/optional/arrange.js b/src/modules/optional/arrange.js index 9aaeef1..292cd79 100644 --- a/src/modules/optional/arrange.js +++ b/src/modules/optional/arrange.js @@ -2,27 +2,27 @@ import { makeInstance } from '../../utils/adopter.js' import { registerMethods } from '../../utils/methods.js' // Get all siblings, including myself -export function siblings () { +export function siblings() { return this.parent().children() } // Get the current position siblings -export function position () { +export function position() { return this.parent().index(this) } // Get the next element (will return null if there is none) -export function next () { +export function next() { return this.siblings()[this.position() + 1] } // Get the next element (will return null if there is none) -export function prev () { +export function prev() { return this.siblings()[this.position() - 1] } // Send given element one step forward -export function forward () { +export function forward() { const i = this.position() const p = this.parent() @@ -33,7 +33,7 @@ export function forward () { } // Send given element one step backward -export function backward () { +export function backward() { const i = this.position() const p = this.parent() @@ -43,7 +43,7 @@ export function backward () { } // Send given element all the way to the front -export function front () { +export function front() { const p = this.parent() // Move node forward @@ -53,7 +53,7 @@ export function front () { } // Send given element all the way to the back -export function back () { +export function back() { const p = this.parent() // Move node back @@ -63,7 +63,7 @@ export function back () { } // Inserts a given element before the targeted element -export function before (element) { +export function before(element) { element = makeInstance(element) element.remove() @@ -75,7 +75,7 @@ export function before (element) { } // Inserts a given element after the targeted element -export function after (element) { +export function after(element) { element = makeInstance(element) element.remove() @@ -86,13 +86,13 @@ export function after (element) { return this } -export function insertBefore (element) { +export function insertBefore(element) { element = makeInstance(element) element.before(this) return this } -export function insertAfter (element) { +export function insertAfter(element) { element = makeInstance(element) element.after(this) return this diff --git a/src/modules/optional/class.js b/src/modules/optional/class.js index 4e544be..3141644 100644 --- a/src/modules/optional/class.js +++ b/src/modules/optional/class.js @@ -2,18 +2,18 @@ import { delimiter } from '../core/regex.js' import { registerMethods } from '../../utils/methods.js' // Return array of classes on the node -export function classes () { +export function classes() { const 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) { +export function hasClass(name) { return this.classes().indexOf(name) !== -1 } // Add class to the node -export function addClass (name) { +export function addClass(name) { if (!this.hasClass(name)) { const array = this.classes() array.push(name) @@ -24,21 +24,30 @@ export function addClass (name) { } // Remove class from the node -export function removeClass (name) { +export function removeClass(name) { if (this.hasClass(name)) { - this.attr('class', this.classes().filter(function (c) { - return c !== name - }).join(' ')) + this.attr( + 'class', + this.classes() + .filter(function (c) { + return c !== name + }) + .join(' ') + ) } return this } // Toggle the presence of a class on the node -export function toggleClass (name) { +export function toggleClass(name) { return this.hasClass(name) ? this.removeClass(name) : this.addClass(name) } registerMethods('Dom', { - classes, hasClass, addClass, removeClass, toggleClass + classes, + hasClass, + addClass, + removeClass, + toggleClass }) diff --git a/src/modules/optional/css.js b/src/modules/optional/css.js index ee93869..92f8c21 100644 --- a/src/modules/optional/css.js +++ b/src/modules/optional/css.js @@ -3,11 +3,12 @@ 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) { const ret = {} if (arguments.length === 0) { // get full style as object - this.node.style.cssText.split(/\s*;\s*/) + this.node.style.cssText + .split(/\s*;\s*/) .filter(function (el) { return !!el.length }) @@ -37,36 +38,39 @@ export function css (style, val) { if (typeof style === 'object') { for (const 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 + this.node.style[camelCase(style)] = + val == null || isBlank.test(val) ? '' : val } return this } // Show element -export function show () { +export function show() { return this.css('display', '') } // Hide element -export function hide () { +export function hide() { return this.css('display', 'none') } // Is element visible? -export function visible () { +export function visible() { return this.css('display') !== 'none' } registerMethods('Dom', { - css, show, hide, visible + css, + show, + hide, + visible }) diff --git a/src/modules/optional/data.js b/src/modules/optional/data.js index 00bb8ea..9655048 100644 --- a/src/modules/optional/data.js +++ b/src/modules/optional/data.js @@ -2,10 +2,18 @@ import { registerMethods } from '../../utils/methods.js' import { filter, map } from '../../utils/utils.js' // Store data values on svg nodes -export function data (a, v, r) { +export function data(a, v, r) { if (a == null) { // get an object of attributes - return this.data(map(filter(this.node.attributes, (el) => el.nodeName.indexOf('data-') === 0), (el) => el.nodeName.slice(5))) + return this.data( + map( + filter( + this.node.attributes, + (el) => el.nodeName.indexOf('data-') === 0 + ), + (el) => el.nodeName.slice(5) + ) + ) } else if (a instanceof Array) { const data = {} for (const key of a) { @@ -23,12 +31,13 @@ export function data (a, v, r) { 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) + ? v + : JSON.stringify(v) ) } diff --git a/src/modules/optional/memory.js b/src/modules/optional/memory.js index 459dcf1..31058c3 100644 --- a/src/modules/optional/memory.js +++ b/src/modules/optional/memory.js @@ -1,7 +1,7 @@ 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 (const key in k) { @@ -19,7 +19,7 @@ export function remember (k, v) { } // Erase a given memory -export function forget () { +export function forget() { if (arguments.length === 0) { this._memory = {} } else { @@ -33,7 +33,7 @@ export function forget () { // 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 () { +export function memory() { return (this._memory = this._memory || {}) } diff --git a/src/modules/optional/sugar.js b/src/modules/optional/sugar.js index d4c3da5..aa5fb82 100644 --- a/src/modules/optional/sugar.js +++ b/src/modules/optional/sugar.js @@ -7,15 +7,24 @@ import SVGNumber from '../../types/SVGNumber.js' // Define list of available attributes for stroke and fill const sugar = { - stroke: [ 'color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset' ], - fill: [ 'color', 'opacity', 'rule' ], + stroke: [ + 'color', + 'width', + 'opacity', + 'linecap', + 'linejoin', + 'miterlimit', + 'dasharray', + 'dashoffset' + ], + fill: ['color', 'opacity', 'rule'], 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) { const extension = {} let i @@ -23,7 +32,12 @@ const sugar = { if (typeof o === 'undefined') { return this.attr(m) } - if (typeof o === 'string' || o instanceof Color || Color.isRgb(o) || (o instanceof Element)) { + if ( + typeof o === 'string' || + o instanceof Color || + Color.isRgb(o) || + o instanceof Element + ) { this.attr(m, o) } else { // set all attributes from sugar.fill and sugar.stroke list @@ -37,10 +51,10 @@ const sugar = { return this } - registerMethods([ 'Element', 'Runner' ], extension) + registerMethods(['Element', 'Runner'], extension) }) -registerMethods([ 'Element', 'Runner' ], { +registerMethods(['Element', 'Runner'], { // Let the user set the matrix directly matrix: function (mat, b, c, d, e, f) { // Act as a getter @@ -61,7 +75,7 @@ registerMethods([ 'Element', 'Runner' ], { 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, y], ox: cx, oy: cy }, true) }, shear: function (lam, cx, cy) { @@ -72,17 +86,17 @@ registerMethods([ 'Element', 'Runner' ], { 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, y], ox: cx, oy: cy }, true) }, // Map translate to transform translate: function (x, y) { - return this.transform({ translate: [ x, y ] }, true) + return this.transform({ translate: [x, y] }, true) }, // Map relative translations to transform relative: function (x, y) { - return this.transform({ relative: [ x, y ] }, true) + return this.transform({ relative: [x, y] }, true) }, // Map flip to transform @@ -122,7 +136,7 @@ registerMethods('Path', { } }) -registerMethods([ 'Element', 'Runner' ], { +registerMethods(['Element', 'Runner'], { // Set font font: function (a, v) { if (typeof a === 'object') { @@ -133,15 +147,21 @@ registerMethods([ 'Element', 'Runner' ], { return a === 'leading' ? this.leading(v) : a === 'anchor' - ? this.attr('text-anchor', v) - : a === 'size' || a === 'family' || a === 'weight' || a === 'stretch' || a === 'variant' || a === 'style' - ? this.attr('font-' + a, v) - : this.attr(a, v) + ? 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) } }) // Add events to elements -const methods = [ 'click', +const methods = [ + 'click', 'dblclick', 'mousedown', 'mouseup', @@ -154,7 +174,8 @@ 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) { diff --git a/src/modules/optional/transform.js b/src/modules/optional/transform.js index d8e7381..7f950b3 100644 --- a/src/modules/optional/transform.js +++ b/src/modules/optional/transform.js @@ -4,22 +4,24 @@ import { registerMethods } from '../../utils/methods.js' import Matrix from '../../types/Matrix.js' // Reset all transformations -export function untransform () { +export function untransform() { return this.attr('transform', null) } // merge the whole transformation chain into one matrix and returns it -export function matrixify () { +export function matrixify() { const 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 const kv = str.trim().split('(') - return [ kv[0], - kv[1].split(delimiter) - .map(function (str) { - return parseFloat(str) - }) + return [ + kv[0], + kv[1].split(delimiter).map(function (str) { + return parseFloat(str) + }) ] }) .reverse() @@ -35,7 +37,7 @@ export function matrixify () { } // add an element to another parent without changing the visual representation on the screen -export function toParent (parent, i) { +export function toParent(parent, i) { if (this === parent) return this const ctm = this.screenCTM() const pCtm = parent.screenCTM().inverse() @@ -46,12 +48,12 @@ export function toParent (parent, i) { } // same as above with parent equals root-svg -export function toRoot (i) { +export function toRoot(i) { return this.toParent(this.root(), i) } // 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') { const decomposed = new Matrix(this).decompose() @@ -64,11 +66,15 @@ export function transform (o, relative) { } // The user can pass a boolean, an Element or an Matrix or nothing - const cleanRelative = relative === true ? this : (relative || false) + const cleanRelative = relative === true ? this : relative || false const result = new Matrix(cleanRelative).transform(o) return this.attr('transform', result) } registerMethods('Element', { - untransform, matrixify, toParent, toRoot, transform + untransform, + matrixify, + toParent, + toRoot, + transform }) diff --git a/src/polyfills/children.js b/src/polyfills/children.js index 98e9143..690e23a 100644 --- a/src/polyfills/children.js +++ b/src/polyfills/children.js @@ -1,7 +1,7 @@ import { filter } from '../utils/utils.js' // IE11: children does not work for svg nodes -export default function children (node) { +export default function children(node) { return filter(node.childNodes, function (child) { return child.nodeType === 1 }) diff --git a/src/polyfills/innerHTML.js b/src/polyfills/innerHTML.js index 4f4140b..51632af 100644 --- a/src/polyfills/innerHTML.js +++ b/src/polyfills/innerHTML.js @@ -1,24 +1,29 @@ -/* globals SVGElement, DOMParser */ - -(function () { +;(function () { try { if (SVGElement.prototype.innerHTML) return - } catch (e) { return } + } catch (e) { + return + } const serializeXML = function (node, output) { const nodeType = node.nodeType if (nodeType === 3) { - output.push(node.textContent.replace(/&/, '&').replace(/</, '<').replace('>', '>')) + output.push( + node.textContent + .replace(/&/, '&') + .replace(/</, '<') + .replace('>', '>') + ) } else if (nodeType === 1) { output.push('<', node.tagName) if (node.hasAttributes()) { - [].forEach.call(node.attributes, function (attrNode) { + ;[].forEach.call(node.attributes, function (attrNode) { output.push(' ', attrNode.name, '="', attrNode.value, '"') }) } output.push('>') if (node.hasChildNodes()) { - [].forEach.call(node.childNodes, function (childNode) { + ;[].forEach.call(node.childNodes, function (childNode) { serializeXML(childNode, output) }) } else { @@ -49,8 +54,14 @@ const dXML = new DOMParser() dXML.async = false - const sXML = '<svg xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\'>' + markupText + '</svg>' - const svgDocElement = dXML.parseFromString(sXML, 'text/xml').documentElement + const sXML = + "<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>" + + markupText + + '</svg>' + const svgDocElement = dXML.parseFromString( + sXML, + 'text/xml' + ).documentElement let childNode = svgDocElement.firstChild while (childNode) { @@ -59,7 +70,7 @@ } } catch (e) { throw new Error('Can not set innerHTML on node') - }; + } } }) @@ -78,18 +89,27 @@ const dXML = new DOMParser() dXML.async = false - const sXML = '<svg xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\'>' + markupText + '</svg>' - const svgDocElement = dXML.parseFromString(sXML, 'text/xml').documentElement + const sXML = + "<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>" + + markupText + + '</svg>' + const svgDocElement = dXML.parseFromString( + sXML, + 'text/xml' + ).documentElement let childNode = svgDocElement.firstChild while (childNode) { - this.parentNode.insertBefore(this.ownerDocument.importNode(childNode, true), this) + this.parentNode.insertBefore( + this.ownerDocument.importNode(childNode, true), + this + ) // this.appendChild(this.ownerDocument.importNode(childNode, true)); childNode = childNode.nextSibling } } catch (e) { throw new Error('Can not set outerHTML on node') - }; + } } }) })() @@ -2,7 +2,7 @@ import * as svgMembers from './main.js' import { makeInstance } from './utils/adopter.js' // The main wrapping element -export default function SVG (element, isHTML) { +export default function SVG(element, isHTML) { return makeInstance(element, isHTML) } diff --git a/src/types/Box.js b/src/types/Box.js index ab19732..cd441ac 100644 --- a/src/types/Box.js +++ b/src/types/Box.js @@ -6,46 +6,55 @@ import Matrix from './Matrix.js' import Point from './Point.js' import parser from '../modules/core/parser.js' -export function isNulledBox (box) { +export function isNulledBox(box) { return !box.width && !box.height && !box.x && !box.y } -export function domContains (node) { - return node === globals.document - || (globals.document.documentElement.contains || function (node) { - // This is IE - it does not support contains() for top-level SVGs - while (node.parentNode) { - node = node.parentNode +export function domContains(node) { + return ( + node === globals.document || + ( + globals.document.documentElement.contains || + function (node) { + // This is IE - it does not support contains() for top-level SVGs + while (node.parentNode) { + node = node.parentNode + } + return node === globals.document } - return node === globals.document - }).call(globals.document.documentElement, node) + ).call(globals.document.documentElement, node) + ) } export default class Box { - constructor (...args) { + constructor(...args) { this.init(...args) } - addOffset () { + addOffset() { // offset by window scroll position, because getBoundingClientRect changes when window is scrolled this.x += globals.window.pageXOffset this.y += globals.window.pageYOffset return new Box(this) } - init (source) { - const base = [ 0, 0, 0, 0 ] - source = typeof source === 'string' - ? source.split(delimiter).map(parseFloat) - : Array.isArray(source) + init(source) { + const base = [0, 0, 0, 0] + 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) - : base + ? [ + source.left != null ? source.left : source.x, + source.top != null ? source.top : source.y, + source.width, + source.height + ] + : arguments.length === 4 + ? [].slice.call(arguments) + : base this.x = source[0] || 0 this.y = source[1] || 0 @@ -61,12 +70,12 @@ export default class Box { return this } - isNulled () { + isNulled() { return isNulledBox(this) } // Merge rect box with another, return a new instance - merge (box) { + merge(box) { const x = Math.min(this.x, box.x) const y = Math.min(this.y, box.y) const width = Math.max(this.x + this.width, box.x + box.width) - x @@ -75,15 +84,15 @@ export default class Box { return new Box(x, y, width, height) } - toArray () { - return [ this.x, this.y, this.width, this.height ] + toArray() { + return [this.x, this.y, this.width, this.height] } - toString () { + toString() { return this.x + ' ' + this.y + ' ' + this.width + ' ' + this.height } - transform (m) { + transform(m) { if (!(m instanceof Matrix)) { m = new Matrix(m) } @@ -108,16 +117,11 @@ export default class Box { yMax = Math.max(yMax, p.y) }) - return new Box( - xMin, yMin, - xMax - xMin, - yMax - yMin - ) + return new Box(xMin, yMin, xMax - xMin, yMax - yMin) } - } -function getBox (el, getBBoxFn, retry) { +function getBox(el, getBBoxFn, retry) { let box try { @@ -137,7 +141,7 @@ function getBox (el, getBBoxFn, retry) { return box } -export function bbox () { +export function bbox() { // Function to get bbox is getBBox() const getBBox = (node) => node.getBBox() @@ -151,7 +155,11 @@ export function bbox () { return box } catch (e) { // We give up... - throw new Error(`Getting bbox of element "${el.node.nodeName}" is not possible: ${e.toString()}`) + throw new Error( + `Getting bbox of element "${ + el.node.nodeName + }" is not possible: ${e.toString()}` + ) } } @@ -161,12 +169,14 @@ export function bbox () { return bbox } -export function rbox (el) { +export function rbox(el) { const getRBox = (node) => node.getBoundingClientRect() const retry = (el) => { // There is no point in trying tricks here because if we insert the element into the dom ourselves // it obviously will be at the wrong position - throw new Error(`Getting rbox of element "${el.node.nodeName}" is not possible`) + throw new Error( + `Getting rbox of element "${el.node.nodeName}" is not possible` + ) } const box = getBox(this, getRBox, retry) @@ -183,18 +193,17 @@ export function rbox (el) { } // Checks whether the given point is inside the bounding box -export function inside (x, y) { +export function inside(x, y) { const box = this.bbox() - return x > box.x - && y > box.y - && x < box.x + box.width - && y < box.y + box.height + return ( + x > box.x && y > box.y && x < box.x + box.width && y < box.y + box.height + ) } registerMethods({ viewbox: { - viewbox (x, y, width, height) { + viewbox(x, y, width, height) { // act as getter if (x == null) return new Box(this.attr('viewBox')) @@ -202,7 +211,7 @@ registerMethods({ return this.attr('viewBox', new Box(x, y, width, height)) }, - zoom (level, point) { + zoom(level, point) { // Its best to rely on the attributes here and here is why: // clientXYZ: Doesn't work on non-root svgs because they dont have a CSSBox (silly!) // getBoundingClientRect: Doesn't work because Chrome just ignores width and height of nested svgs completely @@ -210,18 +219,24 @@ registerMethods({ // Furthermore this size is incorrect if the element is further transformed by its parents // computedStyle: Only returns meaningful values if css was used with px. We dont go this route here! // getBBox: returns the bounding box of its content - that doesn't help! - let { width, height } = this.attr([ 'width', 'height' ]) + let { width, height } = this.attr(['width', 'height']) // Width and height is a string when a number with a unit is present which we can't use // So we try clientXYZ - if ((!width && !height) || (typeof width === 'string' || typeof height === 'string')) { + if ( + (!width && !height) || + typeof width === 'string' || + typeof height === 'string' + ) { width = this.node.clientWidth height = this.node.clientHeight } // Giving up... if (!width || !height) { - throw new Error('Impossible to get absolute width and height. Please provide an absolute width and height attribute on the zooming element') + throw new Error( + 'Impossible to get absolute width and height. Please provide an absolute width and height attribute on the zooming element' + ) } const v = this.viewbox() @@ -240,7 +255,8 @@ registerMethods({ // The * 100 is a bit of wiggle room for the matrix transformation if (zoomAmount === Infinity) zoomAmount = Number.MAX_SAFE_INTEGER / 100 - point = point || new Point(width / 2 / zoomX + v.x, height / 2 / zoomY + v.y) + point = + point || new Point(width / 2 / zoomX + v.x, height / 2 / zoomY + v.y) const box = new Box(v).transform( new Matrix({ scale: zoomAmount, origin: point }) diff --git a/src/types/Color.js b/src/types/Color.js index c050ecc..79fa24e 100644 --- a/src/types/Color.js +++ b/src/types/Color.js @@ -1,25 +1,28 @@ - import { hex, isHex, isRgb, rgb, whitespace } from '../modules/core/regex.js' -function sixDigitHex (hex) { +function sixDigitHex(hex) { return hex.length === 4 - ? [ '#', - hex.substring(1, 2), hex.substring(1, 2), - hex.substring(2, 3), hex.substring(2, 3), - hex.substring(3, 4), hex.substring(3, 4) - ].join('') + ? [ + '#', + hex.substring(1, 2), + hex.substring(1, 2), + hex.substring(2, 3), + hex.substring(2, 3), + hex.substring(3, 4), + hex.substring(3, 4) + ].join('') : hex } -function componentHex (component) { +function componentHex(component) { const integer = Math.round(component) const bounded = Math.max(0, Math.min(255, integer)) const hex = bounded.toString(16) return hex.length === 1 ? '0' + hex : hex } -function is (object, space) { - for (let i = space.length; i--;) { +function is(object, space) { + for (let i = space.length; i--; ) { if (object[space[i]] == null) { return false } @@ -27,26 +30,26 @@ function is (object, space) { return true } -function getParameters (a, b) { +function getParameters(a, b) { const params = is(a, 'rgb') ? { _a: a.r, _b: a.g, _c: a.b, _d: 0, space: 'rgb' } : is(a, 'xyz') - ? { _a: a.x, _b: a.y, _c: a.z, _d: 0, space: 'xyz' } - : is(a, 'hsl') - ? { _a: a.h, _b: a.s, _c: a.l, _d: 0, space: 'hsl' } - : is(a, 'lab') - ? { _a: a.l, _b: a.a, _c: a.b, _d: 0, space: 'lab' } - : is(a, 'lch') - ? { _a: a.l, _b: a.c, _c: a.h, _d: 0, space: 'lch' } - : is(a, 'cmyk') - ? { _a: a.c, _b: a.m, _c: a.y, _d: a.k, space: 'cmyk' } - : { _a: 0, _b: 0, _c: 0, space: 'rgb' } + ? { _a: a.x, _b: a.y, _c: a.z, _d: 0, space: 'xyz' } + : is(a, 'hsl') + ? { _a: a.h, _b: a.s, _c: a.l, _d: 0, space: 'hsl' } + : is(a, 'lab') + ? { _a: a.l, _b: a.a, _c: a.b, _d: 0, space: 'lab' } + : is(a, 'lch') + ? { _a: a.l, _b: a.c, _c: a.h, _d: 0, space: 'lch' } + : is(a, 'cmyk') + ? { _a: a.c, _b: a.m, _c: a.y, _d: a.k, space: 'cmyk' } + : { _a: 0, _b: 0, _c: 0, space: 'rgb' } params.space = b || params.space return params } -function cieSpace (space) { +function cieSpace(space) { if (space === 'lab' || space === 'xyz' || space === 'lch') { return true } else { @@ -54,7 +57,7 @@ function cieSpace (space) { } } -function hueToRgb (p, q, t) { +function hueToRgb(p, q, t) { if (t < 0) t += 1 if (t > 1) t -= 1 if (t < 1 / 6) return p + (q - p) * 6 * t @@ -64,108 +67,90 @@ function hueToRgb (p, q, t) { } export default class Color { - constructor (...inputs) { + constructor(...inputs) { this.init(...inputs) } // Test if given value is a color - static isColor (color) { - return color && ( - color instanceof Color - || this.isRgb(color) - || this.test(color) + static isColor(color) { + return ( + color && (color instanceof Color || this.isRgb(color) || this.test(color)) ) } // Test if given value is an rgb object - static isRgb (color) { - return color && typeof color.r === 'number' - && typeof color.g === 'number' - && typeof color.b === 'number' + static isRgb(color) { + return ( + color && + typeof color.r === 'number' && + typeof color.g === 'number' && + typeof color.b === 'number' + ) } /* Generating random colors */ - static random (mode = 'vibrant', t, u) { - + static random(mode = 'vibrant', t) { // Get the math modules const { random, round, sin, PI: pi } = Math // Run the correct generator if (mode === 'vibrant') { - const l = (81 - 57) * random() + 57 const c = (83 - 45) * random() + 45 const h = 360 * random() const color = new Color(l, c, h, 'lch') return color - } else if (mode === 'sine') { - t = t == null ? random() : t - const r = round(80 * sin(2 * pi * t / 0.5 + 0.01) + 150) - const g = round(50 * sin(2 * pi * t / 0.5 + 4.6) + 200) - const b = round(100 * sin(2 * pi * t / 0.5 + 2.3) + 150) + const r = round(80 * sin((2 * pi * t) / 0.5 + 0.01) + 150) + const g = round(50 * sin((2 * pi * t) / 0.5 + 4.6) + 200) + const b = round(100 * sin((2 * pi * t) / 0.5 + 2.3) + 150) const color = new Color(r, g, b) return color - } else if (mode === 'pastel') { - const l = (94 - 86) * random() + 86 const c = (26 - 9) * random() + 9 const h = 360 * random() const color = new Color(l, c, h, 'lch') return color - } else if (mode === 'dark') { - const l = 10 + 10 * random() const c = (125 - 75) * random() + 86 const h = 360 * random() const color = new Color(l, c, h, 'lch') return color - } else if (mode === 'rgb') { - const r = 255 * random() const g = 255 * random() const b = 255 * random() const color = new Color(r, g, b) return color - } else if (mode === 'lab') { - const l = 100 * random() const a = 256 * random() - 128 const b = 256 * random() - 128 const color = new Color(l, a, b, 'lab') return color - } else if (mode === 'grey') { - const grey = 255 * random() const color = new Color(grey, grey, grey) return color - } else { - throw new Error('Unsupported random color mode') - } } // Test if given value is a color string - static test (color) { - return (typeof color === 'string') - && (isHex.test(color) || isRgb.test(color)) + static test(color) { + return typeof color === 'string' && (isHex.test(color) || isRgb.test(color)) } - cmyk () { - + cmyk() { // Get the rgb values for the current color const { _a, _b, _c } = this.rgb() - const [ r, g, b ] = [ _a, _b, _c ].map(v => v / 255) + const [r, g, b] = [_a, _b, _c].map((v) => v / 255) // Get the cmyk values in an unbounded format const k = Math.min(1 - r, 1 - g, 1 - b) @@ -184,11 +169,10 @@ export default class Color { return color } - hsl () { - + hsl() { // Get the rgb values const { _a, _b, _c } = this.rgb() - const [ r, g, b ] = [ _a, _b, _c ].map(v => v / 255) + const [r, g, b] = [_a, _b, _c].map((v) => v / 255) // Find the maximum and minimum values to get the lightness const max = Math.max(r, g, b) @@ -203,24 +187,24 @@ export default class Color { const s = isGrey ? 0 : l > 0.5 - ? delta / (2 - max - min) - : delta / (max + min) + ? delta / (2 - max - min) + : delta / (max + min) const 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 + ? ((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 const color = new Color(360 * h, 100 * s, 100 * l, 'hsl') return color } - init (a = 0, b = 0, c = 0, d = 0, space = 'rgb') { + init(a = 0, b = 0, c = 0, d = 0, space = 'rgb') { // This catches the case when a falsy value is passed like '' a = !a ? 0 : a @@ -238,7 +222,7 @@ export default class Color { // Assign the values straight to the color Object.assign(this, { _a: a, _b: b, _c: c, _d: d, space }) - // If the user gave us an array, make the color from it + // If the user gave us an array, make the color from it } else if (a instanceof Array) { this.space = b || (typeof a[3] === 'string' ? a[3] : a[4]) || 'rgb' Object.assign(this, { _a: a[0], _b: a[1], _c: a[2], _d: a[3] || 0 }) @@ -249,40 +233,43 @@ export default class Color { } else if (typeof a === 'string') { if (isRgb.test(a)) { const noWhitespace = a.replace(whitespace, '') - const [ _a, _b, _c ] = rgb.exec(noWhitespace) - .slice(1, 4).map(v => parseInt(v)) + const [_a, _b, _c] = rgb + .exec(noWhitespace) + .slice(1, 4) + .map((v) => parseInt(v)) Object.assign(this, { _a, _b, _c, _d: 0, space: 'rgb' }) } else if (isHex.test(a)) { - const hexParse = v => parseInt(v, 16) - const [ , _a, _b, _c ] = hex.exec(sixDigitHex(a)).map(hexParse) + const hexParse = (v) => parseInt(v, 16) + const [, _a, _b, _c] = hex.exec(sixDigitHex(a)).map(hexParse) Object.assign(this, { _a, _b, _c, _d: 0, space: 'rgb' }) - } else throw Error('Unsupported string format, can\'t construct Color') + } else throw Error("Unsupported string format, can't construct Color") } // Now add the components as a convenience const { _a, _b, _c, _d } = this - const components = this.space === 'rgb' - ? { r: _a, g: _b, b: _c } - : this.space === 'xyz' + const 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 } - : {} + ? { 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) } - lab () { + lab() { // Get the xyz color const { x, y, z } = this.xyz() // Get the lab components - const l = (116 * y) - 16 + const l = 116 * y - 16 const a = 500 * (x - y) const b = 200 * (y - z) @@ -291,14 +278,13 @@ export default class Color { return color } - lch () { - + lch() { // Get the lab color directly const { l, a, b } = this.lab() // Get the chromaticity and the hue using polar coordinates const c = Math.sqrt(a ** 2 + b ** 2) - let h = 180 * Math.atan2(b, a) / Math.PI + let h = (180 * Math.atan2(b, a)) / Math.PI if (h < 0) { h *= -1 h = 360 - h @@ -312,7 +298,7 @@ export default class Color { Conversion Methods */ - rgb () { + rgb() { if (this.space === 'rgb') { return this } else if (cieSpace(this.space)) { @@ -337,22 +323,22 @@ export default class Color { const ct = 16 / 116 const mx = 0.008856 const nm = 7.787 - x = 0.95047 * ((xL ** 3 > mx) ? xL ** 3 : (xL - ct) / nm) - y = 1.00000 * ((yL ** 3 > mx) ? yL ** 3 : (yL - ct) / nm) - z = 1.08883 * ((zL ** 3 > mx) ? zL ** 3 : (zL - ct) / nm) + x = 0.95047 * (xL ** 3 > mx ? xL ** 3 : (xL - ct) / nm) + y = 1.0 * (yL ** 3 > mx ? yL ** 3 : (yL - ct) / nm) + z = 1.08883 * (zL ** 3 > mx ? zL ** 3 : (zL - ct) / nm) } // Convert xyz to unbounded rgb values const rU = x * 3.2406 + y * -1.5372 + z * -0.4986 const gU = x * -0.9689 + y * 1.8758 + z * 0.0415 - const bU = x * 0.0557 + y * -0.2040 + z * 1.0570 + const bU = x * 0.0557 + y * -0.204 + z * 1.057 // Convert the values to true rgb values const pow = Math.pow const bd = 0.0031308 - const r = (rU > bd) ? (1.055 * pow(rU, 1 / 2.4) - 0.055) : 12.92 * rU - const g = (gU > bd) ? (1.055 * pow(gU, 1 / 2.4) - 0.055) : 12.92 * gU - const b = (bU > bd) ? (1.055 * pow(bU, 1 / 2.4) - 0.055) : 12.92 * bU + const r = rU > bd ? 1.055 * pow(rU, 1 / 2.4) - 0.055 : 12.92 * rU + const g = gU > bd ? 1.055 * pow(gU, 1 / 2.4) - 0.055 : 12.92 * gU + const b = bU > bd ? 1.055 * pow(bU, 1 / 2.4) - 0.055 : 12.92 * bU // Make and return the color const color = new Color(255 * r, 255 * g, 255 * b) @@ -402,46 +388,45 @@ export default class Color { } } - toArray () { + toArray() { const { _a, _b, _c, _d, space } = this - return [ _a, _b, _c, _d, space ] + return [_a, _b, _c, _d, space] } - toHex () { - const [ r, g, b ] = this._clamped().map(componentHex) + toHex() { + const [r, g, b] = this._clamped().map(componentHex) return `#${r}${g}${b}` } - toRgb () { - const [ rV, gV, bV ] = this._clamped() + toRgb() { + const [rV, gV, bV] = this._clamped() const string = `rgb(${rV},${gV},${bV})` return string } - toString () { + toString() { return this.toHex() } - xyz () { - + xyz() { // Normalise the red, green and blue values const { _a: r255, _b: g255, _c: b255 } = this.rgb() - const [ r, g, b ] = [ r255, g255, b255 ].map(v => v / 255) + const [r, g, b] = [r255, g255, b255].map((v) => v / 255) // Convert to the lab rgb space - const rL = (r > 0.04045) ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92 - const gL = (g > 0.04045) ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92 - const bL = (b > 0.04045) ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92 + const rL = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92 + const gL = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92 + const bL = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92 // Convert to the xyz color space without bounding the values const xU = (rL * 0.4124 + gL * 0.3576 + bL * 0.1805) / 0.95047 - const yU = (rL * 0.2126 + gL * 0.7152 + bL * 0.0722) / 1.00000 + const yU = (rL * 0.2126 + gL * 0.7152 + bL * 0.0722) / 1.0 const zU = (rL * 0.0193 + gL * 0.1192 + bL * 0.9505) / 1.08883 // Get the proper xyz values by applying the bounding - const x = (xU > 0.008856) ? Math.pow(xU, 1 / 3) : (7.787 * xU) + 16 / 116 - const y = (yU > 0.008856) ? Math.pow(yU, 1 / 3) : (7.787 * yU) + 16 / 116 - const z = (zU > 0.008856) ? Math.pow(zU, 1 / 3) : (7.787 * zU) + 16 / 116 + const x = xU > 0.008856 ? Math.pow(xU, 1 / 3) : 7.787 * xU + 16 / 116 + const y = yU > 0.008856 ? Math.pow(yU, 1 / 3) : 7.787 * yU + 16 / 116 + const z = zU > 0.008856 ? Math.pow(zU, 1 / 3) : 7.787 * zU + 16 / 116 // Make and return the color const color = new Color(x, y, z, 'xyz') @@ -452,15 +437,14 @@ export default class Color { Input and Output methods */ - _clamped () { + _clamped() { const { _a, _b, _c } = this.rgb() const { max, min, round } = Math - const format = v => max(0, min(round(v), 255)) - return [ _a, _b, _c ].map(format) + const format = (v) => max(0, min(round(v), 255)) + return [_a, _b, _c].map(format) } /* Constructing colors */ - } diff --git a/src/types/EventTarget.js b/src/types/EventTarget.js index 58f5d5c..de13a5f 100644 --- a/src/types/EventTarget.js +++ b/src/types/EventTarget.js @@ -3,13 +3,13 @@ import { register } from '../utils/adopter.js' import Base from './Base.js' export default class EventTarget extends Base { - addEventListener () {} + addEventListener() {} - dispatch (event, data, options) { + dispatch(event, data, options) { return dispatch(this, event, data, options) } - dispatchEvent (event) { + dispatchEvent(event) { const bag = this.getEventHolder().events if (!bag) return true @@ -25,32 +25,32 @@ export default class EventTarget extends Base { } // Fire given event - fire (event, data, options) { + fire(event, data, options) { this.dispatch(event, data, options) return this } - getEventHolder () { + getEventHolder() { return this } - getEventTarget () { + getEventTarget() { return this } // Unbind event from listener - off (event, listener, options) { + off(event, listener, options) { off(this, event, listener, options) return this } // Bind given event to listener - on (event, listener, binding, options) { + on(event, listener, binding, options) { on(this, event, listener, binding, options) return this } - removeEventListener () {} + removeEventListener() {} } register(EventTarget, 'EventTarget') diff --git a/src/types/List.js b/src/types/List.js index 197a155..bdeb766 100644 --- a/src/types/List.js +++ b/src/types/List.js @@ -2,7 +2,7 @@ import { extend } from '../utils/adopter.js' // import { subClassArray } from './ArrayPolyfill.js' class List extends Array { - constructor (arr = [], ...args) { + constructor(arr = [], ...args) { super(arr, ...args) if (typeof arr === 'number') return this this.length = 0 @@ -19,25 +19,25 @@ class List extends Array { export default List -extend([ List ], { - each (fnOrMethodName, ...args) { +extend([List], { + each(fnOrMethodName, ...args) { if (typeof fnOrMethodName === 'function') { return this.map((el, i, arr) => { return fnOrMethodName.call(el, el, i, arr) }) } else { - return this.map(el => { + return this.map((el) => { return el[fnOrMethodName](...args) }) } }, - toArray () { + toArray() { return Array.prototype.concat.apply([], this) } }) -const reserved = [ 'toArray', 'constructor', 'each' ] +const reserved = ['toArray', 'constructor', 'each'] List.extend = function (methods) { methods = methods.reduce((obj, name) => { @@ -54,5 +54,5 @@ List.extend = function (methods) { return obj }, {}) - extend([ List ], methods) + extend([List], methods) } diff --git a/src/types/Matrix.js b/src/types/Matrix.js index c329df4..760f002 100644 --- a/src/types/Matrix.js +++ b/src/types/Matrix.js @@ -4,87 +4,116 @@ import { register } from '../utils/adopter.js' import Element from '../elements/Element.js' import Point from './Point.js' -function closeEnough (a, b, threshold) { +function closeEnough(a, b, threshold) { return Math.abs(b - a) < (threshold || 1e-6) } export default class Matrix { - constructor (...args) { + constructor(...args) { this.init(...args) } - static formatTransforms (o) { + static formatTransforms(o) { // Get all of the parameters required to form the matrix const flipBoth = o.flip === 'both' || o.flip === true const flipX = o.flip && (flipBoth || o.flip === 'x') ? -1 : 1 const flipY = o.flip && (flipBoth || o.flip === 'y') ? -1 : 1 - const skewX = o.skew && o.skew.length - ? o.skew[0] - : isFinite(o.skew) + const skewX = + o.skew && o.skew.length + ? o.skew[0] + : isFinite(o.skew) ? o.skew : isFinite(o.skewX) - ? o.skewX - : 0 - const skewY = o.skew && o.skew.length - ? o.skew[1] - : isFinite(o.skew) + ? o.skewX + : 0 + const skewY = + o.skew && o.skew.length + ? o.skew[1] + : isFinite(o.skew) ? o.skew : isFinite(o.skewY) - ? o.skewY - : 0 - const scaleX = o.scale && o.scale.length - ? o.scale[0] * flipX - : isFinite(o.scale) + ? o.skewY + : 0 + const scaleX = + o.scale && o.scale.length + ? o.scale[0] * flipX + : isFinite(o.scale) ? o.scale * flipX : isFinite(o.scaleX) - ? o.scaleX * flipX - : flipX - const scaleY = o.scale && o.scale.length - ? o.scale[1] * flipY - : isFinite(o.scale) + ? o.scaleX * flipX + : flipX + const scaleY = + o.scale && o.scale.length + ? o.scale[1] * flipY + : isFinite(o.scale) ? o.scale * flipY : isFinite(o.scaleY) - ? o.scaleY * flipY - : flipY + ? o.scaleY * flipY + : flipY const shear = o.shear || 0 const theta = o.rotate || o.theta || 0 - const origin = new Point(o.origin || o.around || o.ox || o.originX, o.oy || o.originY) + const origin = new Point( + o.origin || o.around || o.ox || o.originX, + o.oy || o.originY + ) const ox = origin.x const oy = origin.y // We need Point to be invalid if nothing was passed because we cannot default to 0 here. That is why NaN - const position = new Point(o.position || o.px || o.positionX || NaN, o.py || o.positionY || NaN) + const position = new Point( + o.position || o.px || o.positionX || NaN, + o.py || o.positionY || NaN + ) const px = position.x const py = position.y - const translate = new Point(o.translate || o.tx || o.translateX, o.ty || o.translateY) + const translate = new Point( + o.translate || o.tx || o.translateX, + o.ty || o.translateY + ) const tx = translate.x const ty = translate.y - const relative = new Point(o.relative || o.rx || o.relativeX, o.ry || o.relativeY) + const relative = new Point( + o.relative || o.rx || o.relativeX, + o.ry || o.relativeY + ) const rx = relative.x const ry = relative.y // Populate all of the values return { - scaleX, scaleY, skewX, skewY, shear, theta, rx, ry, tx, ty, ox, oy, px, py + scaleX, + scaleY, + skewX, + skewY, + shear, + theta, + rx, + ry, + tx, + ty, + ox, + oy, + px, + py } } - 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 - || o.c != null - || o.d != null - || o.e != null - || o.f != null + o.a != null || + o.b != null || + o.c != null || + o.d != null || + o.e != null || + o.f != null ) } // left matrix, right matrix, target matrix which is overwritten - static matrixMultiply (l, r, o) { + static matrixMultiply(l, r, o) { // Work out the product directly const a = l.a * r.a + l.c * r.b const b = l.b * r.a + l.d * r.b @@ -104,24 +133,24 @@ export default class Matrix { return o } - around (cx, cy, matrix) { + around(cx, cy, matrix) { return this.clone().aroundO(cx, cy, matrix) } // Transform around a center point - aroundO (cx, cy, matrix) { + aroundO(cx, cy, matrix) { const dx = cx || 0 const dy = cy || 0 return this.translateO(-dx, -dy).lmultiplyO(matrix).translateO(dx, dy) } // Clones this matrix - clone () { + clone() { return new Matrix(this) } // Decomposes this matrix into its affine parameters - decompose (cx = 0, cy = 0) { + decompose(cx = 0, cy = 0) { // Get the parameters from the matrix const a = this.a const b = this.b @@ -138,14 +167,14 @@ export default class Matrix { // and the rotation of the resulting matrix const sx = ccw * Math.sqrt(a * a + b * b) const thetaRad = Math.atan2(ccw * b, ccw * a) - const theta = 180 / Math.PI * thetaRad + const theta = (180 / Math.PI) * thetaRad const ct = Math.cos(thetaRad) const st = Math.sin(thetaRad) // We can then solve the y basis vector simultaneously to get the other // two affine parameters directly from these parameters const lam = (a * c + b * d) / determinant - const sy = ((c * sx) / (lam * a - b)) || ((d * sx) / (lam * b + a)) + const sy = (c * sx) / (lam * a - b) || (d * sx) / (lam * b + a) // Use the translations const tx = e - cx + cx * ct * sx + cy * (lam * ct * sx - st * sy) @@ -174,45 +203,51 @@ export default class Matrix { } // Check if two matrices are equal - equals (other) { + equals(other) { if (other === this) return true const 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) + 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) + ) } // Flip matrix on x or y, at a given offset - flip (axis, around) { + flip(axis, around) { return this.clone().flipO(axis, around) } - 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 + ? this.scaleO(1, -1, 0, around) + : this.scaleO(-1, -1, axis, around || axis) // Define an x, y flip point } // Initialize - init (source) { - const base = Matrix.fromArray([ 1, 0, 0, 1, 0, 0 ]) + init(source) { + const base = Matrix.fromArray([1, 0, 0, 1, 0, 0]) // ensure source as object - source = source instanceof Element - ? source.matrixify() - : typeof source === 'string' + 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)) - : base + ? 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 this.a = source.a != null ? source.a : base.a @@ -225,12 +260,12 @@ export default class Matrix { return this } - inverse () { + inverse() { return this.clone().inverseO() } // Inverses matrix - inverseO () { + inverseO() { // Get the current parameters out of the matrix const a = this.a const b = this.b @@ -264,40 +299,36 @@ export default class Matrix { return this } - lmultiply (matrix) { + lmultiply(matrix) { return this.clone().lmultiplyO(matrix) } - lmultiplyO (matrix) { + lmultiplyO(matrix) { const r = this - const l = matrix instanceof Matrix - ? matrix - : new Matrix(matrix) + const l = matrix instanceof Matrix ? matrix : new Matrix(matrix) return Matrix.matrixMultiply(l, r, this) } // Left multiplies by the given matrix - multiply (matrix) { + multiply(matrix) { return this.clone().multiplyO(matrix) } - multiplyO (matrix) { + multiplyO(matrix) { // Get the matrices const l = this - const r = matrix instanceof Matrix - ? matrix - : new Matrix(matrix) + const r = matrix instanceof Matrix ? matrix : new Matrix(matrix) return Matrix.matrixMultiply(l, r, this) } // Rotate matrix - rotate (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) @@ -317,11 +348,11 @@ export default class Matrix { } // Scale matrix - scale (x, y, cx, cy) { + scale() { 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) { cy = cx @@ -342,11 +373,12 @@ export default class Matrix { } // Shear matrix - shear (a, cx, cy) { + shear(a, cx, cy) { return this.clone().shearO(a, cx, cy) } - shearO (lx, cx = 0, cy = 0) { + // eslint-disable-next-line no-unused-vars + shearO(lx, cx = 0, cy = 0) { const { a, b, c, d, e, f } = this this.a = a + b * lx @@ -357,11 +389,11 @@ export default class Matrix { } // Skew Matrix - skew (x, y, cx, cy) { + skew() { 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) { cy = cx @@ -389,26 +421,40 @@ export default class Matrix { } // SkewX - skewX (x, cx, cy) { + skewX(x, cx, cy) { return this.skew(x, 0, cx, cy) } // SkewY - skewY (y, cx, cy) { + skewY(y, cx, cy) { return this.skew(0, y, cx, cy) } - toArray () { - return [ 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] } // Convert matrix to string - toString () { - return 'matrix(' + this.a + ',' + this.b + ',' + this.c + ',' + this.d + ',' + this.e + ',' + this.f + ')' + toString() { + return ( + 'matrix(' + + this.a + + ',' + + this.b + + ',' + + this.c + + ',' + + this.d + + ',' + + this.e + + ',' + + this.f + + ')' + ) } // 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)) { const matrix = new Matrix(o) @@ -447,17 +493,17 @@ export default class Matrix { } // Translate matrix - translate (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 } - valueOf () { + valueOf() { return { a: this.a, b: this.b, @@ -467,14 +513,13 @@ export default class Matrix { f: this.f } } - } -export function ctm () { +export function ctm() { return new Matrix(this.node.getCTM()) } -export function screenCTM () { +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. diff --git a/src/types/PathArray.js b/src/types/PathArray.js index 8a37ac4..9e59ed7 100644 --- a/src/types/PathArray.js +++ b/src/types/PathArray.js @@ -3,7 +3,7 @@ import parser from '../modules/core/parser.js' import Box from './Box.js' import { pathParser } from '../utils/pathParser.js' -function arrayToString (a) { +function arrayToString(a) { let s = '' for (let i = 0, il = a.length; i < il; i++) { s += a[i][0] @@ -42,13 +42,13 @@ function arrayToString (a) { export default class PathArray extends SVGArray { // Get bounding box of path - bbox () { + bbox() { parser().path.setAttribute('d', this.toString()) return new Box(parser.nodes.path.getBBox()) } // Move path string - move (x, y) { + move(x, y) { // get bounding box of current situation const box = this.bbox() @@ -89,7 +89,7 @@ export default class PathArray extends SVGArray { } // Absolutize and parse path to array - parse (d = 'M0 0') { + parse(d = 'M0 0') { if (Array.isArray(d)) { d = Array.prototype.concat.apply([], d).toString() } @@ -98,7 +98,7 @@ export default class PathArray extends SVGArray { } // Resize path string - size (width, height) { + size(width, height) { // get bounding box of current situation const box = this.bbox() let i, l @@ -144,8 +144,7 @@ export default class PathArray extends SVGArray { } // Convert array to string - toString () { + toString() { return arrayToString(this) } - } diff --git a/src/types/Point.js b/src/types/Point.js index 76fd985..5d44733 100644 --- a/src/types/Point.js +++ b/src/types/Point.js @@ -2,24 +2,24 @@ import Matrix from './Matrix.js' export default class Point { // Initialize - constructor (...args) { + constructor(...args) { this.init(...args) } // Clone point - clone () { + clone() { return new Point(this) } - init (x, y) { + init(x, y) { const base = { x: 0, y: 0 } // ensure source as object const source = Array.isArray(x) ? { x: x[0], y: x[1] } : typeof x === 'object' - ? { x: x.x, y: x.y } - : { x: x, y: y } + ? { x: x.x, y: x.y } + : { x: x, y: y } // merge source this.x = source.x == null ? base.x : source.x @@ -28,16 +28,16 @@ export default class Point { return this } - toArray () { - return [ this.x, this.y ] + toArray() { + return [this.x, this.y] } - transform (m) { + transform(m) { return this.clone().transformO(m) } // Transform point with matrix - transformO (m) { + transformO(m) { if (!Matrix.isMatrixLike(m)) { m = new Matrix(m) } @@ -50,9 +50,8 @@ export default class Point { return this } - } -export function point (x, y) { +export function point(x, y) { return new Point(x, y).transformO(this.screenCTM().inverseO()) } diff --git a/src/types/PointArray.js b/src/types/PointArray.js index 69d0cd6..f72c2bc 100644 --- a/src/types/PointArray.js +++ b/src/types/PointArray.js @@ -5,7 +5,7 @@ import Matrix from './Matrix.js' export default class PointArray extends SVGArray { // Get bounding box of points - bbox () { + bbox() { let maxX = -Infinity let maxY = -Infinity let minX = Infinity @@ -20,7 +20,7 @@ export default class PointArray extends SVGArray { } // Move point string - move (x, y) { + move(x, y) { const box = this.bbox() // get relative offset @@ -30,7 +30,7 @@ export default class PointArray extends SVGArray { // move every point if (!isNaN(x) && !isNaN(y)) { for (let i = this.length - 1; i >= 0; i--) { - this[i] = [ this[i][0] + x, this[i][1] + y ] + this[i] = [this[i][0] + x, this[i][1] + y] } } @@ -38,13 +38,14 @@ export default class PointArray extends SVGArray { } // Parse point string and flat array - parse (array = [ 0, 0 ]) { + parse(array = [0, 0]) { const points = [] // if it is an array, we flatten it and therefore clone it to 1 depths if (array instanceof Array) { array = Array.prototype.concat.apply([], array) - } else { // Else, it is considered as a string + } else { + // Else, it is considered as a string // parse points array = array.trim().split(delimiter).map(parseFloat) } @@ -55,28 +56,30 @@ export default class PointArray extends SVGArray { // wrap points in two-tuples for (let i = 0, len = array.length; i < len; i = i + 2) { - points.push([ array[i], array[i + 1] ]) + points.push([array[i], array[i + 1]]) } return points } // Resize poly string - size (width, height) { + size(width, height) { let i const 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 + 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 } // Convert array to line object - toLine () { + toLine() { return { x1: this[0][0], y1: this[0][1], @@ -86,7 +89,7 @@ export default class PointArray extends SVGArray { } // Convert array to string - toString () { + toString() { const array = [] // convert to a poly point string for (let i = 0, il = this.length; i < il; i++) { @@ -96,24 +99,23 @@ export default class PointArray extends SVGArray { return array.join(' ') } - transform (m) { + transform(m) { return this.clone().transformO(m) } // transform points with matrix (similar to Point.transform) - transformO (m) { + transformO(m) { if (!Matrix.isMatrixLike(m)) { m = new Matrix(m) } - for (let i = this.length; i--;) { + for (let i = this.length; i--; ) { // Perform the matrix multiplication - const [ x, y ] = this[i] + const [x, y] = this[i] this[i][0] = m.a * x + m.c * y + m.e this[i][1] = m.b * x + m.d * y + m.f } return this } - } diff --git a/src/types/SVGArray.js b/src/types/SVGArray.js index 6ce024a..5826406 100644 --- a/src/types/SVGArray.js +++ b/src/types/SVGArray.js @@ -1,16 +1,16 @@ import { delimiter } from '../modules/core/regex.js' export default class SVGArray extends Array { - constructor (...args) { + constructor(...args) { super(...args) this.init(...args) } - clone () { + clone() { return new this.constructor(this) } - init (arr) { + init(arr) { // This catches the case, that native map tries to create an array with new Array(1) if (typeof arr === 'number') return this this.length = 0 @@ -19,30 +19,29 @@ export default class SVGArray extends Array { } // 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) } - toArray () { + toArray() { return Array.prototype.concat.apply([], this) } - toSet () { + toSet() { return new Set(this) } - toString () { + toString() { return this.join(' ') } // Flattens the array if needed - valueOf () { + valueOf() { const ret = [] ret.push(...this) return ret } - } diff --git a/src/types/SVGNumber.js b/src/types/SVGNumber.js index 25c87c1..5945341 100644 --- a/src/types/SVGNumber.js +++ b/src/types/SVGNumber.js @@ -3,21 +3,21 @@ import { numberAndUnit } from '../modules/core/regex.js' // Module for unit conversions export default class SVGNumber { // Initialize - constructor (...args) { + constructor(...args) { this.init(...args) } - convert (unit) { + convert(unit) { return new SVGNumber(this.value, unit) } // Divide number - divide (number) { + divide(number) { number = new SVGNumber(number) return new SVGNumber(this / number, this.unit || number.unit) } - init (value, unit) { + init(value, unit) { unit = Array.isArray(value) ? value[1] : unit value = Array.isArray(value) ? value[0] : value @@ -28,7 +28,13 @@ export default class SVGNumber { // parse value 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 + this.value = isNaN(value) + ? 0 + : !isFinite(value) + ? value < 0 + ? -3.4e38 + : +3.4e38 + : value } else if (typeof value === 'string') { unit = value.match(numberAndUnit) @@ -57,42 +63,42 @@ export default class SVGNumber { } // Subtract number - minus (number) { + minus(number) { number = new SVGNumber(number) return new SVGNumber(this - number, this.unit || number.unit) } // Add number - plus (number) { + plus(number) { number = new SVGNumber(number) return new SVGNumber(this + number, this.unit || number.unit) } // Multiply number - times (number) { + times(number) { number = new SVGNumber(number) return new SVGNumber(this * number, this.unit || number.unit) } - toArray () { - return [ this.value, this.unit ] + toArray() { + return [this.value, this.unit] } - toJSON () { + toJSON() { return this.toString() } - toString () { - return (this.unit === '%' - ? ~~(this.value * 1e8) / 1e6 - : this.unit === 's' + toString() { + return ( + (this.unit === '%' + ? ~~(this.value * 1e8) / 1e6 + : this.unit === 's' ? this.value / 1e3 - : this.value - ) + this.unit + : this.value) + this.unit + ) } - valueOf () { + valueOf() { return this.value } - } diff --git a/src/utils/adopter.js b/src/utils/adopter.js index 7e1c85e..48814ec 100644 --- a/src/utils/adopter.js +++ b/src/utils/adopter.js @@ -8,12 +8,12 @@ const elements = {} export const root = '___SYMBOL___ROOT___' // Method for element creation -export function create (name, ns = svg) { +export function create(name, ns = svg) { // create element return globals.document.createElementNS(ns, name) } -export function makeInstance (element, isHTML = false) { +export function makeInstance(element, isHTML = false) { if (element instanceof Base) return element if (typeof element === 'object') { @@ -41,12 +41,16 @@ export function makeInstance (element, isHTML = false) { return element } -export function nodeOrNew (name, node) { - return (node && node.ownerDocument && node instanceof node.ownerDocument.defaultView.Node) ? node : create(name) +export function nodeOrNew(name, node) { + return node && + node.ownerDocument && + node instanceof node.ownerDocument.defaultView.Node + ? node + : create(name) } // Adopt existing svg elements -export function adopt (node) { +export function adopt(node) { // check for presence of node if (!node) return null @@ -64,7 +68,7 @@ export function adopt (node) { if (className === 'LinearGradient' || className === 'RadialGradient') { className = 'Gradient' - // Fallback to Dom if element is not known + // Fallback to Dom if element is not known } else if (!elements[className]) { className = 'Dom' } @@ -74,11 +78,11 @@ export function adopt (node) { let adopter = adopt -export function mockAdopt (mock = adopt) { +export function mockAdopt(mock = adopt) { adopter = mock } -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 @@ -87,7 +91,7 @@ export function register (element, name = element.name, asRoot = false) { return element } -export function getClass (name) { +export function getClass(name) { return elements[name] } @@ -95,12 +99,12 @@ export function getClass (name) { 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 (let i = node.children.length - 1; i >= 0; i--) { assignNewId(node.children[i]) @@ -115,10 +119,10 @@ export function assignNewId (node) { } // Method for extending objects -export function extend (modules, methods) { +export function extend(modules, methods) { let key, i - modules = Array.isArray(modules) ? modules : [ modules ] + modules = Array.isArray(modules) ? modules : [modules] for (i = modules.length - 1; i >= 0; i--) { for (key in methods) { @@ -127,7 +131,7 @@ export function extend (modules, methods) { } } -export function wrapWithAttrCheck (fn) { +export function wrapWithAttrCheck(fn) { return function (...args) { const o = args[args.length - 1] diff --git a/src/utils/methods.js b/src/utils/methods.js index 45525e3..9f61f91 100644 --- a/src/utils/methods.js +++ b/src/utils/methods.js @@ -1,7 +1,7 @@ const methods = {} const names = [] -export function registerMethods (name, m) { +export function registerMethods(name, m) { if (Array.isArray(name)) { for (const _name of name) { registerMethods(_name, m) @@ -20,14 +20,14 @@ export function registerMethods (name, 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) ] +export function getMethodNames() { + return [...new Set(names)] } -export function addMethodNames (_names) { +export function addMethodNames(_names) { names.push(..._names) } diff --git a/src/utils/pathParser.js b/src/utils/pathParser.js index 1d0ee86..6d3f4e2 100644 --- a/src/utils/pathParser.js +++ b/src/utils/pathParser.js @@ -1,57 +1,68 @@ import { isPathLetter } from '../modules/core/regex.js' import Point from '../types/Point.js' -const segmentParameters = { M: 2, L: 2, H: 1, V: 1, C: 6, S: 4, Q: 4, T: 2, A: 7, Z: 0 } +const segmentParameters = { + M: 2, + L: 2, + H: 1, + V: 1, + C: 6, + S: 4, + Q: 4, + T: 2, + A: 7, + Z: 0 +} const pathHandlers = { M: function (c, p, p0) { p.x = p0.x = c[0] p.y = p0.y = c[1] - return [ 'M', p.x, p.y ] + return ['M', p.x, p.y] }, L: function (c, p) { p.x = c[0] p.y = c[1] - return [ 'L', c[0], c[1] ] + return ['L', c[0], c[1]] }, H: function (c, p) { p.x = c[0] - return [ 'H', c[0] ] + return ['H', c[0]] }, V: function (c, p) { p.y = c[0] - return [ 'V', c[0] ] + return ['V', c[0]] }, 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] ] + return ['C', c[0], c[1], c[2], c[3], c[4], c[5]] }, S: function (c, p) { p.x = c[2] p.y = c[3] - return [ 'S', c[0], c[1], c[2], c[3] ] + return ['S', c[0], c[1], c[2], c[3]] }, Q: function (c, p) { p.x = c[2] p.y = c[3] - return [ 'Q', c[0], c[1], c[2], c[3] ] + return ['Q', c[0], c[1], c[2], c[3]] }, T: function (c, p) { p.x = c[0] p.y = c[1] - return [ 'T', c[0], c[1] ] + return ['T', c[0], c[1]] }, Z: function (c, p, p0) { p.x = p0.x p.y = p0.y - return [ 'Z' ] + return ['Z'] }, 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] ] + return ['A', c[0], c[1], c[2], c[3], c[4], c[5], c[6]] } } @@ -76,26 +87,30 @@ for (let i = 0, il = mlhvqtcsaz.length; i < il; ++i) { })(mlhvqtcsaz[i].toUpperCase()) } -function makeAbsolut (parser) { +function makeAbsolut(parser) { const command = parser.segment[0] return pathHandlers[command](parser.segment.slice(1), parser.p, parser.p0) } -function segmentComplete (parser) { - return parser.segment.length && parser.segment.length - 1 === segmentParameters[parser.segment[0].toUpperCase()] +function segmentComplete(parser) { + return ( + parser.segment.length && + parser.segment.length - 1 === + segmentParameters[parser.segment[0].toUpperCase()] + ) } -function startNewSegment (parser, token) { +function startNewSegment(parser, token) { parser.inNumber && finalizeNumber(parser, false) const pathLetter = isPathLetter.test(token) if (pathLetter) { - parser.segment = [ token ] + parser.segment = [token] } else { const lastCommand = parser.lastCommand const small = lastCommand.toLowerCase() const isSmall = lastCommand === small - parser.segment = [ small === 'm' ? (isSmall ? 'l' : 'L') : lastCommand ] + parser.segment = [small === 'm' ? (isSmall ? 'l' : 'L') : lastCommand] } parser.inSegment = true @@ -104,7 +119,7 @@ function startNewSegment (parser, token) { return pathLetter } -function finalizeNumber (parser, inNumber) { +function finalizeNumber(parser, inNumber) { if (!parser.inNumber) throw new Error('Parser Error') parser.number && parser.segment.push(parseFloat(parser.number)) parser.inNumber = inNumber @@ -117,7 +132,7 @@ function finalizeNumber (parser, inNumber) { } } -function finalizeSegment (parser) { +function finalizeSegment(parser) { parser.inSegment = false if (parser.absolute) { parser.segment = makeAbsolut(parser) @@ -125,7 +140,7 @@ function finalizeSegment (parser) { parser.segments.push(parser.segment) } -function isArcFlag (parser) { +function isArcFlag(parser) { if (!parser.segment.length) return false const isArc = parser.segment[0].toUpperCase() === 'A' const length = parser.segment.length @@ -133,12 +148,11 @@ function isArcFlag (parser) { return isArc && (length === 4 || length === 5) } -function isExponential (parser) { +function isExponential(parser) { return parser.lastToken.toUpperCase() === 'E' } -export function pathParser (d, toAbsolute = true) { - +export function pathParser(d, toAbsolute = true) { let index = 0 let token = '' const parser = { @@ -155,7 +169,7 @@ export function pathParser (d, toAbsolute = true) { p: new Point() } - while ((parser.lastToken = token, token = d.charAt(index++))) { + while (((parser.lastToken = token), (token = d.charAt(index++)))) { if (!parser.inSegment) { if (startNewSegment(parser, token)) { continue @@ -175,7 +189,6 @@ export function pathParser (d, toAbsolute = true) { } if (!isNaN(parseInt(token))) { - if (parser.number === '0' || isArcFlag(parser)) { parser.inNumber = true parser.number = token @@ -233,5 +246,4 @@ export function pathParser (d, toAbsolute = true) { } return parser.segments - } diff --git a/src/utils/utils.js b/src/utils/utils.js index 7d08e22..c6e6d3b 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -1,5 +1,5 @@ // Map function -export function map (array, block) { +export function map(array, block) { let i const il = array.length const result = [] @@ -12,7 +12,7 @@ export function map (array, block) { } // Filter function -export function filter (array, block) { +export function filter(array, block) { let i const il = array.length const result = [] @@ -27,43 +27,43 @@ export function filter (array, block) { } // Degrees to radians -export function radians (d) { - return d % 360 * Math.PI / 180 +export function radians(d) { + return ((d % 360) * Math.PI) / 180 } // Radians to degrees -export function degrees (r) { - return r * 180 / Math.PI % 360 +export function degrees(r) { + return ((r * 180) / Math.PI) % 360 } // Convert dash-separated-string to camelCase -export function camelCase (s) { +export function camelCase(s) { return s.toLowerCase().replace(/-(.)/g, function (m, g) { return g.toUpperCase() }) } // Convert camel cased string to dash separated -export function unCamelCase (s) { +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) { +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, box) { +export function proportionalSize(element, width, height, box) { if (width == null || height == null) { box = box || element.bbox() if (width == null) { - width = box.width / box.height * height + width = (box.width / box.height) * height } else if (height == null) { - height = box.height / box.width * width + height = (box.height / box.width) * width } } @@ -77,28 +77,20 @@ export function proportionalSize (element, width, height, box) { * This function adds support for string origins. * It searches for an origin in o.origin o.ox and o.originX. * This way, origin: {x: 'center', y: 50} can be passed as well as ox: 'center', oy: 50 -**/ -export function getOrigin (o, element) { + **/ +export function getOrigin(o, element) { const origin = o.origin // First check if origin is in ox or originX - let ox = o.ox != null - ? o.ox - : o.originX != null - ? o.originX - : 'center' - let oy = o.oy != null - ? o.oy - : o.originY != null - ? o.originY - : 'center' + let ox = o.ox != null ? o.ox : o.originX != null ? o.originX : 'center' + let oy = o.oy != null ? o.oy : o.originY != null ? o.originY : 'center' // Then check if origin was used and overwrite in that case if (origin != null) { - [ ox, oy ] = Array.isArray(origin) + ;[ox, oy] = Array.isArray(origin) ? origin : typeof origin === 'object' - ? [ origin.x, origin.y ] - : [ origin, origin ] + ? [origin.x, origin.y] + : [origin, origin] } // Make sure to only call bbox when actually needed @@ -112,19 +104,19 @@ export function getOrigin (o, element) { ox = ox.includes('left') ? x : ox.includes('right') - ? x + width - : x + width / 2 + ? x + width + : x + width / 2 } if (condY) { oy = oy.includes('top') ? y : oy.includes('bottom') - ? y + height - : y + height / 2 + ? y + height + : y + height / 2 } } // Return the origin as it is if it wasn't a string - return [ ox, oy ] + return [ox, oy] } diff --git a/src/utils/window.js b/src/utils/window.js index 626fde3..5009c77 100644 --- a/src/utils/window.js +++ b/src/utils/window.js @@ -3,30 +3,30 @@ 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 } const save = {} -export function saveWindow () { +export function saveWindow() { save.window = globals.window save.document = globals.document } -export function restoreWindow () { +export function restoreWindow() { globals.window = save.window globals.document = save.document } -export function withWindow (win, fn) { +export function withWindow(win, fn) { saveWindow() registerWindow(win, win.document) fn(win, win.document) restoreWindow() } -export function getWindow () { +export function getWindow() { return globals.window } |