aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/animation/Animator.js8
-rw-r--r--src/animation/Morphable.js (renamed from src/types/Morphable.js)19
-rw-r--r--src/animation/Runner.js22
-rw-r--r--src/animation/Timeline.js131
-rw-r--r--src/elements/Bare.js31
-rw-r--r--src/elements/Dom.js15
-rw-r--r--src/elements/HtmlNode.js6
-rw-r--r--src/elements/Style.js6
-rw-r--r--src/main.js19
-rw-r--r--src/modules/optional/arrange.js13
-rw-r--r--src/polyfills/children.js8
-rw-r--r--src/polyfills/innerHTML.js95
-rw-r--r--src/svg.js5
-rw-r--r--src/types/Box.js26
-rw-r--r--src/types/Color.js20
-rw-r--r--src/utils/adopter.js46
-rw-r--r--src/utils/methods.js13
-rw-r--r--src/utils/window.js23
18 files changed, 320 insertions, 186 deletions
diff --git a/src/animation/Animator.js b/src/animation/Animator.js
index cac0eb9..2786602 100644
--- a/src/animation/Animator.js
+++ b/src/animation/Animator.js
@@ -5,7 +5,7 @@ const Animator = {
nextDraw: null,
frames: new Queue(),
timeouts: new Queue(),
- timer: globals.window.performance || globals.window.Date,
+ timer: () => globals.window.performance || globals.window.Date,
transforms: [],
frame (fn) {
@@ -29,7 +29,7 @@ const Animator = {
delay = delay || 0
// Work out when the event should fire
- var time = Animator.timer.now() + delay
+ var time = Animator.timer().now() + delay
// Add the timeout to the end of the queue
var node = Animator.timeouts.push({ run: fn, time: time })
@@ -43,11 +43,11 @@ const Animator = {
},
cancelFrame (node) {
- Animator.frames.remove(node)
+ node != null && Animator.frames.remove(node)
},
clearTimeout (node) {
- Animator.timeouts.remove(node)
+ node != null && Animator.timeouts.remove(node)
},
_draw (now) {
diff --git a/src/types/Morphable.js b/src/animation/Morphable.js
index e7af8c1..56ffe95 100644
--- a/src/types/Morphable.js
+++ b/src/animation/Morphable.js
@@ -1,14 +1,14 @@
-import { Ease } from '../animation/Controller.js'
+import { Ease } from './Controller.js'
import {
delimiter,
numberAndUnit,
pathLetters
} from '../modules/core/regex.js'
import { extend } from '../utils/adopter.js'
-import Color from './Color.js'
-import PathArray from './PathArray.js'
-import SVGArray from './SVGArray.js'
-import SVGNumber from './SVGNumber.js'
+import Color from '../types/Color.js'
+import PathArray from '../types/PathArray.js'
+import SVGArray from '../types/SVGArray.js'
+import SVGNumber from '../types/SVGNumber.js'
export default class Morphable {
constructor (stepper) {
@@ -203,7 +203,14 @@ export class ObjectBag {
return
}
- var entries = Object.entries(objOrArr || {}).sort((a, b) => {
+ objOrArr = objOrArr || {}
+ var entries = []
+
+ for (let i in objOrArr) {
+ entries.push([i, objOrArr[i]])
+ }
+
+ entries.sort((a, b) => {
return a[0] - b[0]
})
diff --git a/src/animation/Runner.js b/src/animation/Runner.js
index 7e04c21..3af5823 100644
--- a/src/animation/Runner.js
+++ b/src/animation/Runner.js
@@ -9,7 +9,7 @@ import Animator from './Animator.js'
import Box from '../types/Box.js'
import EventTarget from '../types/EventTarget.js'
import Matrix from '../types/Matrix.js'
-import Morphable, { TransformBag } from '../types/Morphable.js'
+import Morphable, { TransformBag } from './Morphable.js'
import Point from '../types/Point.js'
import SVGNumber from '../types/SVGNumber.js'
import Timeline from './Timeline.js'
@@ -48,7 +48,10 @@ export default class Runner extends EventTarget {
// Store the state of the runner
this.enabled = true
this._time = 0
- this._last = 0
+ this._lastTime = 0
+
+ // At creation, the runner is in reseted state
+ this._reseted = true
// Save transforms applied to this runner
this.transforms = new Matrix()
@@ -261,7 +264,7 @@ export default class Runner extends EventTarget {
// Figure out if we just started
var duration = this.duration()
- var justStarted = this._lastTime < 0 && this._time > 0
+ var justStarted = this._lastTime <= 0 && this._time > 0
var justFinished = this._lastTime < this._time && this.time > duration
this._lastTime = this._time
if (justStarted) {
@@ -274,6 +277,9 @@ export default class Runner extends EventTarget {
var declarative = this._isDeclarative
this.done = !declarative && !justFinished && this._time >= duration
+ // Runner is running. So its not in reseted state anymore
+ this._reseted = false
+
// Call initialise and the run function
if (running || declarative) {
this._initialise(running)
@@ -281,6 +287,7 @@ export default class Runner extends EventTarget {
// clear the transforms on this runner so they dont get added again and again
this.transforms = new Matrix()
var converged = this._run(declarative ? dt : position)
+
this.fire('step', this)
}
// correct the done flag here
@@ -292,6 +299,13 @@ export default class Runner extends EventTarget {
return this
}
+ reset () {
+ if (this._reseted) return this
+ this.loops(0)
+ this._reseted = true
+ return this
+ }
+
finish () {
return this.step(Infinity)
}
@@ -564,7 +578,7 @@ registerMethods({
return new Runner(o.duration)
.loop(o)
.element(this)
- .timeline(timeline)
+ .timeline(timeline.play())
.schedule(delay, when)
},
diff --git a/src/animation/Timeline.js b/src/animation/Timeline.js
index 6abcb80..c3ad07c 100644
--- a/src/animation/Timeline.js
+++ b/src/animation/Timeline.js
@@ -10,64 +10,58 @@ var makeSchedule = function (runnerInfo) {
return { start: start, duration: duration, end: end, runner: runnerInfo.runner }
}
+const defaultSource = function () {
+ let w = globals.window
+ return (w.performance || w.Date).now()
+}
+
export default class Timeline extends EventTarget {
// Construct a new timeline on the given element
- constructor () {
+ constructor (timeSource = defaultSource) {
super()
- this._timeSource = function () {
- let w = globals.window
- return (w.performance || w.Date).now()
- }
+ this._timeSource = timeSource
// Store the timing variables
this._startTime = 0
this._speed = 1.0
- // Play control variables control how the animation proceeds
- this._reverse = false
+ // Determines how long a runner is hold in memory. Can be a dt or true/false
this._persist = 0
// Keep track of the running animations and their starting parameters
this._nextFrame = null
- this._paused = false
+ this._paused = true
this._runners = []
this._order = []
this._time = 0
this._lastSourceTime = 0
this._lastStepTime = 0
- }
- /**
- *
- */
+ // Make sure that step is always called in class context
+ this._step = this._step.bind(this)
+ }
// schedules a runner on the timeline
schedule (runner, delay, when) {
- // FIXME: how to sort? maybe by runner id?
if (runner == null) {
return this._runners.map(makeSchedule).sort(function (a, b) {
- return (a.start - b.start) || (a.duration - b.duration)
+ return a.runner.id - b.runner.id
})
}
- if (!this.active()) {
- this._step()
- if (when == null) {
- when = 'now'
- }
- }
-
// The start time for the next animation can either be given explicitly,
// derived from the current timeline time or it can be relative to the
// last start time to chain animations direclty
+
var absoluteStartTime = 0
+ var endTime = this.getEndTime()
delay = delay || 0
// Work out when to start the animation
if (when == null || when === 'last' || when === 'after') {
// Take the last time and increment
- absoluteStartTime = this._startTime
+ absoluteStartTime = endTime
} else if (when === 'absolute' || when === 'start') {
absoluteStartTime = delay
delay = 0
@@ -86,21 +80,18 @@ export default class Timeline extends EventTarget {
// Manage runner
runner.unschedule()
runner.timeline(this)
- runner.time(-delay)
-
- // Save startTime for next runner
- this._startTime = absoluteStartTime + runner.duration() + delay
+ // runner.time(-delay)
// Save runnerInfo
this._runners[runner.id] = {
persist: this.persist(),
runner: runner,
- start: absoluteStartTime
+ start: absoluteStartTime + delay
}
- // Save order and continue
+ // Save order, update Time if needed and continue
this._order.push(runner.id)
- this._continue()
+ this.updateTime()._continue()
return this
}
@@ -115,27 +106,42 @@ export default class Timeline extends EventTarget {
return this
}
+ // Calculates the end of the timeline
+ getEndTime () {
+ var lastRunnerInfo = this._runners[this._order[this._order.length - 1]]
+ var lastDuration = lastRunnerInfo ? lastRunnerInfo.runner.duration() : 0
+ var lastStartTime = lastRunnerInfo ? lastRunnerInfo.start : 0
+ return lastStartTime + lastDuration
+ }
+
+ // Makes sure, that after pausing the time doesn't jump
+ updateTime () {
+ if (!this.active()) {
+ this._lastSourceTime = this._timeSource()
+ }
+ return this
+ }
+
play () {
// Now make sure we are not paused and continue the animation
this._paused = false
- return this._continue()
+ return this.updateTime()._continue()
}
pause () {
- // Cancel the next animation frame and pause
- this._nextFrame = null
this._paused = true
- return this
+ return this._continue()
}
stop () {
- // Cancel the next animation frame and go to start
- this.seek(-this._time)
+ // Go to start and pause
+ this.time(0)
return this.pause()
}
finish () {
- this.seek(Infinity)
+ // Go to end and pause
+ this.time(this.getEndTime() + 1)
return this.pause()
}
@@ -154,14 +160,13 @@ export default class Timeline extends EventTarget {
}
seek (dt) {
- this._time += dt
- return this._continue()
+ return this.time(this._time + dt)
}
time (time) {
if (time == null) return this._time
this._time = time
- return this
+ return this._continue(true)
}
persist (dtOrForever) {
@@ -176,20 +181,25 @@ export default class Timeline extends EventTarget {
return this
}
- _step () {
- // If the timeline is paused, just do nothing
- if (this._paused) return
-
+ _step (immediateStep = false) {
// Get the time delta from the last time and update the time
var time = this._timeSource()
var dtSource = time - this._lastSourceTime
+
+ if (immediateStep) dtSource = 0
+
var dtTime = this._speed * dtSource + (this._time - this._lastStepTime)
this._lastSourceTime = time
- // Update the time
- this._time += dtTime
+ // Only update the time if we use the timeSource.
+ // Otherwise use the current time
+ if (!immediateStep) {
+ // Update the time
+ this._time += dtTime
+ this._time = this._time < 0 ? 0 : this._time
+ }
this._lastStepTime = this._time
- // this.fire('time', this._time)
+ this.fire('time', this._time)
// Run all of the runners directly
var runnersLeft = false
@@ -204,8 +214,13 @@ export default class Timeline extends EventTarget {
let dtToStart = this._time - runnerInfo.start
// Dont run runner if not started yet
- if (dtToStart < 0) {
+ if (dtToStart <= 0) {
runnersLeft = true
+
+ // This is for the case that teh timeline was seeked so that the time
+ // is now before the startTime of the runner. Thats why we need to set
+ // the runner to position 0
+ runner.reset()
continue
} else if (dtToStart < dt) {
// Adjust dt to make sure that animation is on point
@@ -234,21 +249,27 @@ export default class Timeline extends EventTarget {
}
}
- // Get the next animation frame to keep the simulation going
- if (runnersLeft) {
- this._nextFrame = Animator.frame(this._step.bind(this))
+ // 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._order.length && this._speed < 0 && this._time > 0)) {
+ this._continue()
} else {
- this._nextFrame = null
+ this.fire('finished')
+ this.pause()
}
+
return this
}
// Checks if we are running and continues the animation
- _continue () {
+ _continue (immediateStep = false) {
+ Animator.cancelFrame(this._nextFrame)
+ this._nextFrame = null
+
+ if (immediateStep) return this._step(true)
if (this._paused) return this
- if (!this._nextFrame) {
- this._nextFrame = Animator.frame(this._step.bind(this))
- }
+
+ this._nextFrame = Animator.frame(this._step)
return this
}
diff --git a/src/elements/Bare.js b/src/elements/Bare.js
deleted file mode 100644
index a057634..0000000
--- a/src/elements/Bare.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { nodeOrNew, register, wrapWithAttrCheck } from '../utils/adopter.js'
-import { registerMethods } from '../utils/methods.js'
-import Container from './Container.js'
-import { globals } from '../utils/window.js'
-
-export default class Bare extends Container {
- constructor (node, attrs) {
- super(nodeOrNew(node, typeof node === 'string' ? null : node), attrs)
- }
-
- words (text) {
- // remove contents
- while (this.node.hasChildNodes()) {
- this.node.removeChild(this.node.lastChild)
- }
-
- // create text node
- this.node.appendChild(globals.document.createTextNode(text))
-
- return this
- }
-}
-
-register(Bare)
-
-registerMethods('Container', {
- // Create an element that is not described by SVG.js
- element: wrapWithAttrCheck(function (node) {
- return this.put(new Bare(node))
- })
-})
diff --git a/src/elements/Dom.js b/src/elements/Dom.js
index bccfbb8..ff8542e 100644
--- a/src/elements/Dom.js
+++ b/src/elements/Dom.js
@@ -4,6 +4,7 @@ import {
eid,
extend,
makeInstance,
+ makeNode,
register
} from '../utils/adopter.js'
import { find } from '../modules/core/selector.js'
@@ -88,6 +89,10 @@ export default class Dom extends EventTarget {
return this
}
+ element (nodeName) {
+ return this.put(new Dom(makeNode(nodeName)))
+ }
+
// Get first child
first () {
return adopt(this.node.firstChild)
@@ -285,12 +290,20 @@ export default class Dom extends EventTarget {
fragment.appendChild(well.firstElementChild)
}
+ let parent = this.parent()
+
// Add the whole fragment at once
return outerHTML
- ? this.replace(fragment)
+ ? this.replace(fragment) && parent
: this.add(fragment)
}
+ words (text) {
+ // This is faster than removing all children and adding a new one
+ this.node.textContent = text
+ return this
+ }
+
// write svgjs data to the dom
writeDataToDom () {
// dump variables recursively
diff --git a/src/elements/HtmlNode.js b/src/elements/HtmlNode.js
deleted file mode 100644
index 009b122..0000000
--- a/src/elements/HtmlNode.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import { register } from '../utils/adopter.js'
-import Dom from './Dom.js'
-
-export default class HtmlNode extends Dom {}
-
-register(HtmlNode)
diff --git a/src/elements/Style.js b/src/elements/Style.js
index 50ec50e..0b1cdb7 100644
--- a/src/elements/Style.js
+++ b/src/elements/Style.js
@@ -23,8 +23,8 @@ export default class Style extends Element {
super(nodeOrNew('style', node), node)
}
- words (w) {
- this.node.textContent += (w || '')
+ addText (w = '') {
+ this.node.textContent += w
return this
}
@@ -37,7 +37,7 @@ export default class Style extends Element {
}
rule (selector, obj) {
- return this.words(cssRule(selector, obj))
+ return this.addText(cssRule(selector, obj))
}
}
diff --git a/src/main.js b/src/main.js
index 919fb25..8ea3e5d 100644
--- a/src/main.js
+++ b/src/main.js
@@ -7,7 +7,7 @@ import './modules/optional/memory.js'
import './modules/optional/sugar.js'
import './modules/optional/transform.js'
-import { extend } from './utils/adopter.js'
+import { extend, makeInstance } from './utils/adopter.js'
import { getMethodNames, getMethodsFor } from './utils/methods.js'
import Box from './types/Box.js'
import Circle from './elements/Circle.js'
@@ -30,7 +30,7 @@ import Morphable, {
TransformBag,
makeMorphable,
registerMorphableType
-} from './types/Morphable.js'
+} from './animation/Morphable.js'
import Path from './elements/Path.js'
import PathArray from './types/PathArray.js'
import Pattern from './elements/Pattern.js'
@@ -43,9 +43,13 @@ import SVGArray from './types/SVGArray.js'
import SVGNumber from './types/SVGNumber.js'
import Shape from './elements/Shape.js'
import Svg from './elements/Svg.js'
+import Symbol from './elements/Symbol.js'
import Text from './elements/Text.js'
import Tspan from './elements/Tspan.js'
import * as defaults from './modules/core/defaults.js'
+import * as utils from './utils/utils.js'
+import * as namespaces from './modules/core/namespaces.js'
+import * as regex from './modules/core/regex.js'
export {
Morphable,
@@ -56,9 +60,8 @@ export {
NonMorphable
}
-export { defaults }
-export * from './utils/utils.js'
-export * from './modules/core/namespaces.js'
+export { defaults, utils, namespaces, regex }
+export const SVG = makeInstance
export { default as parser } from './modules/core/parser.js'
export { default as find } from './modules/core/selector.js'
export * from './modules/core/event.js'
@@ -73,19 +76,18 @@ export { default as Runner } from './animation/Runner.js'
export { default as Timeline } from './animation/Timeline.js'
/* Types */
-export { default as SVGArray } from './types/SVGArray.js'
+export { default as Array } from './types/SVGArray.js'
export { default as Box } from './types/Box.js'
export { default as Color } from './types/Color.js'
export { default as EventTarget } from './types/EventTarget.js'
export { default as Matrix } from './types/Matrix.js'
-export { default as SVGNumber } from './types/SVGNumber.js'
+export { default as Number } from './types/SVGNumber.js'
export { default as PathArray } from './types/PathArray.js'
export { default as Point } from './types/Point.js'
export { default as PointArray } from './types/PointArray.js'
export { default as List } from './types/List.js'
/* Elements */
-export { default as Bare } from './elements/Bare.js'
export { default as Circle } from './elements/Circle.js'
export { default as ClipPath } from './elements/ClipPath.js'
export { default as Container } from './elements/Container.js'
@@ -95,7 +97,6 @@ export { default as Element } from './elements/Element.js'
export { default as Ellipse } from './elements/Ellipse.js'
export { default as Gradient } from './elements/Gradient.js'
export { default as G } from './elements/G.js'
-export { default as HtmlNode } from './elements/HtmlNode.js'
export { default as A } from './elements/A.js'
export { default as Image } from './elements/Image.js'
export { default as Line } from './elements/Line.js'
diff --git a/src/modules/optional/arrange.js b/src/modules/optional/arrange.js
index 6ce2eea..f06509a 100644
--- a/src/modules/optional/arrange.js
+++ b/src/modules/optional/arrange.js
@@ -107,5 +107,16 @@ export function insertAfter (element) {
}
registerMethods('Dom', {
- siblings, position, next, prev, forward, backward, front, back, before, after
+ siblings,
+ position,
+ next,
+ prev,
+ forward,
+ backward,
+ front,
+ back,
+ before,
+ after,
+ insertBefore,
+ insertAfter
})
diff --git a/src/polyfills/children.js b/src/polyfills/children.js
new file mode 100644
index 0000000..98e9143
--- /dev/null
+++ b/src/polyfills/children.js
@@ -0,0 +1,8 @@
+import { filter } from '../utils/utils.js'
+
+// IE11: children does not work for svg nodes
+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
new file mode 100644
index 0000000..4be7f1b
--- /dev/null
+++ b/src/polyfills/innerHTML.js
@@ -0,0 +1,95 @@
+/* globals SVGElement, DOMParser */
+
+(function () {
+ try {
+ if (SVGElement.prototype.innerHTML) return
+ } catch (e) { return }
+
+ var serializeXML = function (node, output) {
+ var nodeType = node.nodeType
+ if (nodeType === 3) {
+ output.push(node.textContent.replace(/&/, '&amp;').replace(/</, '&lt;').replace('>', '&gt;'))
+ } else if (nodeType === 1) {
+ output.push('<', node.tagName)
+ if (node.hasAttributes()) {
+ [].forEach.call(node.attributes, function (attrNode) {
+ output.push(' ', attrNode.name, '=\'', attrNode.value, '\'')
+ })
+ }
+ if (node.hasChildNodes()) {
+ output.push('>');
+ [].forEach.call(node.childNodes, function (childNode) {
+ serializeXML(childNode, output)
+ })
+ output.push('</', node.tagName, '>')
+ } else {
+ output.push('/>')
+ }
+ } else if (nodeType === 8) {
+ output.push('<!--', node.nodeValue, '-->')
+ }
+ }
+
+ Object.defineProperty(SVGElement.prototype, 'innerHTML', {
+ get: function () {
+ var output = []
+ var childNode = this.firstChild
+ while (childNode) {
+ serializeXML(childNode, output)
+ childNode = childNode.nextSibling
+ }
+ return output.join('')
+ },
+ set: function (markupText) {
+ while (this.firstChild) {
+ this.removeChild(this.firstChild)
+ }
+
+ try {
+ var dXML = new DOMParser()
+ dXML.async = false
+
+ var sXML = '<svg xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\'>' + markupText + '</svg>'
+ var svgDocElement = dXML.parseFromString(sXML, 'text/xml').documentElement
+
+ var childNode = svgDocElement.firstChild
+ while (childNode) {
+ this.appendChild(this.ownerDocument.importNode(childNode, true))
+ childNode = childNode.nextSibling
+ }
+ } catch (e) {
+ throw new Error('Can not set innerHTML on node')
+ };
+ }
+ })
+
+ Object.defineProperty(SVGElement.prototype, 'outerHTML', {
+ get: function () {
+ var output = []
+ serializeXML(this, output)
+ return output.join('')
+ },
+ set: function (markupText) {
+ while (this.firstChild) {
+ this.removeChild(this.firstChild)
+ }
+
+ try {
+ var dXML = new DOMParser()
+ dXML.async = false
+
+ var sXML = '<svg xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\'>' + markupText + '</svg>'
+ var svgDocElement = dXML.parseFromString(sXML, 'text/xml').documentElement
+
+ var childNode = svgDocElement.firstChild
+ while (childNode) {
+ 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')
+ };
+ }
+ })
+})()
diff --git a/src/svg.js b/src/svg.js
index a9903fe..f6c4bc5 100644
--- a/src/svg.js
+++ b/src/svg.js
@@ -1,5 +1,4 @@
import * as svgMembers from './main.js'
-import * as regex from './modules/core/regex.js'
import { makeInstance } from './utils/adopter.js'
// The main wrapping element
@@ -8,7 +7,3 @@ export default function SVG (element) {
}
Object.assign(SVG, svgMembers)
-
-SVG.utils = SVG
-SVG.regex = regex
-SVG.get = SVG
diff --git a/src/types/Box.js b/src/types/Box.js
index c90c7e0..d2ddcdd 100644
--- a/src/types/Box.js
+++ b/src/types/Box.js
@@ -104,7 +104,7 @@ export default class Box {
}
}
-function getBox (cb) {
+function getBox (cb, retry) {
let box
try {
@@ -114,23 +114,29 @@ function getBox (cb) {
throw new Error('Element not in the dom')
}
} catch (e) {
- try {
- let clone = this.clone().addTo(parser().svg).show()
- box = cb(clone.node)
- clone.remove()
- } catch (e) {
- throw new Error('Getting a bounding box of element "' + this.node.nodeName + '" is not possible')
- }
+ box = retry(this)
}
+
return box
}
export function bbox () {
- return new Box(getBox.call(this, (node) => node.getBBox()))
+ return new Box(getBox.call(this, (node) => node.getBBox(), (el) => {
+ try {
+ let clone = el.clone().addTo(parser().svg).show()
+ let box = clone.node.getBBox()
+ clone.remove()
+ return box
+ } catch (e) {
+ throw new Error('Getting bbox of element "' + el.node.nodeName + '" is not possible')
+ }
+ }))
}
export function rbox (el) {
- let box = new Box(getBox.call(this, (node) => node.getBoundingClientRect()))
+ let box = new Box(getBox.call(this, (node) => node.getBoundingClientRect(), (el) => {
+ throw new Error('Getting rbox of element "' + el.node.nodeName + '" is not possible')
+ }))
if (el) return box.transform(el.screenCTM().inverse())
return box.addOffset()
}
diff --git a/src/types/Color.js b/src/types/Color.js
index 0004251..b745bfd 100644
--- a/src/types/Color.js
+++ b/src/types/Color.js
@@ -78,7 +78,7 @@ export default class 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
} else if (a instanceof Array) {
- this.space = b || a[4] || 'rgb'
+ 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 })
} else if (a instanceof Object) {
// Set the object up and assign its values directly
@@ -109,20 +109,6 @@ export default class Color {
Object.assign(this, components)
}
- opacity (opacity = 1) {
- this.opacity = opacity
- }
-
- /*
-
- */
-
- brightness () {
- const { _a: r, _b: g, _c: b } = this.rgb()
- const value = (r / 255 * 0.30) + (g / 255 * 0.59) + (b / 255 * 0.11)
- return value
- }
-
/*
Conversion Methods
*/
@@ -332,14 +318,14 @@ export default class Color {
Input and Output methods
*/
- hex () {
+ toHex () {
let { _a, _b, _c } = this.rgb()
let [ r, g, b ] = [ _a, _b, _c ].map(componentHex)
return `#${r}${g}${b}`
}
toString () {
- return this.hex()
+ return this.toHex()
}
toRgb () {
diff --git a/src/utils/adopter.js b/src/utils/adopter.js
index ec6b2e5..5830f5c 100644
--- a/src/utils/adopter.js
+++ b/src/utils/adopter.js
@@ -5,7 +5,7 @@ import { globals } from '../utils/window.js'
import Base from '../types/Base.js'
const elements = {}
-export const root = Symbol('root')
+export const root = '___SYMBOL___ROOT___'
// Method for element creation
export function makeNode (name) {
@@ -17,7 +17,7 @@ export function makeInstance (element) {
if (element instanceof Base) return element
if (typeof element === 'object') {
- return adopt(element)
+ return adopter(element)
}
if (element == null) {
@@ -25,7 +25,7 @@ export function makeInstance (element) {
}
if (typeof element === 'string' && element.charAt(0) !== '<') {
- return adopt(globals.document.querySelector(element))
+ return adopter(globals.document.querySelector(element))
}
var node = makeNode('svg')
@@ -33,7 +33,7 @@ export function makeInstance (element) {
// We can use firstChild here because we know,
// that the first char is < and thus an element
- element = adopt(node.firstChild)
+ element = adopter(node.firstChild)
return element
}
@@ -50,25 +50,25 @@ export function adopt (node) {
// make sure a node isn't already adopted
if (node.instance instanceof Base) return node.instance
- if (!(node instanceof globals.window.SVGElement)) {
- return new elements.HtmlNode(node)
- }
-
// initialize variables
- var element
-
- // adopt with element-specific settings
- if (node.nodeName === 'svg') {
- element = new elements[root](node)
- } else if (node.nodeName === 'linearGradient' || node.nodeName === 'radialGradient') {
- element = new elements.Gradient(node)
- } else if (elements[capitalize(node.nodeName)]) {
- element = new elements[capitalize(node.nodeName)](node)
- } else {
- element = new elements.Bare(node)
+ var className = capitalize(node.nodeName)
+
+ // Make sure that gradients are adopted correctly
+ if (className === 'LinearGradient' || className === 'RadialGradient') {
+ className = 'Gradient'
+
+ // Fallback to Dom if element is not known
+ } else if (!elements[className]) {
+ className = 'Dom'
}
- return element
+ return new elements[className](node)
+}
+
+let adopter = adopt
+
+export function mockAdopt (mock = adopt) {
+ adopter = mock
}
export function register (element, name = element.name, asRoot = false) {
@@ -123,9 +123,9 @@ export function extend (modules, methods, attrCheck) {
}
}
-export function extendWithAttrCheck (...args) {
- extend(...args, true)
-}
+// export function extendWithAttrCheck (...args) {
+// extend(...args, true)
+// }
export function wrapWithAttrCheck (fn) {
return function (...args) {
diff --git a/src/utils/methods.js b/src/utils/methods.js
index 527e7b7..bc05a70 100644
--- a/src/utils/methods.js
+++ b/src/utils/methods.js
@@ -1,5 +1,4 @@
const methods = {}
-const constructors = {}
const names = []
export function registerMethods (name, m) {
@@ -11,8 +10,8 @@ export function registerMethods (name, m) {
}
if (typeof name === 'object') {
- for (let [ _name, _m ] of Object.entries(name)) {
- registerMethods(_name, _m)
+ for (let _name in name) {
+ registerMethods(_name, name[_name])
}
return
}
@@ -32,11 +31,3 @@ export function getMethodNames () {
export function addMethodNames (_names) {
names.push(..._names)
}
-
-export function registerConstructor (name, setup) {
- constructors[name] = setup
-}
-
-export function getConstructor (name) {
- return constructors[name] ? { setup: constructors[name], name } : {}
-}
diff --git a/src/utils/window.js b/src/utils/window.js
index 9e51339..626fde3 100644
--- a/src/utils/window.js
+++ b/src/utils/window.js
@@ -7,3 +7,26 @@ export function registerWindow (win = null, doc = null) {
globals.window = win
globals.document = doc
}
+
+const save = {}
+
+export function saveWindow () {
+ save.window = globals.window
+ save.document = globals.document
+}
+
+export function restoreWindow () {
+ globals.window = save.window
+ globals.document = save.document
+}
+
+export function withWindow (win, fn) {
+ saveWindow()
+ registerWindow(win, win.document)
+ fn(win, win.document)
+ restoreWindow()
+}
+
+export function getWindow () {
+ return globals.window
+}