224 lines
5.3 KiB
JavaScript
224 lines
5.3 KiB
JavaScript
// 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
|
|
}
|
|
}
|
|
})
|