kute.js/src/components/svgTransform.js
thednp 933d61de19 Changes:
* added ESLint and updated all code base 
* updated SVGPathCommander, CubicBezier, shorter-js, minifill
* updated polyfills
* minor CSS fixes
2021-03-30 09:23:29 +00:00

176 lines
5.4 KiB
JavaScript

import numbers from '../interpolation/numbers.js';
import { svgTransformOnStart } from './svgTransformBase.js';
/* const svgTransform = {
property: 'svgTransform',
subProperties,
defaultValue,
Interpolate: {numbers},
functions
} */
// Component Util
function parseStringOrigin(origin, { x, width }) {
let result;
if (/[a-z]/i.test(origin) && !/px/.test(origin)) {
result = origin.replace(/top|left/, 0)
.replace(/right|bottom/, 100)
.replace(/center|middle/, 50);
} else {
result = /%/.test(origin) ? (x + (parseFloat(origin) * width) / 100) : parseFloat(origin);
}
return result;
}
// helper function that turns transform value from string to object
function parseTransformString(a) {
const c = {};
const d = a && /\)/.test(a)
? a.substring(0, a.length - 1).split(/\)\s|\)/)
: 'none';
if (d instanceof Array) {
for (let j = 0, jl = d.length; j < jl; j += 1) {
const [prop, val] = d[j].trim().split('(');
c[prop] = val;
}
}
return c;
}
function parseTransformSVG(p, v) {
const svgTransformObject = {};
// by default the transformOrigin is "50% 50%" of the shape box
const bb = this.element.getBBox();
const cx = bb.x + bb.width / 2;
const cy = bb.y + bb.height / 2;
let origin = this._transformOrigin;
let translation;
if (typeof (origin) !== 'undefined') {
origin = origin instanceof Array ? origin : origin.split(/\s/);
} else {
origin = [cx, cy];
}
origin[0] = typeof origin[0] === 'number' ? origin[0] : parseStringOrigin(origin[0], bb);
origin[1] = typeof origin[1] === 'number' ? origin[1] : parseStringOrigin(origin[1], bb);
svgTransformObject.origin = origin;
// populate the valuesStart and / or valuesEnd
Object.keys(v).forEach((i) => {
if (i === 'rotate') {
if (typeof v[i] === 'number') {
svgTransformObject[i] = v[i];
} else if (v[i] instanceof Array) {
[svgTransformObject[i]] = v[i];
} else {
svgTransformObject[i] = v[i].split(/\s/)[0] * 1;
}
} else if (i === 'translate') {
if (v[i] instanceof Array) {
translation = v[i];
} else if (/,|\s/.test(v[i])) {
translation = v[i].split(',');
} else {
translation = [v[i], 0];
}
svgTransformObject[i] = [translation[0] * 1 || 0, translation[1] * 1 || 0];
} else if (/skew/.test(i)) {
svgTransformObject[i] = v[i] * 1 || 0;
} else if (i === 'scale') {
svgTransformObject[i] = parseFloat(v[i]) || 1;
}
});
return svgTransformObject;
}
// Component Functions
function prepareSvgTransform(p, v) {
return parseTransformSVG.call(this, p, v);
}
// returns an obect with current transform attribute value
function getStartSvgTransform(tweenProp, value) {
const transformObject = {};
const currentTransform = parseTransformString(this.element.getAttribute('transform'));
// find a value in current attribute value or add a default value
Object.keys(value).forEach((j) => {
const scaleValue = j === 'scale' ? 1 : 0;
transformObject[j] = j in currentTransform ? currentTransform[j] : scaleValue;
});
return transformObject;
}
function svgTransformCrossCheck(prop) {
if (!this._resetStart) return; // fix since 1.6.1 for fromTo() method
if (this.valuesEnd[prop]) {
const valuesStart = this.valuesStart[prop];
const valuesEnd = this.valuesEnd[prop];
const currentTransform = parseTransformSVG.call(this, prop,
parseTransformString(this.element.getAttribute('transform')));
// populate the valuesStart first
Object.keys(currentTransform).forEach((tp) => {
valuesStart[tp] = currentTransform[tp];
});
// now try to determine the REAL translation
const parentSVG = this.element.ownerSVGElement;
const startMatrix = parentSVG.createSVGTransformFromMatrix(
parentSVG.createSVGMatrix()
.translate(-valuesStart.origin[0], -valuesStart.origin[1]) // - origin
.translate('translate' in valuesStart // the current translate
? valuesStart.translate[0] : 0, 'translate' in valuesStart ? valuesStart.translate[1]
: 0)
.rotate(valuesStart.rotate || 0)
.skewX(valuesStart.skewX || 0)
.skewY(valuesStart.skewY || 0)
.scale(valuesStart.scale || 1)// the other functions
.translate(+valuesStart.origin[0], +valuesStart.origin[1]), // + origin
);
// finally the translate we're looking for
valuesStart.translate = [startMatrix.matrix.e, startMatrix.matrix.f];
// copy existing and unused properties to the valuesEnd
Object.keys(valuesStart).forEach((s) => {
if (!(s in valuesEnd) || s === 'origin') {
valuesEnd[s] = valuesStart[s];
}
});
}
}
// All Component Functions
export const svgTransformFunctions = {
prepareStart: getStartSvgTransform,
prepareProperty: prepareSvgTransform,
onStart: svgTransformOnStart,
crossCheck: svgTransformCrossCheck,
};
// Component Full
export const svgTransform = {
component: 'svgTransformProperty',
property: 'svgTransform',
// subProperties: ['translate','rotate','skewX','skewY','scale'],
defaultOptions: { transformOrigin: '50% 50%' },
defaultValue: {
translate: 0, rotate: 0, skewX: 0, skewY: 0, scale: 1,
},
Interpolate: { numbers },
functions: svgTransformFunctions,
// export utils to globals for faster execution
Util: { parseStringOrigin, parseTransformString, parseTransformSVG },
};
export default svgTransform;