UNPKG

bodymovin

Version:

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

576 lines (552 loc) 26.3 kB
function TextAnimatorProperty(textData, renderType, elem){ this.mdf = false; this._firstFrame = true; this._hasMaskedPath = false; this._frameId = -1; this._dynamicProperties = []; this._textData = textData; this._renderType = renderType; this._elem = elem; this._animatorsData = Array.apply(null,{length:this._textData.a.length}); this._pathData = {} this._moreOptions = { alignment: {} }; this.renderedLetters = []; this.lettersChangedFlag = false; } TextAnimatorProperty.prototype.searchProperties = function(dynamicProperties){ var i, len = this._textData.a.length, animatorData, animatorProps; var getProp = PropertyFactory.getProp; for(i=0;i<len;i+=1){ animatorProps = this._textData.a[i]; animatorData = { a: {}, s: {} }; if('r' in animatorProps.a) { animatorData.a.r = getProp(this._elem,animatorProps.a.r,0,degToRads,this._dynamicProperties); } if('rx' in animatorProps.a) { animatorData.a.rx = getProp(this._elem,animatorProps.a.rx,0,degToRads,this._dynamicProperties); } if('ry' in animatorProps.a) { animatorData.a.ry = getProp(this._elem,animatorProps.a.ry,0,degToRads,this._dynamicProperties); } if('sk' in animatorProps.a) { animatorData.a.sk = getProp(this._elem,animatorProps.a.sk,0,degToRads,this._dynamicProperties); } if('sa' in animatorProps.a) { animatorData.a.sa = getProp(this._elem,animatorProps.a.sa,0,degToRads,this._dynamicProperties); } if('s' in animatorProps.a) { animatorData.a.s = getProp(this._elem,animatorProps.a.s,1,0.01,this._dynamicProperties); } if('a' in animatorProps.a) { animatorData.a.a = getProp(this._elem,animatorProps.a.a,1,0,this._dynamicProperties); } if('o' in animatorProps.a) { animatorData.a.o = getProp(this._elem,animatorProps.a.o,0,0.01,this._dynamicProperties); } if('p' in animatorProps.a) { animatorData.a.p = getProp(this._elem,animatorProps.a.p,1,0,this._dynamicProperties); } if('sw' in animatorProps.a) { animatorData.a.sw = getProp(this._elem,animatorProps.a.sw,0,0,this._dynamicProperties); } if('sc' in animatorProps.a) { animatorData.a.sc = getProp(this._elem,animatorProps.a.sc,1,0,this._dynamicProperties); } if('fc' in animatorProps.a) { animatorData.a.fc = getProp(this._elem,animatorProps.a.fc,1,0,this._dynamicProperties); } if('fh' in animatorProps.a) { animatorData.a.fh = getProp(this._elem,animatorProps.a.fh,0,0,this._dynamicProperties); } if('fs' in animatorProps.a) { animatorData.a.fs = getProp(this._elem,animatorProps.a.fs,0,0.01,this._dynamicProperties); } if('fb' in animatorProps.a) { animatorData.a.fb = getProp(this._elem,animatorProps.a.fb,0,0.01,this._dynamicProperties); } if('t' in animatorProps.a) { animatorData.a.t = getProp(this._elem,animatorProps.a.t,0,0,this._dynamicProperties); } animatorData.s = PropertyFactory.getTextSelectorProp(this._elem,animatorProps.s,this._dynamicProperties); animatorData.s.t = animatorProps.s.t; this._animatorsData[i] = animatorData; } if(this._textData.p && 'm' in this._textData.p){ this._pathData = { f: getProp(this._elem,this._textData.p.f,0,0,this._dynamicProperties), l: getProp(this._elem,this._textData.p.l,0,0,this._dynamicProperties), r: this._textData.p.r, m: this._elem.maskManager.getMaskProperty(this._textData.p.m) }; this._hasMaskedPath = true; } else { this._hasMaskedPath = false; } this._moreOptions.alignment = getProp(this._elem,this._textData.m.a,1,0,this._dynamicProperties); if(this._dynamicProperties.length) { dynamicProperties.push(this); } } TextAnimatorProperty.prototype.getMeasures = function(documentData, lettersChangedFlag){ this.lettersChangedFlag = lettersChangedFlag; if(!this.mdf && !this._firstFrame && !lettersChangedFlag && (!this._hasMaskedPath || !this._pathData.m.mdf)) { return; } this._firstFrame = false; var alignment = this._moreOptions.alignment.v; var animators = this._animatorsData; var textData = this._textData; var matrixHelper = this.mHelper; var renderType = this._renderType; var renderedLettersCount = this.renderedLetters.length; var data = this.data; var xPos,yPos; var i, len; var letters = documentData.l; if(this._hasMaskedPath) { var mask = this._pathData.m; if(!this._pathData.n || this._pathData.mdf){ var paths = mask.v; if(this._pathData.r){ paths = reversePath(paths); } var pathInfo = { tLength: 0, segments: [] }; len = paths._length - 1; var pathData; var totalLength = 0; for (i = 0; i < len; i += 1) { pathData = { s: paths.v[i], e: paths.v[i + 1], to: [paths.o[i][0] - paths.v[i][0], paths.o[i][1] - paths.v[i][1]], ti: [paths.i[i + 1][0] - paths.v[i + 1][0], paths.i[i + 1][1] - paths.v[i + 1][1]] }; bez.buildBezierData(pathData); pathInfo.tLength += pathData.bezierData.segmentLength; pathInfo.segments.push(pathData); totalLength += pathData.bezierData.segmentLength; } i = len; if (mask.v.c) { pathData = { s: paths.v[i], e: paths.v[0], to: [paths.o[i][0] - paths.v[i][0], paths.o[i][1] - paths.v[i][1]], ti: [paths.i[0][0] - paths.v[0][0], paths.i[0][1] - paths.v[0][1]] }; bez.buildBezierData(pathData); pathInfo.tLength += pathData.bezierData.segmentLength; pathInfo.segments.push(pathData); totalLength += pathData.bezierData.segmentLength; } this._pathData.pi = pathInfo; } var pathInfo = this._pathData.pi; var currentLength = this._pathData.f.v, segmentInd = 0, pointInd = 1, currentPoint, prevPoint, points; var segmentLength = 0, flag = true; var segments = pathInfo.segments; if (currentLength < 0 && mask.v.c) { if (pathInfo.tLength < Math.abs(currentLength)) { currentLength = -Math.abs(currentLength) % pathInfo.tLength; } segmentInd = segments.length - 1; points = segments[segmentInd].bezierData.points; pointInd = points.length - 1; while (currentLength < 0) { currentLength += points[pointInd].partialLength; pointInd -= 1; if (pointInd < 0) { segmentInd -= 1; points = segments[segmentInd].bezierData.points; pointInd = points.length - 1; } } } points = segments[segmentInd].bezierData.points; prevPoint = points[pointInd - 1]; currentPoint = points[pointInd]; var partialLength = currentPoint.partialLength; var perc, tanAngle; } len = letters.length; xPos = 0; yPos = 0; var yOff = documentData.s*1.2*.714; var firstLine = true; var animatorProps, animatorSelector; var j, jLen; var letterValue; jLen = animators.length; if (lettersChangedFlag) { for (j = 0; j < jLen; j += 1) { animatorSelector = animators[j].s; animatorSelector.getValue(true); } } var lastLetter; var mult, ind = -1, offf, xPathPos, yPathPos; var initPathPos = currentLength,initSegmentInd = segmentInd, initPointInd = pointInd, currentLine = -1; var elemOpacity; var sc,sw,fc,k; var lineLength = 0; var letterSw,letterSc,letterFc,letterM = '',letterP = this.defaultPropsArray,letterO; for( i = 0; i < len; i += 1) { matrixHelper.reset(); elemOpacity = 1; if(letters[i].n) { xPos = 0; yPos += documentData.yOffset; yPos += firstLine ? 1 : 0; currentLength = initPathPos ; firstLine = false; lineLength = 0; if(this._hasMaskedPath) { segmentInd = initSegmentInd; pointInd = initPointInd; points = segments[segmentInd].bezierData.points; prevPoint = points[pointInd - 1]; currentPoint = points[pointInd]; partialLength = currentPoint.partialLength; segmentLength = 0; } letterO = letterSw = letterFc = letterM = ''; letterP = this.defaultPropsArray; }else{ if(this._hasMaskedPath) { if(currentLine !== letters[i].line){ switch(documentData.j){ case 1: currentLength += totalLength - documentData.lineWidths[letters[i].line]; break; case 2: currentLength += (totalLength - documentData.lineWidths[letters[i].line])/2; break; } currentLine = letters[i].line; } if (ind !== letters[i].ind) { if (letters[ind]) { currentLength += letters[ind].extra; } currentLength += letters[i].an / 2; ind = letters[i].ind; } currentLength += alignment[0] * letters[i].an / 200; var animatorOffset = 0; for (j = 0; j < jLen; j += 1) { animatorProps = animators[j].a; if ('p' in animatorProps) { animatorSelector = animators[j].s; mult = animatorSelector.getMult(letters[i].anIndexes[j],textData.a[j].s.totalChars); if(mult.length){ animatorOffset += animatorProps.p.v[0] * mult[0]; } else{ animatorOffset += animatorProps.p.v[0] * mult; } } if ('a' in animatorProps) { animatorSelector = animators[j].s; mult = animatorSelector.getMult(letters[i].anIndexes[j],textData.a[j].s.totalChars); if(mult.length){ animatorOffset += animatorProps.a.v[0] * mult[0]; } else{ animatorOffset += animatorProps.a.v[0] * mult; } } } flag = true; while (flag) { if (segmentLength + partialLength >= currentLength + animatorOffset || !points) { perc = (currentLength + animatorOffset - segmentLength) / currentPoint.partialLength; xPathPos = prevPoint.point[0] + (currentPoint.point[0] - prevPoint.point[0]) * perc; yPathPos = prevPoint.point[1] + (currentPoint.point[1] - prevPoint.point[1]) * perc; matrixHelper.translate(-alignment[0]*letters[i].an/200, -(alignment[1] * yOff / 100)); flag = false; } else if (points) { segmentLength += currentPoint.partialLength; pointInd += 1; if (pointInd >= points.length) { pointInd = 0; segmentInd += 1; if (!segments[segmentInd]) { if (mask.v.c) { pointInd = 0; segmentInd = 0; points = segments[segmentInd].bezierData.points; } else { segmentLength -= currentPoint.partialLength; points = null; } } else { points = segments[segmentInd].bezierData.points; } } if (points) { prevPoint = currentPoint; currentPoint = points[pointInd]; partialLength = currentPoint.partialLength; } } } offf = letters[i].an / 2 - letters[i].add; matrixHelper.translate(-offf, 0, 0); } else { offf = letters[i].an/2 - letters[i].add; matrixHelper.translate(-offf,0,0); // Grouping alignment matrixHelper.translate(-alignment[0]*letters[i].an/200, -alignment[1]*yOff/100, 0); } lineLength += letters[i].l/2; for(j=0;j<jLen;j+=1){ animatorProps = animators[j].a; if ('t' in animatorProps) { animatorSelector = animators[j].s; mult = animatorSelector.getMult(letters[i].anIndexes[j],textData.a[j].s.totalChars); if(this._hasMaskedPath) { if(mult.length) { currentLength += animatorProps.t*mult[0]; } else { currentLength += animatorProps.t*mult; } }else{ if(mult.length) { xPos += animatorProps.t.v*mult[0]; } else { xPos += animatorProps.t.v*mult; } } } } lineLength += letters[i].l/2; if(documentData.strokeWidthAnim) { sw = documentData.sw || 0; } if(documentData.strokeColorAnim) { if(documentData.sc){ sc = [documentData.sc[0], documentData.sc[1], documentData.sc[2]]; }else{ sc = [0,0,0]; } } if(documentData.fillColorAnim && documentData.fc) { fc = [documentData.fc[0], documentData.fc[1], documentData.fc[2]]; } for(j=0;j<jLen;j+=1){ animatorProps = animators[j].a; if ('a' in animatorProps) { animatorSelector = animators[j].s; mult = animatorSelector.getMult(letters[i].anIndexes[j],textData.a[j].s.totalChars); if(mult.length){ matrixHelper.translate(-animatorProps.a.v[0]*mult[0], -animatorProps.a.v[1]*mult[1], animatorProps.a.v[2]*mult[2]); } else { matrixHelper.translate(-animatorProps.a.v[0]*mult, -animatorProps.a.v[1]*mult, animatorProps.a.v[2]*mult); } } } for(j=0;j<jLen;j+=1){ animatorProps = animators[j].a; if ('s' in animatorProps) { animatorSelector = animators[j].s; mult = animatorSelector.getMult(letters[i].anIndexes[j],textData.a[j].s.totalChars); if(mult.length){ matrixHelper.scale(1+((animatorProps.s.v[0]-1)*mult[0]),1+((animatorProps.s.v[1]-1)*mult[1]),1); } else { matrixHelper.scale(1+((animatorProps.s.v[0]-1)*mult),1+((animatorProps.s.v[1]-1)*mult),1); } } } for(j=0;j<jLen;j+=1) { animatorProps = animators[j].a; animatorSelector = animators[j].s; mult = animatorSelector.getMult(letters[i].anIndexes[j],textData.a[j].s.totalChars); if ('sk' in animatorProps) { if(mult.length) { matrixHelper.skewFromAxis(-animatorProps.sk.v * mult[0], animatorProps.sa.v * mult[1]); } else { matrixHelper.skewFromAxis(-animatorProps.sk.v * mult, animatorProps.sa.v * mult); } } if ('r' in animatorProps) { if(mult.length) { matrixHelper.rotateZ(-animatorProps.r.v * mult[2]); } else { matrixHelper.rotateZ(-animatorProps.r.v * mult); } } if ('ry' in animatorProps) { if(mult.length) { matrixHelper.rotateY(animatorProps.ry.v*mult[1]); }else{ matrixHelper.rotateY(animatorProps.ry.v*mult); } } if ('rx' in animatorProps) { if(mult.length) { matrixHelper.rotateX(animatorProps.rx.v*mult[0]); } else { matrixHelper.rotateX(animatorProps.rx.v*mult); } } if ('o' in animatorProps) { if(mult.length) { elemOpacity += ((animatorProps.o.v)*mult[0] - elemOpacity)*mult[0]; } else { elemOpacity += ((animatorProps.o.v)*mult - elemOpacity)*mult; } } if (documentData.strokeWidthAnim && 'sw' in animatorProps) { if(mult.length) { sw += animatorProps.sw.v*mult[0]; } else { sw += animatorProps.sw.v*mult; } } if (documentData.strokeColorAnim && 'sc' in animatorProps) { for(k=0;k<3;k+=1){ if(mult.length) { sc[k] = sc[k] + (animatorProps.sc.v[k] - sc[k])*mult[0] } else { sc[k] = sc[k] + (animatorProps.sc.v[k] - sc[k])*mult; } } } if (documentData.fillColorAnim && documentData.fc) { if('fc' in animatorProps){ for(k=0;k<3;k+=1){ if(mult.length) { fc[k] = fc[k] + (animatorProps.fc.v[k] - fc[k])*mult[0]; } else { fc[k] = fc[k] + (animatorProps.fc.v[k] - fc[k])*mult; } } } if('fh' in animatorProps){ if(mult.length) { fc = addHueToRGB(fc,animatorProps.fh.v*mult[0]); } else { fc = addHueToRGB(fc,animatorProps.fh.v*mult); } } if('fs' in animatorProps){ if(mult.length) { fc = addSaturationToRGB(fc,animatorProps.fs.v*mult[0]); } else { fc = addSaturationToRGB(fc,animatorProps.fs.v*mult); } } if('fb' in animatorProps){ if(mult.length) { fc = addBrightnessToRGB(fc,animatorProps.fb.v*mult[0]); } else { fc = addBrightnessToRGB(fc,animatorProps.fb.v*mult); } } } } for(j=0;j<jLen;j+=1){ animatorProps = animators[j].a; if ('p' in animatorProps) { animatorSelector = animators[j].s; mult = animatorSelector.getMult(letters[i].anIndexes[j],textData.a[j].s.totalChars); if(this._hasMaskedPath) { if(mult.length) { matrixHelper.translate(0, animatorProps.p.v[1] * mult[0], -animatorProps.p.v[2] * mult[1]); } else { matrixHelper.translate(0, animatorProps.p.v[1] * mult, -animatorProps.p.v[2] * mult); } }else{ if(mult.length) { matrixHelper.translate(animatorProps.p.v[0] * mult[0], animatorProps.p.v[1] * mult[1], -animatorProps.p.v[2] * mult[2]); } else { matrixHelper.translate(animatorProps.p.v[0] * mult, animatorProps.p.v[1] * mult, -animatorProps.p.v[2] * mult); } } } } if(documentData.strokeWidthAnim){ letterSw = sw < 0 ? 0 : sw; } if(documentData.strokeColorAnim){ letterSc = 'rgb('+Math.round(sc[0]*255)+','+Math.round(sc[1]*255)+','+Math.round(sc[2]*255)+')'; } if(documentData.fillColorAnim && documentData.fc){ letterFc = 'rgb('+Math.round(fc[0]*255)+','+Math.round(fc[1]*255)+','+Math.round(fc[2]*255)+')'; } if(this._hasMaskedPath) { matrixHelper.translate(0,-documentData.ls); matrixHelper.translate(0, alignment[1]*yOff/100 + yPos,0); if (textData.p.p) { tanAngle = (currentPoint.point[1] - prevPoint.point[1]) / (currentPoint.point[0] - prevPoint.point[0]); var rot = Math.atan(tanAngle) * 180 / Math.PI; if (currentPoint.point[0] < prevPoint.point[0]) { rot += 180; } matrixHelper.rotate(-rot * Math.PI / 180); } matrixHelper.translate(xPathPos, yPathPos, 0); currentLength -= alignment[0]*letters[i].an/200; if(letters[i+1] && ind !== letters[i+1].ind){ currentLength += letters[i].an / 2; currentLength += documentData.tr/1000*documentData.s; } }else{ matrixHelper.translate(xPos,yPos,0); if(documentData.ps){ //matrixHelper.translate(documentData.ps[0],documentData.ps[1],0); matrixHelper.translate(documentData.ps[0],documentData.ps[1] + documentData.ascent,0); } switch(documentData.j){ case 1: matrixHelper.translate(documentData.justifyOffset + (documentData.boxWidth - documentData.lineWidths[letters[i].line]),0,0); break; case 2: matrixHelper.translate(documentData.justifyOffset + (documentData.boxWidth - documentData.lineWidths[letters[i].line])/2,0,0); break; } matrixHelper.translate(0,-documentData.ls); matrixHelper.translate(offf,0,0); matrixHelper.translate(alignment[0]*letters[i].an/200,alignment[1]*yOff/100,0); xPos += letters[i].l + documentData.tr/1000*documentData.s; } if(renderType === 'html'){ letterM = matrixHelper.toCSS(); }else if(renderType === 'svg'){ letterM = matrixHelper.to2dCSS(); }else{ letterP = [matrixHelper.props[0],matrixHelper.props[1],matrixHelper.props[2],matrixHelper.props[3],matrixHelper.props[4],matrixHelper.props[5],matrixHelper.props[6],matrixHelper.props[7],matrixHelper.props[8],matrixHelper.props[9],matrixHelper.props[10],matrixHelper.props[11],matrixHelper.props[12],matrixHelper.props[13],matrixHelper.props[14],matrixHelper.props[15]]; } letterO = elemOpacity; } if(renderedLettersCount <= i) { letterValue = new LetterProps(letterO,letterSw,letterSc,letterFc,letterM,letterP); this.renderedLetters.push(letterValue); renderedLettersCount += 1; this.lettersChangedFlag = true; } else { letterValue = this.renderedLetters[i]; this.lettersChangedFlag = letterValue.update(letterO, letterSw, letterSc, letterFc, letterM, letterP) || this.lettersChangedFlag; } } } TextAnimatorProperty.prototype.getValue = function(){ if(this._elem.globalData.frameId === this._frameId){ return; } this._frameId = this._elem.globalData.frameId; var i, len = this._dynamicProperties.length; this.mdf = false; for(i = 0; i < len; i += 1) { this._dynamicProperties[i].getValue(); this.mdf = this._dynamicProperties[i].mdf || this.mdf; } } TextAnimatorProperty.prototype.mHelper = new Matrix(); TextAnimatorProperty.prototype.defaultPropsArray = [];