aboutsummaryrefslogtreecommitdiffstats
path: root/src/elements
diff options
context:
space:
mode:
Diffstat (limited to 'src/elements')
-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
26 files changed, 149 insertions, 155 deletions
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)
})
}
})