UNPKG

animare

Version:

Advanced animation library for modern JavaScript.

17 lines 2.43 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.generateEasingFunctionFromString=generateEasingFunctionFromString;/** - Converts a path string to two dimensional array `[[M], ...[C]]` */function parsePointsFromPathString(path){const pathData=path.match(/-?[0-9.]+/g)?.map(parseFloat);const points=[];if(!pathData)return points;points.push([pathData[0],pathData[1]]);// M points // C points for(let i=2;i<pathData.length;i+=6){points.push([pathData[i],pathData[i+1],pathData[i+2],pathData[i+3],pathData[i+4],pathData[i+5]]);}return points;}/** * - Convert to relative value -> * - Flip the Y points -> * - Store only Cubic curves with starting, control, and ending points (without the first M command). */function preparePointsForAnimation(array){const results=[];let x=0;let y=0;for(let i=0;i<array.length;i++){const curve=array[i];const c1x=curve[0];const c1y=1-curve[1];if(!i){x=c1x;y=c1y;continue;}const c2x=curve[2];const c2y=1-curve[3];const px=curve[4];const py=1-curve[5];results.push([x,y,c1x,c1y,c2x,c2y,px,py]);x=px;y=py;}return results;}function generateEasingFunctionFromString(path){const points=parsePointsFromPathString(path);const curves=preparePointsForAnimation(points);const epsilon=1e-6;// Desired precision on the computation. return t=>{// Special case start and end. if(t===0)return curves[0][1];// The Y-coordinate of the first point of the first curve if(t===1)return curves[curves.length-1][7];// The Y-coordinate of the end point of the last curve let from=0;for(let i=0;i<curves.length;i++){const[p0x,p0y,c0x,c0y,c1x,c1y,p1x,p1y]=curves[i];if(t<from||t>p1x)continue;// t is outside the range of the current curve from=p1x;// A binary search algorithm is used to determine the Y-coordinate value // corresponding to a specified position on the X-coordinate. let start=0,end=1,target=(start+end)/2,times=0;while(target>=start&&target<=1){// Compute the point (x, y) on the curve for a given time `target` [0 to 1] const mt=1-target,mt2=mt*mt,mt3=mt2*mt;const x=p0x*mt3+c0x*3*mt2*target+c1x*3*mt*target*target+p1x*target**3;const y=p0y*mt3+c0y*3*mt2*target+c1y*3*mt*target*target+p1y*target**3;// If the point cannot be found within 50 attempts, a safe loop break will be triggered. if(++times>50)return y;// Return the located Y-coordinate value. if(Math.abs(x-t)<=epsilon)return y;if(x>=t)end=target;else start=target;target=(start+end)/2;}return 0;}return 0;};}