删除一大堆扩展

master
yutent 2024-03-14 18:16:20 +08:00
parent 78a90d987a
commit 95c922f7ea
6 changed files with 0 additions and 1186 deletions

View File

@ -1,212 +0,0 @@
/**
* {}
* @author yutent<yutent.io@gmail.com>
* @date 2024/03/07 15:46:18
*/
import eve from './eve.js'
import { SnapElement } from './svg.js'
import mina from './mina.js'
import { is } from './utils.js'
let elproto = SnapElement.prototype,
Str = String,
has = 'hasOwnProperty'
function slice(from, to, f) {
return function (arr) {
let res = arr.slice(from, to)
if (res.length == 1) {
res = res[0]
}
return f ? f(res) : res
}
}
export class Animation {
constructor(attr, ms, easing, callback) {
if (typeof easing === 'function' && !easing.length) {
callback = easing
easing = mina.linear
}
this.attr = attr
this.dur = ms
easing && (this.easing = easing)
callback && (this.callback = callback)
}
}
/**
* Creates an animation object
**
* attr (object) attributes of final destination
* duration (number) duration of the animation, in milliseconds
* easing (function) #optional one of easing functions of @mina or custom one
* callback (function) #optional callback function that fires when animation ends
*/
export function createAnimation(attr, ms, easing, callback) {
return new Animation(attr, ms, easing, callback)
}
/**
* Returns a set of animations that may be able to manipulate the current element
**
= (object) in format:
{
anim (object) animation object,
mina (object) @mina object,
curStatus (number) 0..1 status of the animation: 0 just started, 1 just finished,
status (function) gets or sets the status of the animation,
stop (function) stops the animation
}
*/
elproto.inAnim = function () {
let el = this
let res = []
for (let id in el.anims) {
if (el.anims.hasOwnProperty(id)) {
let a = el.anims[id]
res.push({
anim: new Animation(a._attrs, a.dur, a.easing, a._callback),
mina: a,
curStatus: a.status(),
status(val) {
return a.status(val)
},
stop() {
a.stop()
}
})
}
}
return res
}
/**
* Runs generic animation of one number into another with a caring function
**
- from (number|array) number or array of numbers
- to (number|array) number or array of numbers
- setter (function) caring function that accepts one number argument
- duration (number) duration, in milliseconds
- easing (function) #optional easing function from @mina or custom
- callback (function) #optional callback function to execute when animation ends
= (object) animation object in @mina format
{
id (string) animation id, consider it read-only,
duration (function) gets or sets the duration of the animation,
easing (function) easing,
speed (function) gets or sets the speed of the animation,
status (function) gets or sets the status of the animation,
stop (function) stops the animation
}
let rect = new Snap().rect(0, 0, 10, 10);
animate(0, 10, function (val) {
rect.attr({
x: val
});
}, 1000);
// in given context is equivalent to
rect.animate({x: 10}, 1000);
*/
export function animate(from, to, setter, ms, easing, callback) {
if (typeof easing == 'function' && !easing.length) {
callback = easing
easing = mina.linear
}
let now = mina.time(),
anim = mina(from, to, now, now + ms, mina.time, setter, easing)
callback && eve.once('mina.finish.' + anim.id, callback)
return anim
}
/*\
* SnapElement.stop
[ method ]
**
* Stops all the animations for the current element
**
= (SnapElement) the current element
\*/
elproto.stop = function () {
let anims = this.inAnim()
for (let i = 0, ii = anims.length; i < ii; i++) {
anims[i].stop()
}
return this
}
/*\
* SnapElement.animate
[ method ]
**
* Animates the given attributes of the element
**
- attrs (object) key-value pairs of destination attributes
- duration (number) duration of the animation in milliseconds
- easing (function) #optional easing function from @mina or custom
- callback (function) #optional callback function that executes when the animation ends
= (SnapElement) the current element
\*/
elproto.animate = function (attrs, ms, easing, callback) {
if (typeof easing == 'function' && !easing.length) {
callback = easing
easing = mina.linear
}
if (attrs instanceof Animation) {
callback = attrs.callback
easing = attrs.easing
ms = attrs.dur
attrs = attrs.attr
}
let fkeys = [],
tkeys = [],
keys = {},
from,
to,
f,
eq,
el = this
for (let key in attrs)
if (attrs[has](key)) {
if (el.equal) {
eq = el.equal(key, Str(attrs[key]))
from = eq.from
to = eq.to
f = eq.f
} else {
from = +el.attr(key)
to = +attrs[key]
}
let len = is(from, 'array') ? from.length : 1
keys[key] = slice(fkeys.length, fkeys.length + len, f)
fkeys = fkeys.concat(from)
tkeys = tkeys.concat(to)
}
let now = mina.time(),
anim = mina(
fkeys,
tkeys,
now,
now + ms,
mina.time,
function (val) {
let attr = {}
for (let key in keys)
if (keys[has](key)) {
attr[key] = keys[key](val)
}
el.attr(attr)
},
easing
)
el.anims[anim.id] = anim
anim._attrs = attrs
anim._callback = callback
eve('snap.animcreated.' + el.id, anim)
eve.once('mina.finish.' + anim.id, function () {
eve.off('mina.*.' + anim.id)
delete el.anims[anim.id]
callback && callback.call(el)
})
eve.once('mina.stop.' + anim.id, function () {
eve.off('mina.*.' + anim.id)
delete el.anims[anim.id]
})
return el
}

