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)
}
// 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.
/*\
* SnapElement.use
[ method ]
**
* Creates a `<use>` element linked to the current element
**
= (SnapElement) the `<use>` element
\*/
/***
* Creates a `<use>` element linked to the current element
**
= (SnapElement) the `<use>` element
*/
elproto.use = function () {
let use,
id = this.node.id
let id = this.node.id
let attr, use
if (!id) {
id = this.id
$(this.node, {
id: id
})
this.node.id = id
}
attr = { 'xlink:href': '#' + id }
if (
this.type == 'linearGradient' ||
this.type == 'radialGradient' ||
this.type == 'pattern'
) {
use = make(this.type, this.node.parentNode)
use = make(this.type, this.node.parentNode, attr)
} else {
use = make('use', this.node.parentNode)
use = make('use', this.node.parentNode, attr)
}
$(use.node, {
'xlink:href': '#' + id
})
use.original = this
return use
}
function fixids(el) {
let els = el.selectAll('*'),
it,
@ -561,9 +556,7 @@ function fixids(el) {
\*/
elproto.clone = function () {
let clone = wrap(this.node.cloneNode(true))
if ($(clone.node, 'id')) {
$(clone.node, { id: clone.id })
}
fixids(clone)
clone.insertAfter(this)
return clone

View File

@ -6,7 +6,7 @@
import eve from './eve.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'
let proto = Paper.prototype
@ -28,20 +28,19 @@ let proto = Paper.prototype
* offset (number) stops offset 0..100
*/
function GaddStop(color, offset) {
let stop = $('stop'),
attr = {
offset: +offset + '%'
}
let attr = {
offset: +offset + '%'
}
color = parseColor(color)
attr['stop-color'] = color.hex
if (color.opacity < 1) {
attr['stop-opacity'] = color.opacity
}
$(stop, attr)
let stop = h('stop', attr)
let stops = this.stops(),
inserted
for (let i = 0; i < stops.length; i++) {
let stopOffset = parseFloat(stops[i].attr('offset'))
let stopOffset = +stops[i].attr('offset')
if (stopOffset > offset) {
this.node.insertBefore(stop, stops[i].node)
inserted = true

View File

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

View File

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