UNPKG

es6tween-plugin-render

Version:

Rendering plugin for es6-tween

441 lines (404 loc) 18 kB
/*! * @name CSS Renderer Plugin * @description CSS Rendering with full-power of JavaScript, no fail... * @license MIT-License * @requires: es6-tween core files for running this plugin */ (function (factory) { "use strict"; if (typeof define === "function" && define.amd) { define(['es6-tween'], factory); } else if (typeof module !== "undefined" && module.exports && !!require('es6-tween')) { module.exports = factory(require('es6-tween')); } else if (typeof exports !== "undefined" && exports["TWEEN"]) { factory(exports["TWEEN"]); } else if (typeof window !== "undefined" && window["TWEEN"]) { factory(window["TWEEN"]); } else if (this["TWEEN"]) { factory(this["TWEEN"]); } } (function (TWEEN) { "use strict"; // Some variables to be working correctly // Get prefix var doc = window.document; if (typeof doc === 'undefined') { return false; } var HYPEN_PREFIX = null; var Prefixes = ["Webkit", "Moz", "Ms", "ms", "O"]; var Property = "Transform"; var _isSetPropertySupported = false; var el, s; if (!doc || !doc.createElement) { HYPEN_PREFIX = 'Webkit'; // It should be Webkit/V8 as it's Node.js } else { el = document.createElement('div'); s = el.style; _isSetPropertySupported = ('setProperty' in s) && typeof s.setProperty === 'function'; if (Property in s) { HYPEN_PREFIX = ''; // Modern prefix-free browsers } else { for (var i = 0, len = Prefixes.length; i < len; i++) { var pref = Prefixes[i]; if ((pref + Property) in s) { HYPEN_PREFIX = pref; break; } } } } var CSS_PREFIX = HYPEN_PREFIX ? "-" + HYPEN_PREFIX.toLowerCase() + "-" : ''; // Prefix var _prefix = function (property) { var propPrefixed = String(HYPEN_PREFIX + property[0].toUpperCase() + property.substr(1)); return propPrefixed in s ? propPrefixed : property; }; // Check SVG Elem var hasSVGSupport = window.SVGElement; var isSVGElement = function (node) { return hasSVGSupport && node instanceof SVGElement; }; // Check 3D support for CSS3 Transform var IS3D = _prefix('perspective') in s; // Performance Optimization var GlobalRoundProps = { left: true, top: true, right: true, bottom: true }; var TransformProps = { x: true, y: true, z: true, translate: true, translate3d: true, scale: true, scaleX: true, scaleY: true, scaleZ: true, scale3d: true, rotateX: true, rotateY: true, rotateZ: true, rotate: true, skew: true, skewX: true, skewY: true, transformPerspective: true }; var FilterProps = { grayscale: 1, brightness: 1, sepia: 1, invert: 1, saturate: 1, contrast: 1, blur: 1, 'hue-rotate': 1, 'drop-shadow': 1 }; var ExceptedProperty = { transformOrder: true, clearProps: true, roundProps: true, decimalProps: true, transformOrigin: true }; var Plugins = TWEEN.Plugins; var AttrProperty = { d: true, points: true, x1: true, y1: true, x2: true, y2: true, r: true, rx: true, ry: true, cx: true, cy: true, stopColor: true }; var ScrollProperty = { scrollTop: true, scrollLeft: true }; var StaticProperty = { display: true, visibility: true, cssFloat: true, backfaceVisibility: true, transformStyle: true }; var defaultTransformOrder = ["transformPerspective", "x", "y", "z", "scaleX", "scaleY", "scaleY", "scale", "rotateX", "rotateY", "rotateZ", "rotate", "skewX", "skewY", "skew"]; var transformProp = _prefix('transform'); var filterProp = _prefix('filter'); var CSSPlugin = { init: function CSSPlugin(CurrentObject, Start, End) { var Tween = this; var node = Tween.node; if (!node) { return false; } this.node = node; this._style = node.style; var transformOrder = End.transformOrder || defaultTransformOrder; var clearProps = End.clearProps; this.roundProps = End.roundProps; var transformOrigin = End.transformOrigin, isSVGNode = isSVGElement(node), is3DNode = IS3D && !isSVGNode, orderLen = transformOrder.length, obj = Tween.object; if (transformOrder.length < defaultTransformOrder.length) { transformOrder = defaultTransformOrder.reduce(function (p, c) { if (p.indexOf(c) === -1) { p.push(c); } return p; }, transformOrder); } this.transformOrder = transformOrder; var transformOriginFunc; var bbox, originTweenX = 0, originTweenY = 0, setTransformDOM = false; var pxsfx = isSVGNode ? 0 : 'px'; var degsfx = isSVGNode ? 0 : 'deg'; var smoothOriginPrepend = '', smoothOriginAppend = ''; var _style = node.style; if (!transformOrigin && isSVGNode) { transformOrigin = "0% 0%"; } if (transformOrigin) { if (isSVGNode) { transformOriginFunc = function (origin, i) { if (origin.indexOf("px") !== -1) { return bbox[i === 0 ? "x" : "y"] + parseFloat(origin); } else if (origin.indexOf("%") !== -1) { return bbox[i === 0 ? "x" : "y"] + (bbox[i === 0 ? "width" : "height"] * (parseFloat(origin) / 100)) } return parseFloat(origin); }; bbox = node.getBBox(); transformOrigin = transformOrigin.split(" ").map(transformOriginFunc); originTweenX = transformOrigin[0]; originTweenY = transformOrigin[1]; smoothOriginPrepend = 'translate(' + originTweenX + ',' + originTweenY + ') '; smoothOriginAppend = 'translate(' + -originTweenX + ',' + -originTweenY + ') '; } else { transformOriginFunc = function (origin, i) { if (origin.indexOf("%") !== -1) { return (node[i === 0 ? "offsetWidth" : "offsetHeight"] * (parseFloat(origin) / 100)); } return parseFloat(origin); }; var orig = transformOrigin.split(" ").map(transformOriginFunc); node.style.transformOrigin = transformOrigin; originTweenX = orig[0]; originTweenY = orig[1]; if (is3DNode) { smoothOriginPrepend = 'translate3d(' + originTweenX + pxsfx + ',' + originTweenY + pxsfx + ', 0px) '; } else { smoothOriginPrepend = 'translate(' + originTweenX + pxsfx + ',' + originTweenY + pxsfx + ') '; } } this.transformOrigin = transformOrigin; this.transformOriginFunc = transformOriginFunc; } this.is3DNode = is3DNode; this.isSVGNode = isSVGNode; this.pxsfx = pxsfx; this.degsfx = degsfx; this.setTransformDOM = setTransformDOM; this.smoothOriginPrepend = smoothOriginPrepend; this.smoothOriginAppend = smoothOriginAppend; this.clearProps = clearProps; for (var prop in obj) { var prefProp = _prefix(prop); if (prop !== prefProp) { var vs = Start[prop], ve = End[prop], vb = obj[prop]; Start[prop] = null; obj[prop] = null; Start[prefProp] = vs; obj[prefProp] = vb; delete Start[prop]; delete obj[prop]; if (prop in End) { End[prefProp] = ve; End[prop] = null; delete End[prop]; } } } for (var prop in StaticProperty) { if (!(prop in node.style)) { continue } if (Start[prop] !== undefined) { node.style[_prefix(prop)] = Start[prop]; Start[prop] = null; delete Start[prop]; } if (End[prop] !== undefined) { node.style[_prefix(prop)] = End[prop]; End[prop] = null; delete End[prop]; } node.style[_prefix('transformOrigin')] = transformOrigin; } return this; }, setOrigin: function (origin) { var transformOriginFunc = this.transformOriginFunc; if (isSVGNode) { var transformOrigin = this.transformOrigin.split(" "); var oldX = transformOrigin[0]; var oldY = transformOrigin[1]; var orig = origin.split(" ").map(transformOriginFunc); var newX = orig[0]; var newY = orig[1]; var diffX = newX - oldX; var diffY = newY - oldY; originTweenX = newX; originTweenY = newY; transformOrigin[0] += diffX; transformOrigin[1] += diffY; var xOrig = transformOrigin[0], yOrig = transformOrigin[1]; originTweenX += Math.abs(xOrig - oldX); originTweenY += Math.abs(yOrig - oldY); smoothOriginPrepend = 'translate(' + originTweenX + ',' + originTweenY + ')'; smoothOriginAppend = 'translate(' + -xOrig + ',' + -yOrig + ')'; } else { var orig = origin.split(" ").map(transformOriginFunc); originTweenX += orig[0]; originTweenY += orig[1]; transformOrigin = origin; setTransformDOM = false; if (is3DNode) { smoothOriginPrepend = 'translate3d( ' + originTweenX + pxsfx + ',' + originTweenY + pxsfx + ',0px)'; } else { smoothOriginPrepend = 'translate(' + originTweenX + pxsfx + ',' + originTweenY + pxsfx + ')'; } this.smoothOriginPrepend = smoothOriginPrepend; this.smoothOriginAppend = smoothOriginAppend; } return this; }, translateDecimal: 10, rotateDecimal: 100, scaleDecimal: 1000, defPx: '0px', def: function (v, u, d) { return !v ? d : typeof v === 'number' ? v + u : v; }, update: function (style, t) { var roundProps = this.roundProps; var clearProps = this.clearProps; var node = this.node; var _style = this._style; var transformOrder = this.transformOrder; var is3DNode = this.is3DNode; var isSVGNode = this.isSVGNode; var setTransformDOM = this.setTransformDOM; var pxsfx = this.pxsfx; var degsfx = this.degsfx; var smoothOriginPrepend = this.smoothOriginPrepend; var smoothOriginAppend = this.smoothOriginAppend; var i = 0; var orderLen = transformOrder.length; var transform; var cssFilter; var translateSet; var trd = 10; var rtd = 100; var std = 1000; var defpx = 0 + pxsfx; var def = CSSPlugin.def; for (var p in style) { if (typeof style[p] === 'number') { if (roundProps && roundProps.indexOf(p) !== -1 || GlobalRoundProps[p]) { style[p] = style[p] | 0; } if (p === 'x' || p === 'y' || p === 'z') { style[p] = (((style[p] * trd) | 0) / trd); } else if (p === 'scale' || p === 'scaleX' || p === 'scaleY' || p === 'scaleZ') { style[p] = ((style[p] * std) | 0) / std } else if (p === 'rotate' || p === 'rotateZ') { style[p] = (((style[p] * rtd) | 0) / rtd); } } if (Plugins[p] || TransformProps[p] || ExceptedProperty[p]) { continue; } else if (FilterProps[p]) { cssFilter = cssFilter || ''; cssFilter += p + '(' + style[p] + ') '; } else if (ScrollProperty[p]) { node[p] = style[p]; } else if (AttrProperty[p]) { node.setAttribute(p, style[p]); } else if (p.indexOf('--') === 0 && _isSetPropertySupported) { _style.setProperty(p, style[p]) } else { _style[p] = style[p]; } } for (; i < orderLen; i++) { var p = transformOrder[i]; if (style[p] !== undefined) { transform = transform || ''; if (p === 'x' || p === 'y' || p === 'z') { if (!translateSet) { transform += is3DNode ? 'translate3d(' + def(style.x, pxsfx, defpx) + ',' + def(style.y, pxsfx, defpx) + ',' + def(style.z, pxsfx, defpx) + ') ' : 'translate(' + def(style.x, pxsfx, defpx) + ',' + def(style.y, pxsfx, defpx) + ') '; translateSet = true; } } else if (p === 'scale' || p === 'scaleX' || p === 'scaleY' || p === 'scaleZ') { transform += is3DNode ? 'scale3d(' + (style.scaleX !== undefined ? style.scaleX : style.scale !== undefined ? style.scale : 1) + ',' + (style.scaleY !== undefined ? style.scaleY : style.scale !== undefined ? style.scale : 1) + ',' + (style.scaleZ !== undefined ? style.scaleZ : style.scale !== undefined ? style.scale : 1) + ') ' : 'scale(' + (style.scaleX !== undefined ? style.scaleX : style.scale !== undefined ? style.scale : 1) + ',' + (style.scaleY !== undefined ? style.scaleY : style.scale !== undefined ? style.scale : 1) + ') '; } else if (p === 'transformPerspective') { transform += 'perspective(' + style[p] + ') '; } else if (p === 'rotate' || p === 'rotateZ') { var rotateValue = style[p]; if (typeof rotateValue === 'number') { rotateValue += degsfx; } transform += p + '(' + rotateValue + ') '; } else { transform += p + '(' + style[p] + ') '; } } } if (transform) { if (isSVGNode) { node.setAttribute('transform', smoothOriginPrepend + transform + smoothOriginAppend); } else { _style[transformProp] = smoothOriginPrepend + transform; } transform = null; } if (cssFilter) { _style[filterProp] = cssFilter; cssFilter = null; } if (t === 1 && clearProps) { for (var i = 0, len = clearProps.length; i < len; i++) { var p = clearProps[i]; if (isSVGNode && node.getAttribute(p)) { node.removeAttribute(p); } else { _style[p] = ''; } } } } } TWEEN.Tween.Renderer = CSSPlugin; }));