summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/animation/Runner.js2
-rw-r--r--src/elements/A.js42
-rw-r--r--src/elements/Circle.js4
-rw-r--r--src/elements/ClipPath.js4
-rw-r--r--src/elements/Defs.js4
-rw-r--r--src/elements/Dom.js28
-rw-r--r--src/elements/Element.js15
-rw-r--r--src/elements/Ellipse.js4
-rw-r--r--src/elements/ForeignObject.js4
-rw-r--r--src/elements/G.js4
-rw-r--r--src/elements/Image.js4
-rw-r--r--src/elements/Line.js4
-rw-r--r--src/elements/Marker.js8
-rw-r--r--src/elements/Mask.js4
-rw-r--r--src/elements/Path.js4
-rw-r--r--src/elements/Pattern.js4
-rw-r--r--src/elements/Polygon.js4
-rw-r--r--src/elements/Polyline.js4
-rw-r--r--src/elements/Rect.js4
-rw-r--r--src/elements/Stop.js4
-rw-r--r--src/elements/Style.js4
-rw-r--r--src/elements/Svg.js4
-rw-r--r--src/elements/Symbol.js4
-rw-r--r--src/elements/Text.js69
-rw-r--r--src/elements/TextPath.js6
-rw-r--r--src/elements/Tspan.js56
-rw-r--r--src/elements/Use.js8
-rw-r--r--src/modules/core/event.js15
-rw-r--r--src/modules/core/textable.js64
-rw-r--r--src/modules/optional/sugar.js29
-rw-r--r--src/svg.js4
-rw-r--r--src/types/Box.js4
-rw-r--r--src/utils/adopter.js5
-rw-r--r--src/utils/utils.js61
34 files changed, 274 insertions, 214 deletions
diff --git a/src/animation/Runner.js b/src/animation/Runner.js
index 8c0aca5..8c56423 100644
--- a/src/animation/Runner.js
+++ b/src/animation/Runner.js
@@ -681,7 +681,7 @@ extend(Runner, {
},
zoom (level, point) {
- if (this._tryRetarget('zoom', to, point)) return this
+ if (this._tryRetarget('zoom', level, point)) return this
var morpher = new Morphable(this._stepper).to(new SVGNumber(level))
diff --git a/src/elements/A.js b/src/elements/A.js
index 4e7297b..6f9bec2 100644
--- a/src/elements/A.js
+++ b/src/elements/A.js
@@ -4,8 +4,8 @@ import { xlink } from '../modules/core/namespaces.js'
import Container from './Container.js'
export default class A extends Container {
- constructor (node) {
- super(nodeOrNew('a', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('a', node), attrs)
}
// Link url
@@ -27,9 +27,31 @@ registerMethods({
})
},
Element: {
- // Create a hyperlink element
- linkTo: function (url) {
- var link = new A()
+ unlink () {
+ var link = this.linker()
+
+ if (!link) return this
+
+ var parent = link.parent()
+
+ if (!parent) {
+ return this.remove()
+ }
+
+ var index = parent.index(link)
+ parent.add(this, index)
+
+ link.remove()
+ return this
+ },
+ linkTo (url) {
+ // reuse old link if possible
+ var link = this.linker()
+
+ if (!link) {
+ link = new A()
+ this.wrap(link)
+ }
if (typeof url === 'function') {
url.call(link, link)
@@ -37,7 +59,15 @@ registerMethods({
link.to(url)
}
- return this.parent().put(link).put(this)
+ return this
+ },
+ linker () {
+ var link = this.parent()
+ if (link && link.node.nodeName.toLowerCase() === 'a') {
+ return link
+ }
+
+ return null
}
}
})
diff --git a/src/elements/Circle.js b/src/elements/Circle.js
index 29683c9..701b5e1 100644
--- a/src/elements/Circle.js
+++ b/src/elements/Circle.js
@@ -10,8 +10,8 @@ import SVGNumber from '../types/SVGNumber.js'
import Shape from './Shape.js'
export default class Circle extends Shape {
- constructor (node) {
- super(nodeOrNew('circle', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('circle', node), attrs)
}
radius (r) {
diff --git a/src/elements/ClipPath.js b/src/elements/ClipPath.js
index 0a87bed..55f9c3d 100644
--- a/src/elements/ClipPath.js
+++ b/src/elements/ClipPath.js
@@ -4,8 +4,8 @@ import Container from './Container.js'
import baseFind from '../modules/core/selector.js'
export default class ClipPath extends Container {
- constructor (node) {
- super(nodeOrNew('clipPath', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('clipPath', node), attrs)
}
// Unclip all clipped elements and remove itself
diff --git a/src/elements/Defs.js b/src/elements/Defs.js
index 1bd3bd4..7491ba0 100644
--- a/src/elements/Defs.js
+++ b/src/elements/Defs.js
@@ -2,8 +2,8 @@ import { nodeOrNew, register } from '../utils/adopter.js'
import Container from './Container.js'
export default class Defs extends Container {
- constructor (node) {
- super(nodeOrNew('defs', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('defs', node), attrs)
}
flatten () {
diff --git a/src/elements/Dom.js b/src/elements/Dom.js
index 0c4ecb3..6fd1b1b 100644
--- a/src/elements/Dom.js
+++ b/src/elements/Dom.js
@@ -194,22 +194,15 @@ export default class Dom extends EventTarget {
return element
}
- round (precision = 2, map) {
+ round (precision = 2, map = null) {
const factor = 10 ** precision
- const attrs = this.attr()
+ const attrs = this.attr(map)
- // If we have no map, build one from attrs
- if (!map) {
- map = Object.keys(attrs)
+ for (const i in attrs) {
+ attrs[i] = Math.round(attrs[i] * factor) / factor
}
- // Holds rounded attributes
- const newAttrs = {}
- map.forEach((key) => {
- newAttrs[key] = Math.round(attrs[key] * factor) / factor
- })
-
- this.attr(newAttrs)
+ this.attr(attrs)
return this
}
@@ -302,6 +295,17 @@ export default class Dom extends EventTarget {
return this
}
+ wrap (node) {
+ const parent = this.parent()
+
+ if (!parent) {
+ return node.put(this)
+ }
+
+ const position = parent.index(this)
+ return parent.put(node, position).put(this)
+ }
+
// write svgjs data to the dom
writeDataToDom () {
// dump variables recursively
diff --git a/src/elements/Element.js b/src/elements/Element.js
index 3bd97de..56dbcf3 100644
--- a/src/elements/Element.js
+++ b/src/elements/Element.js
@@ -38,7 +38,9 @@ export default class Element extends Dom {
// Move by center over x-axis
cx (x) {
- return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2)
+ return x == null
+ ? this.x() + this.width() / 2
+ : this.x(x - this.width() / 2)
}
// Move by center over y-axis
@@ -99,17 +101,16 @@ export default class Element extends Dom {
}
// return array of all ancestors of given type up to the root svg
- parents (until = globals.document) {
+ parents (until = this.root()) {
until = makeInstance(until)
const parents = new List()
let parent = this
- while (
- (parent = parent.parent())
- && parent.node !== until.node
- && parent.node !== globals.document
- ) {
+ while ((parent = parent.parent()) && parent.node !== globals.document) {
parents.push(parent)
+ if (parent.node === until.node) {
+ break
+ }
}
return parents
diff --git a/src/elements/Ellipse.js b/src/elements/Ellipse.js
index 60660e7..b993687 100644
--- a/src/elements/Ellipse.js
+++ b/src/elements/Ellipse.js
@@ -11,8 +11,8 @@ import Shape from './Shape.js'
import * as circled from '../modules/core/circled.js'
export default class Ellipse extends Shape {
- constructor (node) {
- super(nodeOrNew('ellipse', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('ellipse', node), attrs)
}
size (width, height) {
diff --git a/src/elements/ForeignObject.js b/src/elements/ForeignObject.js
index 4e6aae4..0a417b0 100644
--- a/src/elements/ForeignObject.js
+++ b/src/elements/ForeignObject.js
@@ -3,8 +3,8 @@ import { registerMethods } from '../utils/methods.js'
import Element from './Element.js'
export default class ForeignObject extends Element {
- constructor (node) {
- super(nodeOrNew('foreignObject', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('foreignObject', node), attrs)
}
}
diff --git a/src/elements/G.js b/src/elements/G.js
index d922a41..7677b92 100644
--- a/src/elements/G.js
+++ b/src/elements/G.js
@@ -6,8 +6,8 @@ import Matrix from '../types/Matrix.js'
import Point from '../types/Point.js'
export default class G extends Container {
- constructor (node) {
- super(nodeOrNew('g', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('g', node), attrs)
}
x (x, box = this.bbox()) {
diff --git a/src/elements/Image.js b/src/elements/Image.js
index fdd3d83..347269c 100644
--- a/src/elements/Image.js
+++ b/src/elements/Image.js
@@ -9,8 +9,8 @@ import Shape from './Shape.js'
import { globals } from '../utils/window.js'
export default class Image extends Shape {
- constructor (node) {
- super(nodeOrNew('image', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('image', node), attrs)
}
// (re)load image
diff --git a/src/elements/Line.js b/src/elements/Line.js
index 0b7534b..146aa45 100644
--- a/src/elements/Line.js
+++ b/src/elements/Line.js
@@ -12,8 +12,8 @@ import * as pointed from '../modules/core/pointed.js'
export default class Line extends Shape {
// Initialize node
- constructor (node) {
- super(nodeOrNew('line', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('line', node), attrs)
}
// Get array
diff --git a/src/elements/Marker.js b/src/elements/Marker.js
index d6a599d..b3077b1 100644
--- a/src/elements/Marker.js
+++ b/src/elements/Marker.js
@@ -4,8 +4,8 @@ import Container from './Container.js'
export default class Marker extends Container {
// Initialize node
- constructor (node) {
- super(nodeOrNew('marker', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('marker', node), attrs)
}
// Set width of element
@@ -18,6 +18,10 @@ export default class Marker extends Container {
return this.attr('markerHeight', height)
}
+ orient (orient) {
+ return this.attr('orient', orient)
+ }
+
// Set marker refX and refY
ref (x, y) {
return this.attr('refX', x).attr('refY', y)
diff --git a/src/elements/Mask.js b/src/elements/Mask.js
index 178dcb5..64caca5 100644
--- a/src/elements/Mask.js
+++ b/src/elements/Mask.js
@@ -5,8 +5,8 @@ import baseFind from '../modules/core/selector.js'
export default class Mask extends Container {
// Initialize node
- constructor (node) {
- super(nodeOrNew('mask', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('mask', node), attrs)
}
// Unmask all masked elements and remove itself
diff --git a/src/elements/Path.js b/src/elements/Path.js
index 4549506..8f37319 100644
--- a/src/elements/Path.js
+++ b/src/elements/Path.js
@@ -7,8 +7,8 @@ import baseFind from '../modules/core/selector.js'
export default class Path extends Shape {
// Initialize node
- constructor (node) {
- super(nodeOrNew('path', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('path', node), attrs)
}
// Get array
diff --git a/src/elements/Pattern.js b/src/elements/Pattern.js
index 99e8ded..72b7c59 100644
--- a/src/elements/Pattern.js
+++ b/src/elements/Pattern.js
@@ -6,8 +6,8 @@ import baseFind from '../modules/core/selector.js'
export default class Pattern extends Container {
// Initialize node
- constructor (node) {
- super(nodeOrNew('pattern', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('pattern', node), attrs)
}
// Return the fill id
diff --git a/src/elements/Polygon.js b/src/elements/Polygon.js
index 5984689..0c99aa7 100644
--- a/src/elements/Polygon.js
+++ b/src/elements/Polygon.js
@@ -12,8 +12,8 @@ import * as poly from '../modules/core/poly.js'
export default class Polygon extends Shape {
// Initialize node
- constructor (node) {
- super(nodeOrNew('polygon', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('polygon', node), attrs)
}
}
diff --git a/src/elements/Polyline.js b/src/elements/Polyline.js
index 94a767c..e390da3 100644
--- a/src/elements/Polyline.js
+++ b/src/elements/Polyline.js
@@ -12,8 +12,8 @@ import * as poly from '../modules/core/poly.js'
export default class Polyline extends Shape {
// Initialize node
- constructor (node) {
- super(nodeOrNew('polyline', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('polyline', node), attrs)
}
}
diff --git a/src/elements/Rect.js b/src/elements/Rect.js
index 149ae48..0ed85fc 100644
--- a/src/elements/Rect.js
+++ b/src/elements/Rect.js
@@ -10,8 +10,8 @@ import Shape from './Shape.js'
export default class Rect extends Shape {
// Initialize node
- constructor (node) {
- super(nodeOrNew('rect', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('rect', node), attrs)
}
}
diff --git a/src/elements/Stop.js b/src/elements/Stop.js
index 570dda7..d258b86 100644
--- a/src/elements/Stop.js
+++ b/src/elements/Stop.js
@@ -3,8 +3,8 @@ import Element from './Element.js'
import SVGNumber from '../types/SVGNumber.js'
export default class Stop extends Element {
- constructor (node) {
- super(nodeOrNew('stop', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('stop', node), attrs)
}
// add color stops
diff --git a/src/elements/Style.js b/src/elements/Style.js
index b878189..0b7d952 100644
--- a/src/elements/Style.js
+++ b/src/elements/Style.js
@@ -19,8 +19,8 @@ function cssRule (selector, rule) {
}
export default class Style extends Element {
- constructor (node) {
- super(nodeOrNew('style', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('style', node), attrs)
}
addText (w = '') {
diff --git a/src/elements/Svg.js b/src/elements/Svg.js
index f96a5f8..7cec826 100644
--- a/src/elements/Svg.js
+++ b/src/elements/Svg.js
@@ -11,8 +11,8 @@ import Defs from './Defs.js'
import { globals } from '../utils/window.js'
export default class Svg extends Container {
- constructor (node) {
- super(nodeOrNew('svg', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('svg', node), attrs)
this.namespace()
}
diff --git a/src/elements/Symbol.js b/src/elements/Symbol.js
index 3dd48d7..d2a98ac 100644
--- a/src/elements/Symbol.js
+++ b/src/elements/Symbol.js
@@ -4,8 +4,8 @@ import Container from './Container.js'
export default class Symbol extends Container {
// Initialize node
- constructor (node) {
- super(nodeOrNew('symbol', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('symbol', node), attrs)
}
}
diff --git a/src/elements/Text.js b/src/elements/Text.js
index b3fb8e0..2951c2f 100644
--- a/src/elements/Text.js
+++ b/src/elements/Text.js
@@ -13,60 +13,14 @@ import * as textable from '../modules/core/textable.js'
export default class Text extends Shape {
// Initialize node
- constructor (node) {
- super(nodeOrNew('text', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('text', node), attrs)
this.dom.leading = new SVGNumber(1.3) // store leading value for rebuilding
this._rebuild = true // enable automatic updating of dy values
this._build = false // disable build mode for adding multiple lines
}
- // Move over x-axis
- // Text is moved its bounding box
- // text-anchor does NOT matter
- x (x, box = this.bbox()) {
- if (x == null) {
- return box.x
- }
-
- return this.attr('x', this.attr('x') + x - box.x)
- }
-
- // Move over y-axis
- y (y, box = this.bbox()) {
- if (y == null) {
- return box.y
- }
-
- return this.attr('y', this.attr('y') + y - box.y)
- }
-
- move (x, y, box = this.bbox()) {
- return this.x(x, box).y(y, box)
- }
-
- // Move center over x-axis
- cx (x, box = this.bbox()) {
- if (x == null) {
- return box.cx
- }
-
- return this.attr('x', this.attr('x') + x - box.cx)
- }
-
- // Move center over y-axis
- cy (y, box = this.bbox()) {
- if (y == null) {
- return box.cy
- }
-
- return this.attr('y', this.attr('y') + y - box.cy)
- }
-
- center (x, y, box = this.bbox()) {
- return this.cx(x, box).cy(y, box)
- }
-
// Set the text content
text (text) {
// act as getter
@@ -102,11 +56,11 @@ export default class Text extends Shape {
text.call(this, this)
} else {
// store text and make sure text is not blank
- text = text.split('\n')
+ text = (text + '').split('\n')
// build new lines
for (var j = 0, jl = text.length; j < jl; j++) {
- this.tspan(text[j]).newLine()
+ this.newLine(text[j])
}
}
@@ -140,9 +94,10 @@ export default class Text extends Shape {
var blankLineOffset = 0
var leading = this.dom.leading
- this.each(function () {
+ this.each(function (i) {
var fontSize = globals.window.getComputedStyle(this.node)
.getPropertyValue('font-size')
+
var dy = leading * new SVGNumber(fontSize)
if (this.dom.newLined) {
@@ -151,7 +106,7 @@ export default class Text extends Shape {
if (this.text() === '\n') {
blankLineOffset += dy
} else {
- this.attr('dy', dy + blankLineOffset)
+ this.attr('dy', i ? dy + blankLineOffset : 0)
blankLineOffset = 0
}
}
@@ -163,12 +118,6 @@ export default class Text extends Shape {
return this
}
- // Enable / disable build mode
- build (build) {
- this._build = !!build
- return this
- }
-
// overwrite method from parent to set data properly
setData (o) {
this.dom = o
@@ -182,12 +131,12 @@ extend(Text, textable)
registerMethods({
Container: {
// Create text element
- text: wrapWithAttrCheck(function (text) {
+ text: wrapWithAttrCheck(function (text = '') {
return this.put(new Text()).text(text)
}),
// Create plain text element
- plain: wrapWithAttrCheck(function (text) {
+ plain: wrapWithAttrCheck(function (text = '') {
return this.put(new Text()).plain(text)
})
}
diff --git a/src/elements/TextPath.js b/src/elements/TextPath.js
index f26b251..fde8131 100644
--- a/src/elements/TextPath.js
+++ b/src/elements/TextPath.js
@@ -8,8 +8,8 @@ import baseFind from '../modules/core/selector.js'
export default class TextPath extends Text {
// Initialize node
- constructor (node) {
- super(nodeOrNew('textPath', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('textPath', node), attrs)
}
// return the array of the path track element
@@ -92,7 +92,7 @@ registerMethods({
}),
targets () {
- return baseFind('svg [href*="' + this.id() + '"]')
+ return baseFind('svg [*|href*="' + this.id() + '"]')
}
}
})
diff --git a/src/elements/Tspan.js b/src/elements/Tspan.js
index 11f7fc3..00934ab 100644
--- a/src/elements/Tspan.js
+++ b/src/elements/Tspan.js
@@ -7,20 +7,28 @@ import {
import { globals } from '../utils/window.js'
import { registerMethods } from '../utils/methods.js'
import SVGNumber from '../types/SVGNumber.js'
+import Shape from './Shape.js'
import Text from './Text.js'
import * as textable from '../modules/core/textable.js'
-export default class Tspan extends Text {
+export default class Tspan extends Shape {
// Initialize node
- constructor (node) {
- super(nodeOrNew('tspan', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('tspan', node), attrs)
+ this._build = false // disable build mode for adding multiple lines
}
// Set text content
text (text) {
if (text == null) return this.node.textContent + (this.dom.newLined ? '\n' : '')
- typeof text === 'function' ? text.call(this, this) : this.plain(text)
+ if (typeof text === 'function') {
+ this.clear().build(true)
+ text.call(this, this)
+ this.build(false)
+ } else {
+ this.plain(text)
+ }
return this
}
@@ -35,32 +43,27 @@ export default class Tspan extends Text {
return this.attr('dy', dy)
}
- x (x) {
- return this.attr('x', x)
- }
-
- y (y) {
- return this.attr('x', y)
- }
-
- move (x, y) {
- return this.x(x).y(y)
- }
-
// Create new line
newLine () {
- // fetch text parent
- var t = this.parent(Text)
-
// mark new line
this.dom.newLined = true
+ // fetch parent
+ var text = this.parent()
+
+ // early return in case we are not in a text element
+ if (!(text instanceof Text)) {
+ return this
+ }
+
+ var i = text.index(this)
+
var fontSize = globals.window.getComputedStyle(this.node)
.getPropertyValue('font-size')
- var dy = t.dom.leading * new SVGNumber(fontSize)
+ var dy = text.dom.leading * new SVGNumber(fontSize)
// apply new position
- return this.dy(dy).attr('x', t.x())
+ return this.dy(i ? dy : 0).attr('x', text.x())
}
}
@@ -68,7 +71,7 @@ extend(Tspan, textable)
registerMethods({
Tspan: {
- tspan: wrapWithAttrCheck(function (text) {
+ tspan: wrapWithAttrCheck(function (text = '') {
var tspan = new Tspan()
// clear if build mode is disabled
@@ -77,10 +80,13 @@ registerMethods({
}
// add new tspan
- this.node.appendChild(tspan.node)
-
- return tspan.text(text)
+ return this.put(tspan).text(text)
})
+ },
+ Text: {
+ newLine: function (text = '') {
+ return this.tspan(text).newLine()
+ }
}
})
diff --git a/src/elements/Use.js b/src/elements/Use.js
index 99fb8ec..30d9436 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) {
- super(nodeOrNew('use', node), node)
+ constructor (node, attrs = node) {
+ super(nodeOrNew('use', node), attrs)
}
// Use element as a reference
- element (element, file) {
+ use (element, file) {
// Set lined element
return this.attr('href', (file || '') + '#' + element, xlink)
}
@@ -19,7 +19,7 @@ registerMethods({
Container: {
// Create a use element
use: wrapWithAttrCheck(function (element, file) {
- return this.put(new Use()).element(element, file)
+ return this.put(new Use()).use(element, file)
})
}
})
diff --git a/src/modules/core/event.js b/src/modules/core/event.js
index 2cf9b1e..976e13d 100644
--- a/src/modules/core/event.js
+++ b/src/modules/core/event.js
@@ -3,9 +3,9 @@ import { makeInstance } from '../../utils/adopter.js'
import { globals } from '../../utils/window.js'
let listenerId = 0
-const windowEvents = {}
+export const windowEvents = {}
-function getEvents (instance) {
+export function getEvents (instance) {
let n = instance.getEventHolder()
// We dont want to save events in global space
@@ -14,12 +14,13 @@ function getEvents (instance) {
return n.events
}
-function getEventTarget (instance) {
+export function getEventTarget (instance) {
return instance.getEventTarget()
}
-function clearEvents (instance) {
- const n = instance.getEventHolder()
+export function clearEvents (instance) {
+ let n = instance.getEventHolder()
+ if (n === globals.window) n = windowEvents
if (n.events) n.events = {}
}
@@ -120,14 +121,14 @@ export function off (node, events, listener, options) {
})
}
-export function dispatch (node, event, data) {
+export function dispatch (node, event, data, options) {
var 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 })
+ event = new globals.window.CustomEvent(event, { detail: data, cancelable: true, ...options })
n.dispatchEvent(event)
}
return event
diff --git a/src/modules/core/textable.js b/src/modules/core/textable.js
index 55df7c6..28b13cb 100644
--- a/src/modules/core/textable.js
+++ b/src/modules/core/textable.js
@@ -17,3 +17,67 @@ export function plain (text) {
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()) {
+ if (x == null) {
+ return box.x
+ }
+
+ return this.attr('x', this.attr('x') + x - box.x)
+}
+
+// Move over y-axis
+export function y (y, box = this.bbox()) {
+ if (y == null) {
+ return box.y
+ }
+
+ return this.attr('y', this.attr('y') + y - box.y)
+}
+
+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()) {
+ if (x == null) {
+ return box.cx
+ }
+
+ return this.attr('x', this.attr('x') + x - box.cx)
+}
+
+// Move center over y-axis
+export function cy (y, box = this.bbox()) {
+ if (y == null) {
+ return box.cy
+ }
+
+ return this.attr('y', this.attr('y') + y - box.cy)
+}
+
+export function center (x, y, box = this.bbox()) {
+ return this.cx(x, box).cy(y, box)
+}
+
+export function ax (x) {
+ return this.attr('x', x)
+}
+
+export function ay (y) {
+ return this.attr('y', y)
+}
+
+export function amove (x, y) {
+ return this.ax(x).ay(y)
+}
+
+// Enable / disable build mode
+export function build (build) {
+ this._build = !!build
+ return this
+}
diff --git a/src/modules/optional/sugar.js b/src/modules/optional/sugar.js
index 0da0fe4..0de2c04 100644
--- a/src/modules/optional/sugar.js
+++ b/src/modules/optional/sugar.js
@@ -87,16 +87,13 @@ registerMethods([ 'Element', 'Runner' ], {
},
// Map flip to transform
- flip: function (direction, around) {
- var directionString = typeof direction === 'string' ? direction
- : isFinite(direction) ? 'both'
- : 'both'
- var origin = (direction === 'both' && isFinite(around)) ? [ around, around ]
- : (direction === 'x') ? [ around, 0 ]
- : (direction === 'y') ? [ 0, around ]
- : isFinite(direction) ? [ direction, direction ]
- : [ 0, 0 ]
- return this.transform({ flip: directionString, origin: origin }, true)
+ flip: function (direction = 'both', origin = 'center') {
+ if ('xybothtrue'.indexOf(direction) === -1) {
+ origin = direction
+ direction = 'both'
+ }
+
+ return this.transform({ flip: direction, origin: origin }, true)
},
// Opacity
@@ -144,18 +141,6 @@ registerMethods([ 'Element', 'Runner' ], {
}
})
-registerMethods('Text', {
- ax (x) {
- return this.attr('x', x)
- },
- ay (y) {
- return this.attr('y', y)
- },
- amove (x, y) {
- return this.ax(x).ay(y)
- }
-})
-
// Add events to elements
const methods = [ 'click',
'dblclick',
diff --git a/src/svg.js b/src/svg.js
index f6c4bc5..85f2518 100644
--- a/src/svg.js
+++ b/src/svg.js
@@ -2,8 +2,8 @@ import * as svgMembers from './main.js'
import { makeInstance } from './utils/adopter.js'
// The main wrapping element
-export default function SVG (element) {
- return makeInstance(element)
+export default function SVG (element, isHTML) {
+ return makeInstance(element, isHTML)
}
Object.assign(SVG, svgMembers)
diff --git a/src/types/Box.js b/src/types/Box.js
index 5c31535..6d7d8a9 100644
--- a/src/types/Box.js
+++ b/src/types/Box.js
@@ -95,7 +95,7 @@ export default class Box {
// offset by window scroll position, because getBoundingClientRect changes when window is scrolled
this.x += globals.window.pageXOffset
this.y += globals.window.pageYOffset
- return this
+ return new Box(this)
}
toString () {
@@ -166,7 +166,7 @@ registerMethods({
// Firefox does not support clientHeight and returns 0
// https://bugzilla.mozilla.org/show_bug.cgi?id=874811
if (!width && !height) {
- var style = window.getComputedStyle(this.node)
+ var style = globals.window.getComputedStyle(this.node)
width = parseFloat(style.getPropertyValue('width'))
height = parseFloat(style.getPropertyValue('height'))
}
diff --git a/src/utils/adopter.js b/src/utils/adopter.js
index e8b30ea..30eab84 100644
--- a/src/utils/adopter.js
+++ b/src/utils/adopter.js
@@ -13,7 +13,7 @@ export function create (name) {
return globals.document.createElementNS(ns, name)
}
-export function makeInstance (element) {
+export function makeInstance (element, isHTML = false) {
if (element instanceof Base) return element
if (typeof element === 'object') {
@@ -28,7 +28,8 @@ export function makeInstance (element) {
return adopter(globals.document.querySelector(element))
}
- var node = create('svg')
+ // Make sure, that HTML elements are created with the correct namespace
+ var node = isHTML ? globals.document.createElement('div') : create('svg')
node.innerHTML = element
// We can use firstChild here because we know,
diff --git a/src/utils/utils.js b/src/utils/utils.js
index 5d8706e..ee47079 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -43,7 +43,7 @@ export function camelCase (s) {
})
}
-// Convert camel cased string to string seperated
+// Convert camel cased string to dash seperated
export function unCamelCase (s) {
return s.replace(/([A-Z])/g, function (m, g) {
return '-' + g.toLowerCase()
@@ -73,31 +73,46 @@ 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) {
- // Allow origin or around as the names
- const origin = o.origin // o.around == null ? o.origin : o.around
- let ox, oy
-
- // Allow the user to pass a string to rotate around a given point
- if (typeof origin === 'string' || origin == null) {
- // Get the bounding box of the element with no transformations applied
- const string = (origin || 'center').toLowerCase().trim()
+ 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'
+
+ // Then check if origin was used and overwrite in that case
+ if (origin != null) {
+ [ ox, oy ] = Array.isArray(origin) ? origin
+ : typeof origin === 'object' ? [ origin.x, origin.y ]
+ : [ origin, origin ]
+ }
+
+ // Make sure to only call bbox when actually needed
+ const condX = typeof ox === 'string'
+ const condY = typeof oy === 'string'
+ if (condX || condY) {
const { height, width, x, y } = element.bbox()
- // Calculate the transformed x and y coordinates
- const bx = string.includes('left') ? x
- : string.includes('right') ? x + width
- : x + width / 2
- const by = string.includes('top') ? y
- : string.includes('bottom') ? y + height
- : y + height / 2
-
- // Set the bounds eg : "bottom-left", "Top right", "middle" etc...
- ox = o.ox != null ? o.ox : bx
- oy = o.oy != null ? o.oy : by
- } else {
- ox = origin[0]
- oy = origin[1]
+ // And only overwrite if string was passed for this specific axis
+ if (condX) {
+ ox = ox.includes('left') ? x
+ : ox.includes('right') ? x + width
+ : x + width / 2
+ }
+
+ if (condY) {
+ oy = oy.includes('top') ? y
+ : oy.includes('bottom') ? y + height
+ : y + height / 2
+ }
}
// Return the origin as it is if it wasn't a string