123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- import {
- bmPow,
- bmMax,
- bmMin,
- bmSqrt,
- } from '../../utils/common';
- import {
- extendPrototype,
- } from '../../utils/functionExtensions';
- import createNS from '../../utils/helpers/svg_elements';
- import RenderableElement from '../helpers/RenderableElement';
- import BaseElement from '../BaseElement';
- import TransformElement from '../helpers/TransformElement';
- import HierarchyElement from '../helpers/HierarchyElement';
- import FrameElement from '../helpers/FrameElement';
- import HBaseElement from './HBaseElement';
- import HSolidElement from './HSolidElement';
- import SVGShapeElement from '../svgElements/SVGShapeElement';
- function HShapeElement(data, globalData, comp) {
- // List of drawable elements
- this.shapes = [];
- // Full shape data
- this.shapesData = data.shapes;
- // List of styles that will be applied to shapes
- this.stylesList = [];
- // List of modifiers that will be applied to shapes
- this.shapeModifiers = [];
- // List of items in shape tree
- this.itemsData = [];
- // List of items in previous shape tree
- this.processedElements = [];
- // List of animated components
- this.animatedContents = [];
- this.shapesContainer = createNS('g');
- this.initElement(data, globalData, comp);
- // Moving any property that doesn't get too much access after initialization because of v8 way of handling more than 10 properties.
- // List of elements that have been created
- this.prevViewData = [];
- this.currentBBox = {
- x: 999999,
- y: -999999,
- h: 0,
- w: 0,
- };
- }
- extendPrototype([BaseElement, TransformElement, HSolidElement, SVGShapeElement, HBaseElement, HierarchyElement, FrameElement, RenderableElement], HShapeElement);
- HShapeElement.prototype._renderShapeFrame = HShapeElement.prototype.renderInnerContent;
- HShapeElement.prototype.createContent = function () {
- var cont;
- this.baseElement.style.fontSize = 0;
- if (this.data.hasMask) {
- this.layerElement.appendChild(this.shapesContainer);
- cont = this.svgElement;
- } else {
- cont = createNS('svg');
- var size = this.comp.data ? this.comp.data : this.globalData.compSize;
- cont.setAttribute('width', size.w);
- cont.setAttribute('height', size.h);
- cont.appendChild(this.shapesContainer);
- this.layerElement.appendChild(cont);
- }
- this.searchShapes(this.shapesData, this.itemsData, this.prevViewData, this.shapesContainer, 0, [], true);
- this.filterUniqueShapes();
- this.shapeCont = cont;
- };
- HShapeElement.prototype.getTransformedPoint = function (transformers, point) {
- var i;
- var len = transformers.length;
- for (i = 0; i < len; i += 1) {
- point = transformers[i].mProps.v.applyToPointArray(point[0], point[1], 0);
- }
- return point;
- };
- HShapeElement.prototype.calculateShapeBoundingBox = function (item, boundingBox) {
- var shape = item.sh.v;
- var transformers = item.transformers;
- var i;
- var len = shape._length;
- var vPoint;
- var oPoint;
- var nextIPoint;
- var nextVPoint;
- if (len <= 1) {
- return;
- }
- for (i = 0; i < len - 1; i += 1) {
- vPoint = this.getTransformedPoint(transformers, shape.v[i]);
- oPoint = this.getTransformedPoint(transformers, shape.o[i]);
- nextIPoint = this.getTransformedPoint(transformers, shape.i[i + 1]);
- nextVPoint = this.getTransformedPoint(transformers, shape.v[i + 1]);
- this.checkBounds(vPoint, oPoint, nextIPoint, nextVPoint, boundingBox);
- }
- if (shape.c) {
- vPoint = this.getTransformedPoint(transformers, shape.v[i]);
- oPoint = this.getTransformedPoint(transformers, shape.o[i]);
- nextIPoint = this.getTransformedPoint(transformers, shape.i[0]);
- nextVPoint = this.getTransformedPoint(transformers, shape.v[0]);
- this.checkBounds(vPoint, oPoint, nextIPoint, nextVPoint, boundingBox);
- }
- };
- HShapeElement.prototype.checkBounds = function (vPoint, oPoint, nextIPoint, nextVPoint, boundingBox) {
- this.getBoundsOfCurve(vPoint, oPoint, nextIPoint, nextVPoint);
- var bounds = this.shapeBoundingBox;
- boundingBox.x = bmMin(bounds.left, boundingBox.x);
- boundingBox.xMax = bmMax(bounds.right, boundingBox.xMax);
- boundingBox.y = bmMin(bounds.top, boundingBox.y);
- boundingBox.yMax = bmMax(bounds.bottom, boundingBox.yMax);
- };
- HShapeElement.prototype.shapeBoundingBox = {
- left: 0,
- right: 0,
- top: 0,
- bottom: 0,
- };
- HShapeElement.prototype.tempBoundingBox = {
- x: 0,
- xMax: 0,
- y: 0,
- yMax: 0,
- width: 0,
- height: 0,
- };
- HShapeElement.prototype.getBoundsOfCurve = function (p0, p1, p2, p3) {
- var bounds = [[p0[0], p3[0]], [p0[1], p3[1]]];
- for (var a, b, c, t, b2ac, t1, t2, i = 0; i < 2; ++i) { // eslint-disable-line no-plusplus
- b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i];
- a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i];
- c = 3 * p1[i] - 3 * p0[i];
- b |= 0; // eslint-disable-line no-bitwise
- a |= 0; // eslint-disable-line no-bitwise
- c |= 0; // eslint-disable-line no-bitwise
- if (a === 0 && b === 0) {
- //
- } else if (a === 0) {
- t = -c / b;
- if (t > 0 && t < 1) {
- bounds[i].push(this.calculateF(t, p0, p1, p2, p3, i));
- }
- } else {
- b2ac = b * b - 4 * c * a;
- if (b2ac >= 0) {
- t1 = (-b + bmSqrt(b2ac)) / (2 * a);
- if (t1 > 0 && t1 < 1) bounds[i].push(this.calculateF(t1, p0, p1, p2, p3, i));
- t2 = (-b - bmSqrt(b2ac)) / (2 * a);
- if (t2 > 0 && t2 < 1) bounds[i].push(this.calculateF(t2, p0, p1, p2, p3, i));
- }
- }
- }
- this.shapeBoundingBox.left = bmMin.apply(null, bounds[0]);
- this.shapeBoundingBox.top = bmMin.apply(null, bounds[1]);
- this.shapeBoundingBox.right = bmMax.apply(null, bounds[0]);
- this.shapeBoundingBox.bottom = bmMax.apply(null, bounds[1]);
- };
- HShapeElement.prototype.calculateF = function (t, p0, p1, p2, p3, i) {
- return bmPow(1 - t, 3) * p0[i]
- + 3 * bmPow(1 - t, 2) * t * p1[i]
- + 3 * (1 - t) * bmPow(t, 2) * p2[i]
- + bmPow(t, 3) * p3[i];
- };
- HShapeElement.prototype.calculateBoundingBox = function (itemsData, boundingBox) {
- var i;
- var len = itemsData.length;
- for (i = 0; i < len; i += 1) {
- if (itemsData[i] && itemsData[i].sh) {
- this.calculateShapeBoundingBox(itemsData[i], boundingBox);
- } else if (itemsData[i] && itemsData[i].it) {
- this.calculateBoundingBox(itemsData[i].it, boundingBox);
- } else if (itemsData[i] && itemsData[i].style && itemsData[i].w) {
- this.expandStrokeBoundingBox(itemsData[i].w, boundingBox);
- }
- }
- };
- HShapeElement.prototype.expandStrokeBoundingBox = function (widthProperty, boundingBox) {
- var width = 0;
- if (widthProperty.keyframes) {
- for (var i = 0; i < widthProperty.keyframes.length; i += 1) {
- var kfw = widthProperty.keyframes[i].s;
- if (kfw > width) {
- width = kfw;
- }
- }
- width *= widthProperty.mult;
- } else {
- width = widthProperty.v * widthProperty.mult;
- }
- boundingBox.x -= width;
- boundingBox.xMax += width;
- boundingBox.y -= width;
- boundingBox.yMax += width;
- };
- HShapeElement.prototype.currentBoxContains = function (box) {
- return this.currentBBox.x <= box.x
- && this.currentBBox.y <= box.y
- && this.currentBBox.width + this.currentBBox.x >= box.x + box.width
- && this.currentBBox.height + this.currentBBox.y >= box.y + box.height;
- };
- HShapeElement.prototype.renderInnerContent = function () {
- this._renderShapeFrame();
- if (!this.hidden && (this._isFirstFrame || this._mdf)) {
- var tempBoundingBox = this.tempBoundingBox;
- var max = 999999;
- tempBoundingBox.x = max;
- tempBoundingBox.xMax = -max;
- tempBoundingBox.y = max;
- tempBoundingBox.yMax = -max;
- this.calculateBoundingBox(this.itemsData, tempBoundingBox);
- tempBoundingBox.width = tempBoundingBox.xMax < tempBoundingBox.x ? 0 : tempBoundingBox.xMax - tempBoundingBox.x;
- tempBoundingBox.height = tempBoundingBox.yMax < tempBoundingBox.y ? 0 : tempBoundingBox.yMax - tempBoundingBox.y;
- // var tempBoundingBox = this.shapeCont.getBBox();
- if (this.currentBoxContains(tempBoundingBox)) {
- return;
- }
- var changed = false;
- if (this.currentBBox.w !== tempBoundingBox.width) {
- this.currentBBox.w = tempBoundingBox.width;
- this.shapeCont.setAttribute('width', tempBoundingBox.width);
- changed = true;
- }
- if (this.currentBBox.h !== tempBoundingBox.height) {
- this.currentBBox.h = tempBoundingBox.height;
- this.shapeCont.setAttribute('height', tempBoundingBox.height);
- changed = true;
- }
- if (changed || this.currentBBox.x !== tempBoundingBox.x || this.currentBBox.y !== tempBoundingBox.y) {
- this.currentBBox.w = tempBoundingBox.width;
- this.currentBBox.h = tempBoundingBox.height;
- this.currentBBox.x = tempBoundingBox.x;
- this.currentBBox.y = tempBoundingBox.y;
- this.shapeCont.setAttribute('viewBox', this.currentBBox.x + ' ' + this.currentBBox.y + ' ' + this.currentBBox.w + ' ' + this.currentBBox.h);
- var shapeStyle = this.shapeCont.style;
- var shapeTransform = 'translate(' + this.currentBBox.x + 'px,' + this.currentBBox.y + 'px)';
- shapeStyle.transform = shapeTransform;
- shapeStyle.webkitTransform = shapeTransform;
- }
- }
- };
- export default HShapeElement;
|