UNPKG

bodymovin

Version:

After Effects plugin for exporting animations to SVG + JavaScript or canvas + JavaScript

314 lines (300 loc) 12.4 kB
function TrimModifier(){}; extendPrototype(ShapeModifier,TrimModifier); TrimModifier.prototype.processKeys = function(forceRender){ if(this.elem.globalData.frameId === this.frameId && !forceRender){ return; } this.mdf = forceRender ? true : false; this.frameId = this.elem.globalData.frameId; var i, len = this.dynamicProperties.length; for(i=0;i<len;i+=1){ this.dynamicProperties[i].getValue(); if(this.dynamicProperties[i].mdf){ this.mdf = true; } } if(this.mdf || forceRender){ var o = (this.o.v%360)/360; if(o < 0){ o += 1; } var s = this.s.v + o; var e = this.e.v + o; if(s == e){ } if(s>e){ var _s = s; s = e; e = _s; } this.sValue = s; this.eValue = e; this.oValue = o; } } TrimModifier.prototype.initModifierProperties = function(elem,data){ this.sValue = 0; this.eValue = 0; this.oValue = 0; this.getValue = this.processKeys; this.s = PropertyFactory.getProp(elem,data.s,0,0.01,this.dynamicProperties); this.e = PropertyFactory.getProp(elem,data.e,0,0.01,this.dynamicProperties); this.o = PropertyFactory.getProp(elem,data.o,0,0,this.dynamicProperties); this.m = data.m; if(!this.dynamicProperties.length){ this.getValue(true); } }; TrimModifier.prototype.calculateShapeEdges = function(s, e, shapeLength, addedLength, totalModifierLength) { var segments = [] if(e <= 1){ segments.push({ s: s, e: e }) }else if(s >= 1){ segments.push({ s: s - 1, e: e - 1 }) }else{ segments.push({ s: s, e: 1 }) segments.push({ s: 0, e: e - 1 }) } var shapeSegments = []; var i, len = segments.length, segmentOb; for(i = 0; i < len; i += 1) { segmentOb = segments[i]; if (segmentOb.e * totalModifierLength < addedLength || segmentOb.s * totalModifierLength > addedLength + shapeLength) { } else { var shapeS, shapeE; if(segmentOb.s * totalModifierLength <= addedLength) { shapeS = 0; } else { shapeS = (segmentOb.s * totalModifierLength - addedLength) / shapeLength; } if(segmentOb.e * totalModifierLength >= addedLength + shapeLength) { shapeE = 1; } else { shapeE = ((segmentOb.e * totalModifierLength - addedLength) / shapeLength); } shapeSegments.push([shapeS, shapeE]); } } if(!shapeSegments.length){ shapeSegments.push([0,0]); } return shapeSegments; } TrimModifier.prototype.processShapes = function(firstFrame){ var shapePaths; var i, len = this.shapes.length; var j, jLen; var s = this.sValue; var e = this.eValue; var pathsData,pathData, totalShapeLength, totalModifierLength = 0; if(e === s){ for(i=0;i<len;i+=1){ this.shapes[i].localShapeCollection.releaseShapes(); this.shapes[i].shape.mdf = true; this.shapes[i].shape.paths = this.shapes[i].localShapeCollection; } } else if(!((e === 1 && s === 0) || (e===0 && s === 1))){ var segments = [], shapeData, localShapeCollection; for(i=0;i<len;i+=1){ shapeData = this.shapes[i]; if(!shapeData.shape.mdf && !this.mdf && !firstFrame && this.m !== 2){ shapeData.shape.paths = shapeData.localShapeCollection; } else { shapePaths = shapeData.shape.paths; jLen = shapePaths._length; totalShapeLength = 0; if(!shapeData.shape.mdf && shapeData.pathsData){ totalShapeLength = shapeData.totalShapeLength; } else { pathsData = []; for(j=0;j<jLen;j+=1){ pathData = bez.getSegmentsLength(shapePaths.shapes[j]); pathsData.push(pathData); totalShapeLength += pathData.totalLength; } shapeData.totalShapeLength = totalShapeLength; shapeData.pathsData = pathsData; } totalModifierLength += totalShapeLength; shapeData.shape.mdf = true; } } var shapeS = s, shapeE = e, addedLength = 0; var j, jLen; for(i = len - 1; i >= 0; i -= 1){ shapeData = this.shapes[i]; if (shapeData.shape.mdf) { localShapeCollection = shapeData.localShapeCollection; localShapeCollection.releaseShapes(); if(this.m === 2 && len > 1) { var edges = this.calculateShapeEdges(s, e, shapeData.totalShapeLength, addedLength, totalModifierLength); addedLength += shapeData.totalShapeLength; } else { edges = [[shapeS, shapeE]] } jLen = edges.length; for (j = 0; j < jLen; j += 1) { shapeS = edges[j][0]; shapeE = edges[j][1]; segments.length = 0; if(shapeE <= 1){ segments.push({ s:shapeData.totalShapeLength * shapeS, e:shapeData.totalShapeLength * shapeE }) }else if(shapeS >= 1){ segments.push({ s:shapeData.totalShapeLength * (shapeS - 1), e:shapeData.totalShapeLength * (shapeE - 1) }) }else{ segments.push({ s:shapeData.totalShapeLength * shapeS, e:shapeData.totalShapeLength }) segments.push({ s:0, e:shapeData.totalShapeLength*(shapeE - 1) }) } var newShapesData = this.addShapes(shapeData,segments[0]); if (segments[0].s !== segments[0].e) { var lastPos; if(segments.length > 1){ if(shapeData.shape.v.c){ var lastShape = newShapesData.pop(); this.addPaths(newShapesData, localShapeCollection); newShapesData = this.addShapes(shapeData,segments[1], lastShape); } else { this.addPaths(newShapesData, localShapeCollection); newShapesData = this.addShapes(shapeData,segments[1]); } } this.addPaths(newShapesData, localShapeCollection); } } shapeData.shape.paths = localShapeCollection; } } } else if(this.mdf){ for(i=0;i<len;i+=1){ this.shapes[i].shape.mdf = true; } } if(!this.dynamicProperties.length){ this.mdf = false; } } TrimModifier.prototype.addPaths = function(newPaths, localShapeCollection) { var i, len = newPaths.length; for(i = 0; i < len; i += 1) { localShapeCollection.addShape(newPaths[i]) } } TrimModifier.prototype.addSegment = function(pt1,pt2,pt3,pt4,shapePath,pos, newShape) { /*console.log(pt1, 'vertex: v, at: ', pos); console.log(pt2, 'vertex: o, at: ', pos); console.log(pt3, 'vertex: i, at: ', pos + 1); console.log(pt4, 'vertex: v, at: ', pos + 1); console.log('newShape: ', newShape);*/ shapePath.setXYAt(pt2[0],pt2[1],'o',pos); shapePath.setXYAt(pt3[0],pt3[1],'i',pos + 1); if(newShape){ shapePath.setXYAt(pt1[0],pt1[1],'v',pos); } shapePath.setXYAt(pt4[0],pt4[1],'v',pos + 1); } TrimModifier.prototype.addShapes = function(shapeData, shapeSegment, shapePath){ var pathsData = shapeData.pathsData; var shapePaths = shapeData.shape.paths.shapes; var i, len = shapeData.shape.paths._length, j, jLen; var addedLength = 0; var currentLengthData,segmentCount; var lengths; var segment; var shapes = []; var initPos; var newShape = true; if(!shapePath){ shapePath = shape_pool.newShape(); segmentCount = 0; initPos = 0; } else { segmentCount = shapePath._length; initPos = shapePath._length; } shapes.push(shapePath); for(i=0;i<len;i+=1){ lengths = pathsData[i].lengths; shapePath.c = shapePaths[i].c; jLen = shapePaths[i].c ? lengths.length : lengths.length + 1; for(j=1;j<jLen;j+=1){ currentLengthData = lengths[j-1]; if(addedLength + currentLengthData.addedLength < shapeSegment.s){ addedLength += currentLengthData.addedLength; shapePath.c = false; } else if(addedLength > shapeSegment.e){ shapePath.c = false; break; } else { if(shapeSegment.s <= addedLength && shapeSegment.e >= addedLength + currentLengthData.addedLength){ this.addSegment(shapePaths[i].v[j-1],shapePaths[i].o[j-1],shapePaths[i].i[j],shapePaths[i].v[j],shapePath,segmentCount,newShape); newShape = false; } else { segment = bez.getNewSegment(shapePaths[i].v[j-1],shapePaths[i].v[j],shapePaths[i].o[j-1],shapePaths[i].i[j], (shapeSegment.s - addedLength)/currentLengthData.addedLength,(shapeSegment.e - addedLength)/currentLengthData.addedLength, lengths[j-1]); this.addSegment(segment.pt1,segment.pt3,segment.pt4,segment.pt2,shapePath,segmentCount,newShape); newShape = false; shapePath.c = false; } addedLength += currentLengthData.addedLength; segmentCount += 1; } } if(shapePaths[i].c){ currentLengthData = lengths[j-1]; if(addedLength <= shapeSegment.e){ var segmentLength = lengths[j-1].addedLength; if(shapeSegment.s <= addedLength && shapeSegment.e >= addedLength + segmentLength){ this.addSegment(shapePaths[i].v[j-1],shapePaths[i].o[j-1],shapePaths[i].i[0],shapePaths[i].v[0],shapePath,segmentCount,newShape); newShape = false; }else{ segment = bez.getNewSegment(shapePaths[i].v[j-1],shapePaths[i].v[0],shapePaths[i].o[j-1],shapePaths[i].i[0], (shapeSegment.s - addedLength)/segmentLength,(shapeSegment.e - addedLength)/segmentLength, lengths[j-1]); this.addSegment(segment.pt1,segment.pt3,segment.pt4,segment.pt2,shapePath,segmentCount,newShape); newShape = false; shapePath.c = false; } } else { shapePath.c = false; } addedLength += currentLengthData.addedLength; segmentCount += 1; } if(shapePath._length){ shapePath.setXYAt(shapePath.v[initPos][0],shapePath.v[initPos][1],'i',initPos); shapePath.setXYAt(shapePath.v[shapePath._length - 1][0],shapePath.v[shapePath._length - 1][1],'o',shapePath._length - 1); } if(addedLength > shapeSegment.e){ break; } if(i<len-1){ shapePath = shape_pool.newShape(); newShape = true; shapes.push(shapePath); segmentCount = 0; } } return shapes; } ShapeModifiers.registerModifier('tm',TrimModifier);