master
yutent 2024-03-15 18:43:46 +08:00
parent 4814b9c398
commit e141a2db96
4 changed files with 105 additions and 195 deletions

View File

@ -456,39 +456,34 @@ elproto.asPX = function (attr, value) {
} }
return +unit2px(this, attr, value) return +unit2px(this, attr, value)
} }
// SIERRA SnapElement.use(): I suggest adding a note about how to access the original element the returned <use> instantiates. It's a part of SVG with which ordinary web developers may be least familiar. /***
/*\ * Creates a `<use>` element linked to the current element
* SnapElement.use **
[ method ] = (SnapElement) the `<use>` element
** */
* Creates a `<use>` element linked to the current element
**
= (SnapElement) the `<use>` element
\*/
elproto.use = function () { elproto.use = function () {
let use, let id = this.node.id
id = this.node.id let attr, use
if (!id) { if (!id) {
id = this.id id = this.id
$(this.node, { this.node.id = id
id: id
})
} }
attr = { 'xlink:href': '#' + id }
if ( if (
this.type == 'linearGradient' || this.type == 'linearGradient' ||
this.type == 'radialGradient' || this.type == 'radialGradient' ||
this.type == 'pattern' this.type == 'pattern'
) { ) {
use = make(this.type, this.node.parentNode) use = make(this.type, this.node.parentNode, attr)
} else { } else {
use = make('use', this.node.parentNode) use = make('use', this.node.parentNode, attr)
} }
$(use.node, {
'xlink:href': '#' + id
})
use.original = this use.original = this
return use return use
} }
function fixids(el) { function fixids(el) {
let els = el.selectAll('*'), let els = el.selectAll('*'),
it, it,
@ -561,9 +556,7 @@ function fixids(el) {
\*/ \*/
elproto.clone = function () { elproto.clone = function () {
let clone = wrap(this.node.cloneNode(true)) let clone = wrap(this.node.cloneNode(true))
if ($(clone.node, 'id')) {
$(clone.node, { id: clone.id })
}
fixids(clone) fixids(clone)
clone.insertAfter(this) clone.insertAfter(this)
return clone return clone

View File

@ -6,7 +6,7 @@
import eve from './eve.js' import eve from './eve.js'
import { Snap, SnapElement, Paper, make } from './svg.js' import { Snap, SnapElement, Paper, make } from './svg.js'
import { $, is, uuid, preload } from './utils.js' import { $, h, is, uuid, preload } from './utils.js'
import { doc, win } from './lib/constants.js' import { doc, win } from './lib/constants.js'
let proto = Paper.prototype let proto = Paper.prototype
@ -28,20 +28,19 @@ let proto = Paper.prototype
* offset (number) stops offset 0..100 * offset (number) stops offset 0..100
*/ */
function GaddStop(color, offset) { function GaddStop(color, offset) {
let stop = $('stop'), let attr = {
attr = { offset: +offset + '%'
offset: +offset + '%' }
}
color = parseColor(color) color = parseColor(color)
attr['stop-color'] = color.hex attr['stop-color'] = color.hex
if (color.opacity < 1) { if (color.opacity < 1) {
attr['stop-opacity'] = color.opacity attr['stop-opacity'] = color.opacity
} }
$(stop, attr) let stop = h('stop', attr)
let stops = this.stops(), let stops = this.stops(),
inserted inserted
for (let i = 0; i < stops.length; i++) { for (let i = 0; i < stops.length; i++) {
let stopOffset = parseFloat(stops[i].attr('offset')) let stopOffset = +stops[i].attr('offset')
if (stopOffset > offset) { if (stopOffset > offset) {
this.node.insertBefore(stop, stops[i].node) this.node.insertBefore(stop, stops[i].node)
inserted = true inserted = true

View File

@ -26,14 +26,6 @@ import {
extend extend
} from './utils.js' } from './utils.js'
let has = 'hasOwnProperty',
math = Math,
abs = math.abs,
E = '',
S = ' ',
objectToString = Object.prototype.toString,
hub = {}
export function make(name, parent = doc.body, attr, children) { export function make(name, parent = doc.body, attr, children) {
let el = h(name, attr, children) let el = h(name, attr, children)
parent.appendChild(el) parent.appendChild(el)
@ -245,7 +237,7 @@ export class Snap {
if (is(values, 'array')) { if (is(values, 'array')) {
let i = values.length let i = values.length
while (i--) while (i--)
if (abs(values[i] - value) <= tolerance) { if (Math.abs(values[i] - value) <= tolerance) {
return values[i] return values[i]
} }
} else { } else {
@ -423,9 +415,9 @@ function svgTransform2string(tstr) {
} }
} }
if (name == 'skewX') { if (name == 'skewX') {
res.push(['m', 1, 0, math.tan(rad(params[0])), 1, 0, 0]) res.push(['m', 1, 0, Math.tan(rad(params[0])), 1, 0, 0])
} else if (name == 'skewY') { } else if (name == 'skewY') {
res.push(['m', 1, math.tan(rad(params[0])), 0, 1, 0, 0]) res.push(['m', 1, Math.tan(rad(params[0])), 0, 1, 0, 0])
} else { } else {
res.push([name.charAt(0)].concat(params)) res.push([name.charAt(0)].concat(params))
} }
@ -545,7 +537,7 @@ export function unit2px(el, name, value) {
} }
function getW(val) { function getW(val) {
if (val == null) { if (val == null) {
return E return ''
} }
if (val == +val) { if (val == +val) {
return val return val
@ -559,7 +551,7 @@ export function unit2px(el, name, value) {
} }
function getH(val) { function getH(val) {
if (val == null) { if (val == null) {
return E return ''
} }
if (val == +val) { if (val == +val) {
return val return val
@ -627,45 +619,23 @@ export function unit2px(el, name, value) {
return out return out
} }
function add2group(list) { function add2group(...list) {
if (!is(list, 'array')) { let i = 0
list = Array.prototype.slice.call(arguments, 0) let node = this.node
while (this[i]) {
delete this[i++]
} }
let i = 0,
j = 0, for (let it of list) {
node = this.node node.appendChild(it.node)
while (this[i]) delete this[i++]
for (i = 0; i < list.length; i++) {
if (list[i].type == 'set') {
list[i].forEach(function (el) {
node.appendChild(el.node)
})
} else {
node.appendChild(list[i].node)
}
} }
let children = node.childNodes let children = Array.from(node.childNodes)
for (i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
this[j++] = wrap(children[i]) this[i] = wrap(children[i])
} }
return this return this
} }
// Hub garbage collector every 10s
setInterval(function () {
for (let key in hub)
if (hub[has](key)) {
let el = hub[key],
node = el.node
if (
(el.type != 'svg' && !node.ownerSVGElement) ||
(el.type == 'svg' &&
(!node.parentNode ||
('ownerSVGElement' in node.parentNode && !node.ownerSVGElement)))
) {
delete hub[key]
}
}
}, 1e4)
export class Paper { export class Paper {
constructor(width, height) { constructor(width, height) {
@ -674,9 +644,6 @@ export class Paper {
dom = width dom = width
} }
if (dom) { if (dom) {
if (dom.snap in hub) {
return hub[dom.snap]
}
let doc = dom.ownerDocument let doc = dom.ownerDocument
res = new SnapElement(dom) res = new SnapElement(dom)
desc = dom.querySelector('desc') desc = dom.querySelector('desc')
@ -693,8 +660,7 @@ export class Paper {
extend(res, Paper.prototype) extend(res, Paper.prototype)
res.paper = res.root = res res.paper = res.root = res
} else { } else {
res = make('svg', doc.body) res = make('svg', doc.body, {
h(res.node, {
width, width,
height, height,
version: 1.1, version: 1.1,
@ -704,48 +670,8 @@ export class Paper {
return res return res
} }
/*\
**
* Creates a nested SVG element.
- x (number) @optional X of the element
- y (number) @optional Y of the element
- width (number) @optional width of the element
- height (number) @optional height of the element
- vbx (number) @optional viewbox X
- vby (number) @optional viewbox Y
- vbw (number) @optional viewbox width
- vbh (number) @optional viewbox height
**
= (object) the `svg` element
**
\*/
svg(x, y, width, height, vbx, vby, vbw, vbh) {
let attrs = {}
if (is(x, 'object') && y == null) {
attrs = x
} else {
if (x != null) {
attrs.x = x
}
if (y != null) {
attrs.y = y
}
if (width != null) {
attrs.width = width
}
if (height != null) {
attrs.height = height
}
if (vbx != null && vby != null && vbw != null && vbh != null) {
attrs.viewBox = [vbx, vby, vbw, vbh]
}
}
return this.el('svg', attrs)
}
mask(first) { mask(first) {
let attr, let el = this.el('mask')
el = this.el('mask')
if (arguments.length == 1 && first && !first.type) { if (arguments.length == 1 && first && !first.type) {
el.attr(first) el.attr(first)
} else if (arguments.length) { } else if (arguments.length) {
@ -754,21 +680,20 @@ export class Paper {
return el return el
} }
/*\ /***
** * Equivalent in behaviour to @Paper.g, except its a pattern.
* Equivalent in behaviour to @Paper.g, except its a pattern. - x (number) @optional X of the element
- x (number) @optional X of the element - y (number) @optional Y of the element
- y (number) @optional Y of the element - width (number) @optional width of the element
- width (number) @optional width of the element - height (number) @optional height of the element
- height (number) @optional height of the element - vbx (number) @optional viewbox X
- vbx (number) @optional viewbox X - vby (number) @optional viewbox Y
- vby (number) @optional viewbox Y - vbw (number) @optional viewbox width
- vbw (number) @optional viewbox width - vbh (number) @optional viewbox height
- vbh (number) @optional viewbox height **
** = (object) the `pattern` element
= (object) the `pattern` element **
** */
\*/
ptrn(x, y, width, height, vx, vy, vw, vh) { ptrn(x, y, width, height, vx, vy, vw, vh) {
if (is(x, 'object')) { if (is(x, 'object')) {
let attr = x let attr = x
@ -794,31 +719,27 @@ export class Paper {
} }
return this.el('pattern', attr) return this.el('pattern', attr)
} }
/*\ /*
** **
* Creates a <use> element. * Creates a <use> element.
- id (string) @optional id of element to link - id (string) @optional id of element to link
* or * or
- id (SnapElement) @optional element to link - id (SnapElement) @optional element to link
** **
= (object) the `use` element = (object) the `use` element
** **
\*/ */
use(id) { use(id) {
if (id != null) { if (id instanceof SnapElement) {
if (id instanceof SnapElement) { if (!id.attr('id')) {
if (!id.attr('id')) { id.attr({ id: uuid(id.type + 'S') })
id.attr({ id: uuid(id.type + 'S') })
}
id = id.attr('id')
} }
if (String(id).charAt() == '#') { id = id.attr('id')
id = id.substring(1)
}
return this.el('use', { 'xlink:href': '#' + id })
} else {
return SnapElement.prototype.use.call(this)
} }
if (id.charAt() == '#') {
id = id.slice(1)
}
return this.el('use', { 'xlink:href': '#' + id })
} }
/*\ /*\
** **
@ -838,40 +759,38 @@ export class Paper {
return this.el('symbol', attr) return this.el('symbol', attr)
} }
/*\ /***
** * Draws a text string
* Draws a text string **
** - x (number) x coordinate position
- x (number) x coordinate position - y (number) y coordinate position
- y (number) y coordinate position - text (string|array) The text string to draw or array of strings to nest within separate `<tspan>` elements
- text (string|array) The text string to draw or array of strings to nest within separate `<tspan>` elements = (object) the `text` element
= (object) the `text` element **
** > Usage
> Usage let t1 = paper.text(50, 50, "Snap");
| let t1 = paper.text(50, 50, "Snap"); let t2 = paper.text(50, 50, ["S","n","a","p"]);
| let t2 = paper.text(50, 50, ["S","n","a","p"]); // Text path usage
| // Text path usage t1.attr({textpath: "M10,10L100,100"});
| t1.attr({textpath: "M10,10L100,100"}); // or
| // or let pth = paper.path("M10,10L100,100");
| let pth = paper.path("M10,10L100,100"); t1.attr({textpath: pth});
| t1.attr({textpath: pth}); */
\*/
text(x = 0, y = 0, text = '') { text(x = 0, y = 0, text = '') {
return this.el('text', { x, y }, text) return this.el('text', { x, y }, text)
} }
/*\ /***
** * Draws a line
* Draws a line **
** - x1 (number) x coordinate position of the start
- x1 (number) x coordinate position of the start - y1 (number) y coordinate position of the start
- y1 (number) y coordinate position of the start - x2 (number) x coordinate position of the end
- x2 (number) x coordinate position of the end - y2 (number) y coordinate position of the end
- y2 (number) y coordinate position of the end = (object) the `line` element
= (object) the `line` element **
** > Usage
> Usage let t1 = paper.line(50, 50, 100, 100);
| let t1 = paper.line(50, 50, 100, 100); */
\*/
line(x1, y1, x2, y2) { line(x1, y1, x2, y2) {
let attr = {} let attr = {}
if (is(x1, 'object')) { if (is(x1, 'object')) {
@ -1108,7 +1027,7 @@ export class Paper {
if (arguments.length == 1 && first && !first.type) { if (arguments.length == 1 && first && !first.type) {
el.attr(first) el.attr(first)
} else if (arguments.length) { } else if (arguments.length) {
el.add(Array.from(arguments)) el.add(...Array.from(arguments))
} }
return el return el
} }
@ -1179,9 +1098,6 @@ export class Paper {
export class SnapElement { export class SnapElement {
constructor(el) { constructor(el) {
if (el.snap in hub) {
return hub[el.snap]
}
let svg let svg
try { try {
svg = el.ownerSVGElement svg = el.ownerSVGElement
@ -1210,7 +1126,7 @@ export class SnapElement {
transform: [] transform: []
} }
el.snap = id el.snap = id
hub[id] = this
if (this.type == 'g') { if (this.type == 'g') {
this.add = add2group this.add = add2group
} }

View File

@ -117,6 +117,8 @@ export function h(el, props = null, children) {
return el return el
} }
window.h = h
export function clone(obj) { export function clone(obj) {
if (typeof obj == 'function' || Object(obj) !== obj) { if (typeof obj == 'function' || Object(obj) !== obj) {
return obj return obj