View File

@ -1,80 +0,0 @@
/**
* {}
* @author yutent<yutent.io@gmail.com>
* @date 2024/03/07 15:17:00
*/
import eve from './eve.js'
let operators = {
'+': function (x, y) {
return x + y
},
'-': function (x, y) {
return x - y
},
'/': function (x, y) {
return x / y
},
'*': function (x, y) {
return x * y
}
},
reUnit = /[a-z]+$/i,
reAddon = /^\s*([+\-\/*])\s*=\s*([\d.eE+\-]+)\s*([^\d\s]+)?\s*$/
function getUnit(unit) {
return function (val) {
return +val.toFixed(3) + unit
}
}
eve.on('snap.util.attr', function (val) {
let plus = String(val).match(reAddon)
if (plus) {
let evnt = eve.nt(),
name = evnt.substring(evnt.lastIndexOf('.') + 1),
a = this.attr(name),
atr = {}
eve.stop()
let unit = plus[3] || '',
aUnit = a.match(reUnit),
op = operators[plus[1]]
if (aUnit && aUnit == unit) {
val = op(+a, +plus[2])
} else {
a = this.asPX(name)
val = op(this.asPX(name), this.asPX(name, plus[2] + unit))
}
if (isNaN(a) || isNaN(val)) {
return
}
atr[name] = val
this.attr(atr)
}
})(-10)
eve.on('snap.util.equal', function (name, b) {
let a = String(this.attr(name) || '')
let bplus = String(b).match(reAddon)
if (bplus) {
eve.stop()
let unit = bplus[3] || '',
aUnit = a.match(reUnit),
op = operators[bplus[1]]
if (aUnit && aUnit === unit) {
return {
from: +a,
to: op(+a, +bplus[2]),
f: getUnit(aUnit)
}
} else {
a = this.asPX(name)
return {
from: a,
to: op(a, this.asPX(name, bplus[2] + unit)),
f: _ => _
}
}
}
})(-10)

View File

@ -1,223 +0,0 @@
// Copyright (c) 2013 Adobe Systems Incorporated. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import eve from './eve.js'
import { Snap } from './svg.js'
import { is } from './utils.js'
import { SEPARATOR } from './lib/constants.js'
import { parseColor } from './lib/color.js'
import { Matrix } from './matrix.js'
let names = {},
reUnit = /[%a-z]+$/i,
Str = String
names.stroke = names.fill = 'colour'
function getEmpty(item) {
let l = item[0]
switch (l.toLowerCase()) {
case 't':
return [l, 0, 0]
case 'm':
return [l, 1, 0, 0, 1, 0, 0]
case 'r':
if (item.length == 4) {
return [l, 0, item[2], item[3]]
} else {
return [l, 0]
}
case 's':
if (item.length == 5) {
return [l, 1, 1, item[3], item[4]]
} else if (item.length == 3) {
return [l, 1, 1]
} else {
return [l, 1]
}
}
}
function equaliseTransform(t1, t2, getBBox) {
t1 = t1 || new Matrix()
t2 = t2 || new Matrix()
t1 = Snap.parseTransformString(t1.toTransformString()) || []
t2 = Snap.parseTransformString(t2.toTransformString()) || []
let maxlength = Math.max(t1.length, t2.length),
from = [],
to = [],
i = 0,
j,
jj,
tt1,
tt2
for (; i < maxlength; i++) {
tt1 = t1[i] || getEmpty(t2[i])
tt2 = t2[i] || getEmpty(tt1)
if (
tt1[0] != tt2[0] ||
(tt1[0].toLowerCase() == 'r' && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||
(tt1[0].toLowerCase() == 's' && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))
) {
t1 = Snap._.transform2matrix(t1, getBBox())
t2 = Snap._.transform2matrix(t2, getBBox())
from = [['m', t1.a, t1.b, t1.c, t1.d, t1.e, t1.f]]
to = [['m', t2.a, t2.b, t2.c, t2.d, t2.e, t2.f]]
break
}
from[i] = []
to[i] = []
for (j = 0, jj = Math.max(tt1.length, tt2.length); j < jj; j++) {
j in tt1 && (from[i][j] = tt1[j])
j in tt2 && (to[i][j] = tt2[j])
}
}
return {
from: path2array(from),
to: path2array(to),
f: getPath(from)
}
}
function getNumber(val) {
return val
}
function getUnit(unit) {
return function (val) {
return +val.toFixed(3) + unit
}
}
function getViewBox(val) {
return val.join(' ')
}
function getColour(clr) {
return Snap.rgb(clr[0], clr[1], clr[2], clr[3])
}
function getPath(path) {
let k = 0,
i,
ii,
j,
jj,
out,
a,
b = []
for (i = 0, ii = path.length; i < ii; i++) {
out = '['
a = ['"' + path[i][0] + '"']
for (j = 1, jj = path[i].length; j < jj; j++) {
a[j] = 'val[' + k++ + ']'
}
out += a + ']'
b[i] = out
}
return Function('val', 'return Snap.path.toString.call([' + b + '])')
}
function path2array(path) {
let out = []
for (let i = 0, ii = path.length; i < ii; i++) {
for (let j = 1, jj = path[i].length; j < jj; j++) {
out.push(path[i][j])
}
}
return out
}
function isNumeric(obj) {
return isFinite(obj)
}
function arrayEqual(arr1, arr2) {
if (!is(arr1, 'array') || !is(arr2, 'array')) {
return false
}
return arr1.toString() == arr2.toString()
}
eve.on('snap.util.equal', function (name, b) {
let A,
B,
a = Str(this.attr(name) || ''),
el = this
if (names[name] == 'colour') {
A = parseColor(a)
B = parseColor(b)
return {
from: [A.r, A.g, A.b, A.opacity],
to: [B.r, B.g, B.b, B.opacity],
f: getColour
}
}
if (name == 'viewBox') {
A = this.attr(name).vb.split(' ').map(Number)
B = b.split(' ').map(Number)
return {
from: A,
to: B,
f: getViewBox
}
}
if (
name == 'transform' ||
name == 'gradientTransform' ||
name == 'patternTransform'
) {
if (typeof b == 'string') {
b = Str(b).replace(/\.{3}|\u2026/g, a)
}
a = this.matrix
if (!Snap._.rgTransform.test(b)) {
b = Snap._.transform2matrix(Snap._.svgTransform2string(b), this.getBBox())
} else {
b = Snap._.transform2matrix(b, this.getBBox())
}
return equaliseTransform(a, b, function () {
return el.getBBox(1)
})
}
if (name == 'd' || name == 'path') {
A = Snap.path.toCubic(a, b)
return {
from: path2array(A[0]),
to: path2array(A[1]),
f: getPath(A[0])
}
}
if (name == 'points') {
A = Str(a).split(SEPARATOR)
B = Str(b).split(SEPARATOR)
return {
from: A,
to: B,
f: function (val) {
return val
}
}
}
if (isNumeric(a) && isNumeric(b)) {
return {
from: parseFloat(a),
to: parseFloat(b),
f: getNumber
}
}
let aUnit = a.match(reUnit),
bUnit = Str(b).match(reUnit)
if (aUnit && arrayEqual(aUnit, bUnit)) {
return {
from: parseFloat(a),
to: parseFloat(b),
f: getUnit(aUnit)
}
} else {
return {
from: this.asPX(name),
to: this.asPX(name, b),
f: getNumber
}
}
})

View File

@ -1,13 +1,8 @@
import { Snap } from './svg.js' import { Snap } from './svg.js'
import './paper.js' import './paper.js'
import './element.js' import './element.js'
import { createAnimation, animate } from './animation.js'
import { Matrix } from './matrix.js' import { Matrix } from './matrix.js'
import './attradd.js'
import './path.js' import './path.js'
import './set.js'
import './equal.js'
import './mouse.js'
import './filter.js' import './filter.js'
export default Snap export default Snap
@ -15,5 +10,3 @@ export default Snap
export function createSvg(...args) { export function createSvg(...args) {
return new Snap(...args) return new Snap(...args)
} }
export { Matrix, createAnimation, animate }

View File

@ -1,343 +0,0 @@
/**
* {}
* @author yutent<yutent.io@gmail.com>
* @date 2024/03/08 10:20:25
*/
import eve from './eve.js'
import { uuid } from './utils.js'
let animations = {},
requestAnimFrame =
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame,
requestID,
isArray = Array.isArray,
diff = function (a, b, A, B) {
if (isArray(a)) {
res = []
for (let i = 0, ii = a.length; i < ii; i++) {
res[i] = diff(a[i], b, A[i], B)
}
return res
}
let dif = (A - a) / (B - b)
return function (bb) {
return a + dif * (bb - b)
}
},
timer = Date.now,
sta = function (val) {
let a = this
if (val == null) {
return a.s
}
let ds = a.s - val
a.b += a.dur * ds
a.B += a.dur * ds
a.s = val
},
speed = function (val) {
if (val == null) {
return this.spd
}
this.spd = val
},
duration = function (val) {
if (val == null) {
return this.dur
}
this.s = (this.s * val) / this.dur
this.dur = val
},
stopit = function () {
delete animations[this.id]
this.update()
eve('mina.stop.' + this.id, a)
},
pause = function () {
let a = this
if (a.pdif) {
return
}
delete animations[a.id]
a.update()
a.pdif = a.get() - a.b
},
resume = function () {
let a = this
if (!a.pdif) {
return
}
a.b = a.get() - a.pdif
delete a.pdif
animations[a.id] = a
frame()
},
update = function () {
let a = this,
res
if (isArray(a.start)) {
res = []
for (let j = 0, jj = a.start.length; j < jj; j++) {
res[j] = +a.start[j] + (a.end[j] - a.start[j]) * a.easing(a.s)
}
} else {
res = +a.start + (a.end - a.start) * a.easing(a.s)
}
a.set(res)
},
frame = function (timeStamp) {
// Manual invokation?
if (!timeStamp) {
// Frame loop stopped?
if (!requestID) {
// Start frame loop...
requestID = requestAnimFrame(frame)
}
return
}
let len = 0
for (let i in animations)
if (animations.hasOwnProperty(i)) {
let a = animations[i],
b = a.get(),
res
len++
a.s = (b - a.b) / (a.dur / a.spd)
if (a.s >= 1) {
delete animations[i]
a.s = 1
len--
;(function (a) {
setTimeout(function () {
eve('mina.finish.' + a.id, a)
})
})(a)
}
a.update()
}
requestID = len ? requestAnimFrame(frame) : false
}
/***
* Generic animation of numbers
**
* a (number) start _slave_ number
* A (number) end _slave_ number
* b (number) start _master_ number (start time in general case)
* B (number) end _master_ number (end time in general case)
* get (function) getter of _master_ number (see @mina.time)
* set (function) setter of _slave_ number
* easing (function) #optional easing function, default is @mina.linear
= (object) animation descriptor
{
id (string) animation id,
start (number) start _slave_ number,
end (number) end _slave_ number,
b (number) start _master_ number,
s (number) animation status (0..1),
dur (number) animation duration,
spd (number) animation speed,
get (function) getter of _master_ number (see @mina.time),
set (function) setter of _slave_ number,
easing (function) easing function, default is @mina.linear,
status (function) status getter/setter,
speed (function) speed getter/setter,
duration (function) duration getter/setter,
stop (function) animation stopper
pause (function) pauses the animation
resume (function) resumes the animation
update (function) calles setter with the right value of the animation
}
*/
export const mina = function (a, A, b, B, get, set, easing) {
let anim = {
id: uuid('M'),
start: a,
end: A,
b: b,
s: 0,
dur: B - b,
spd: 1,
get: get,
set: set,
easing: easing || mina.linear,
status: sta,
speed: speed,
duration: duration,
stop: stopit,
pause: pause,
resume: resume,
update: update
}
animations[anim.id] = anim
let len = 0,
i
for (i in animations)
if (animations.hasOwnProperty(i)) {
len++
if (len == 2) {
break
}
}
len == 1 && frame()
return anim
}
/*\
* mina.time
[ method ]
**
* Returns the current time. Equivalent to:
| function () {
| return (new Date).getTime();
| }
\*/
mina.time = timer
/*\
* mina.getById
[ method ]
**
* Returns an animation by its id
- id (string) animation's id
= (object) See @mina
\*/
mina.getById = function (id) {
return animations[id] || null
}
/*\
* mina.linear
[ method ]
**
* Default linear easing
- n (number) input 0..1
= (number) output 0..1
\*/
mina.linear = function (n) {
return n
}
/*\
* mina.easeout
[ method ]
**
* Easeout easing
- n (number) input 0..1
= (number) output 0..1
\*/
mina.easeout = function (n) {
return Math.pow(n, 1.7)
}
/*\
* mina.easein
[ method ]
**
* Easein easing
- n (number) input 0..1
= (number) output 0..1
\*/
mina.easein = function (n) {
return Math.pow(n, 0.48)
}
/*\
* mina.easeinout
[ method ]
**
* Easeinout easing
- n (number) input 0..1
= (number) output 0..1
\*/
mina.easeinout = function (n) {
if (n == 1) {
return 1
}
if (n == 0) {
return 0
}
let q = 0.48 - n / 1.04,
Q = Math.sqrt(0.1734 + q * q),
x = Q - q,
X = Math.pow(Math.abs(x), 1 / 3) * (x < 0 ? -1 : 1),
y = -Q - q,
Y = Math.pow(Math.abs(y), 1 / 3) * (y < 0 ? -1 : 1),
t = X + Y + 0.5
return (1 - t) * 3 * t * t + t * t * t
}
/*\
* mina.backin
[ method ]
**
* Backin easing
- n (number) input 0..1
= (number) output 0..1
\*/
mina.backin = function (n) {
if (n == 1) {
return 1
}
let s = 1.70158
return n * n * ((s + 1) * n - s)
}
/*\
* mina.backout
[ method ]
**
* Backout easing
- n (number) input 0..1
= (number) output 0..1
\*/
mina.backout = function (n) {
if (n == 0) {
return 0
}
n = n - 1
let s = 1.70158
return n * n * ((s + 1) * n + s) + 1
}
/*\
* mina.elastic
[ method ]
**
* Elastic easing
- n (number) input 0..1
= (number) output 0..1
\*/
mina.elastic = function (n) {
if (n == !!n) {
return n
}
return (
Math.pow(2, -10 * n) * Math.sin(((n - 0.075) * (2 * Math.PI)) / 0.3) + 1
)
}
/*\
* mina.bounce
[ method ]
**
* Bounce easing
- n (number) input 0..1
= (number) output 0..1
\*/
mina.bounce = function (n) {
let s = 7.5625,
p = 2.75,
l
if (n < 1 / p) {
l = s * n * n
} else {
if (n < 2 / p) {
n -= 1.5 / p
l = s * n * n + 0.75
} else {
if (n < 2.5 / p) {
n -= 2.25 / p
l = s * n * n + 0.9375
} else {
n -= 2.625 / p
l = s * n * n + 0.984375
}
}
}
return l
}
export default mina

View File

@ -1,321 +0,0 @@
/**
* {}
* @author yutent<yutent.io@gmail.com>
* @date 2024/03/07 15:33:05
*/
import eve from './eve.js'
import { Animation } from './animation.js'
import mina from './mina.js'
import { is } from './utils.js'
let mmax = Math.max,
mmin = Math.min
// Set
let Set = function (items) {
this.items = []
this.bindings = {}
this.length = 0
this.type = 'set'
if (items) {
for (let i = 0, ii = items.length; i < ii; i++) {
if (items[i]) {
this[this.items.length] = this.items[this.items.length] = items[i]
this.length++
}
}
}
},
setproto = Set.prototype
/*\
* Set.push
[ method ]
**
* Adds each argument to the current set
= (object) original element
\*/
setproto.push = function () {
let item, len
for (let i = 0, ii = arguments.length; i < ii; i++) {
item = arguments[i]
if (item) {
len = this.items.length
this[len] = this.items[len] = item
this.length++
}
}
return this
}
/*\
* Set.pop
[ method ]
**
* Removes last element and returns it
= (object) element
\*/
setproto.pop = function () {
this.length && delete this[this.length--]
return this.items.pop()
}
/*\
* Set.forEach
[ method ]
**
* Executes given function for each element in the set
*
* If the function returns `false`, the loop stops running.
**
- callback (function) function to run
- thisArg (object) context object for the callback
= (object) Set object
\*/
setproto.forEach = function (callback, thisArg) {
for (let i = 0, ii = this.items.length; i < ii; i++) {
if (callback.call(thisArg, this.items[i], i) === false) {
return this
}
}
return this
}
/**
* Animates each element in set in sync.
*
**
- attrs (object) key-value pairs of destination attributes
- duration (number) duration of the animation in milliseconds
- easing (function) #optional easing function from @mina or custom
- callback (function) #optional callback function that executes when the animation ends
* or
- animation (array) array of animation parameter for each element in set in format `[attrs, duration, easing, callback]`
> Usage
| // animate all elements in set to radius 10
| set.animate({r: 10}, 500, mina.easein);
| // or
| // animate first element to radius 10, but second to radius 20 and in different time
| set.animate([{r: 10}, 500, mina.easein], [{r: 20}, 1500, mina.easein]);
= (SnapElement) the current element
*/
setproto.animate = function (attrs, ms, easing, callback) {
if (typeof easing == 'function' && !easing.length) {
callback = easing
easing = mina.linear
}
if (attrs instanceof Animation) {
callback = attrs.callback
easing = attrs.easing
ms = easing.dur
attrs = attrs.attr
}
let args = arguments
if (is(attrs, 'array') && is(args[args.length - 1], 'array')) {
let each = true
}
let begin,
handler = function () {
if (begin) {
this.b = begin
} else {
begin = this.b
}
},
cb = 0,
set = this,
callbacker =
callback &&
function () {
if (++cb == set.length) {
callback.call(this)
}
}
return this.forEach(function (el, i) {
eve.once('snap.animcreated.' + el.id, handler)
if (each) {
args[i] && el.animate.apply(el, args[i])
} else {
el.animate(attrs, ms, easing, callbacker)
}
})
}
/**
* Removes all children of the set.
*
*/
setproto.remove = function () {
while (this.length) {
this.pop().remove()
}
return this
}
/**
* Specifies how to handle a specific attribute when applied
* to a set.
*
**
- attr (string) attribute name
- callback (function) function to run
* or
- attr (string) attribute name
- element (SnapElement) specific element in the set to apply the attribute to
* or
- attr (string) attribute name
- element (SnapElement) specific element in the set to apply the attribute to
- eattr (string) attribute on the element to bind the attribute to
= (object) Set object
*/
setproto.bind = function (attr, a, b) {
let data = {}
if (typeof a == 'function') {
this.bindings[attr] = a
} else {
let aname = b || attr
this.bindings[attr] = function (v) {
data[aname] = v
a.attr(data)
}
}
return this
}
/**
* Equivalent of @SnapElement.attr.
*/
setproto.attr = function (value) {
let unbound = {}
for (let k in value) {
if (this.bindings[k]) {
this.bindings[k](value[k])
} else {
unbound[k] = value[k]
}
}
for (let i = 0, ii = this.items.length; i < ii; i++) {
this.items[i].attr(unbound)
}
return this
}
/**
* Removes all elements from the set
*/
setproto.clear = function () {
while (this.length) {
this.pop()
}
}
/**
* Removes range of elements from the set
**
* index (number) position of the deletion
* count (number) number of element to remove
* insertion (object) #optional elements to insert
*/
setproto.splice = function (index, count, insertion) {
index = index < 0 ? mmax(this.length + index, 0) : index
count = mmax(0, mmin(this.length - index, count))
let tail = [],
todel = [],
args = [],
i
for (i = 2; i < arguments.length; i++) {
args.push(arguments[i])
}
for (i = 0; i < count; i++) {
todel.push(this[index + i])
}
for (; i < this.length - index; i++) {
tail.push(this[index + i])
}
let arglen = args.length
for (i = 0; i < arglen + tail.length; i++) {
this.items[index + i] = this[index + i] =
i < arglen ? args[i] : tail[i - arglen]
}
i = this.items.length = this.length -= count - arglen
while (this[i]) {
delete this[i++]
}
return new Set(todel)
}
/**
* Removes given element from the set
**
* element (object) element to remove
*/
setproto.exclude = function (el) {
for (let i = 0, ii = this.length; i < ii; i++)
if (this[i] == el) {
this.splice(i, 1)
return true
}
return false
}
/**
* Inserts set elements after given element.
**
* element (object) set will be inserted after this element
*/
setproto.insertAfter = function (el) {
let i = this.items.length
while (i--) {
this.items[i].insertAfter(el)
}
return this
}
/**
* Union of all bboxes of the set. See @SnapElement.getBBox.
*/
setproto.getBBox = function () {
let x = [],
y = [],
x2 = [],
y2 = []
for (let i = this.items.length; i--; )
if (!this.items[i].removed) {
let box = this.items[i].getBBox()
x.push(box.x)
y.push(box.y)
x2.push(box.x + box.width)
y2.push(box.y + box.height)
}
x = mmin.apply(0, x)
y = mmin.apply(0, y)
x2 = mmax.apply(0, x2)
y2 = mmax.apply(0, y2)
return {
x: x,
y: y,
x2: x2,
y2: y2,
width: x2 - x,
height: y2 - y,
cx: x + (x2 - x) / 2,
cy: y + (y2 - y) / 2
}
}
/**
* Creates a clone of the set.
*/
setproto.clone = function (s) {
s = new Set()
for (let i = 0, ii = this.items.length; i < ii; i++) {
s.push(this.items[i].clone())
}
return s
}
setproto.type = 'set'
/**
* Creates a set and fills it with list of arguments.
**
= (object) New Set object
| let r = paper.rect(0, 0, 10, 10),
| s1 = createSet(), // empty set
| s2 = createSet(r, paper.circle(100, 100, 20)); // prefilled set
*/
export function createSet(...args) {
let set = new Set()
if (args.length) {
set.push.apply(set, args)
}
return set
}