diff --git a/.gitignore b/.gitignore index eeb5f8f..2a42f97 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,6 @@ node_modules # Optional REPL history .node_repl_history -/lib .DS_Store examples/interactive-docs/example.bundle.js diff --git a/lib/Animated.js b/lib/Animated.js new file mode 100644 index 0000000..6d3e591 --- /dev/null +++ b/lib/Animated.js @@ -0,0 +1,25 @@ + + + + + + + + + + +'use strict';var _createClass=function(){function defineProperties(target,props){for(var i=0;i0?1:0; +}},{key:'step1',value:function step1( + +n){ +return n>=1?1:0; +}},{key:'linear',value:function linear( + +t){ +return t; +}},{key:'ease',value:function ease( + +t){ +return _ease(t); +}},{key:'quad',value:function quad( + +t){ +return t*t; +}},{key:'cubic',value:function cubic( + +t){ +return t*t*t; +}},{key:'poly',value:function poly( + +n){ +return function(t){return Math.pow(t,n);}; +}},{key:'sin',value:function sin( + +t){ +return 1-Math.cos(t*Math.PI/2); +}},{key:'circle',value:function circle( + +t){ +return 1-Math.sqrt(1-t*t); +}},{key:'exp',value:function exp( + +t){ +return Math.pow(2,10*(t-1)); +}},{key:'elastic',value:function elastic() + + + + + + + + + + + +{var bounciness=arguments.length>0&&arguments[0]!==undefined?arguments[0]:1; +var p=bounciness*Math.PI; +return function(t){return 1-Math.pow(Math.cos(t*Math.PI/2),3)*Math.cos(t*p);}; +}},{key:'back',value:function back( + +s){ +if(s===undefined){ +s=1.70158; +} +return function(t){return t*t*((s+1)*t-s);}; +}},{key:'bounce',value:function bounce( + +t){ +if(t<1/2.75){ +return 7.5625*t*t; +} + +if(t<2/2.75){ +t-=1.5/2.75; +return 7.5625*t*t+0.75; +} + +if(t<2.5/2.75){ +t-=2.25/2.75; +return 7.5625*t*t+0.9375; +} + +t-=2.625/2.75; +return 7.5625*t*t+0.984375; +}},{key:'bezier',value:function bezier( + + +x1, +y1, +x2, +y2) +{ +return _bezier(x1,y1,x2,y2); +}},{key:'in',value:function _in( + + +easing) +{ +return easing; +}},{key:'out',value:function out( + + + + + +easing) +{ +return function(t){return 1-easing(1-t);}; +}},{key:'inOut',value:function inOut( + + + + + +easing) +{ +return function(t){ +if(t<0.5){ +return easing(t*2)/2; +} +return 1-easing((1-t)*2)/2; +}; +}}]);return Easing;}(); + + +var _ease=Easing.bezier(0.42,0,1,1); + + + +module.exports=Easing; \ No newline at end of file diff --git a/lib/Interpolation.js b/lib/Interpolation.js new file mode 100644 index 0000000..bc37640 --- /dev/null +++ b/lib/Interpolation.js @@ -0,0 +1,290 @@ + + + + + + + + + + + +'use strict';var _extends=Object.assign||function(target){for(var i=1;iinputMax){ +if(extrapolateRight==='identity'){ +return result; +}else if(extrapolateRight==='clamp'){ +result=inputMax; +}else if(extrapolateRight==='extend'){ + +} +} + +if(outputMin===outputMax){ +return outputMin; +} + +if(inputMin===inputMax){ +if(input<=inputMin){ +return outputMin; +} +return outputMax; +} + + +if(inputMin===-Infinity){ +result=-result; +}else if(inputMax===Infinity){ +result=result-inputMin; +}else{ +result=(result-inputMin)/(inputMax-inputMin); +} + + +result=easing(result); + + +if(outputMin===-Infinity){ +result=-result; +}else if(outputMax===Infinity){ +result=result+outputMin; +}else{ +result=result*(outputMax-outputMin)+outputMin; +} + +return result; +} + +function colorToRgba(input){ +var int32Color=normalizeColor(input); +if(int32Color===null){ +return input; +} + +int32Color=int32Color||0; + +var r=(int32Color&0xff000000)>>>24; +var g=(int32Color&0x00ff0000)>>>16; +var b=(int32Color&0x0000ff00)>>>8; +var a=(int32Color&0x000000ff)/255; + +return'rgba('+r+', '+g+', '+b+', '+a+')'; +} + +var stringShapeRegex=/[0-9\.-]+/g; + + + + + + + + + +function createInterpolationFromStringOutputRange( +config) +{ +var outputRange=config.outputRange; +invariant(outputRange.length>=2,'Bad output range'); +outputRange=outputRange.map(colorToRgba); +checkPattern(outputRange); + + + + + + + + + + + + +var outputRanges=outputRange[0].match(stringShapeRegex).map(function(){return[];}); +outputRange.forEach(function(value){ + + + +value.match(stringShapeRegex).forEach(function(number,i){ +outputRanges[i].push(+number); +}); +}); + + + + +var interpolations=outputRange[0].match(stringShapeRegex).map(function(value,i){ +return Interpolation.create(_extends({}, +config,{ +outputRange:outputRanges[i]})); + +}); + + + +var shouldRound=/^rgb/.test(outputRange[0]); + +return function(input){ +var i=0; + + + +return outputRange[0].replace(stringShapeRegex,function(){ +var val=interpolations[i++](input); +return String(shouldRound&&i<4?Math.round(val):val); +}); +}; +} + +function checkPattern(arr){ +var pattern=arr[0].replace(stringShapeRegex,''); +for(var i=1;i=input){ +break; +} +} +return i-1; +} + +function checkValidInputRange(arr){ +invariant(arr.length>=2,'inputRange must have at least 2 elements'); +for(var i=1;i=arr[i-1], + + + + + + +'inputRange must be monotonically increasing '+arr); + +} +} + +function checkInfiniteRange(name,arr){ +invariant(arr.length>=2,name+' must have at least 2 elements'); +invariant( +arr.length!==2||arr[0]!==-Infinity||arr[1]!==Infinity, + + + + + + +name+'cannot be ]-infinity;+infinity[ '+arr); + +} + +module.exports=Interpolation; \ No newline at end of file diff --git a/lib/SetPolyfill.js b/lib/SetPolyfill.js new file mode 100644 index 0000000..432f171 --- /dev/null +++ b/lib/SetPolyfill.js @@ -0,0 +1,26 @@ + + + + + + + + + +'use strict'; + +function SetPolyfill(){ +this._cache=[]; +} + +SetPolyfill.prototype.add=function(e){ +if(this._cache.indexOf(e)===-1){ +this._cache.push(e); +} +}; + +SetPolyfill.prototype.forEach=function(cb){ +this._cache.forEach(cb); +}; + +module.exports=SetPolyfill; \ No newline at end of file diff --git a/lib/SpringAnimation.js b/lib/SpringAnimation.js new file mode 100644 index 0000000..cb87aef --- /dev/null +++ b/lib/SpringAnimation.js @@ -0,0 +1,224 @@ + + + + + + + + + + +'use strict';var _createClass=function(){function defineProperties(target,props){for(var i=0;ithis._lastTime+MAX_STEPS){ +now=this._lastTime+MAX_STEPS; +} + + + + +var TIMESTEP_MSEC=1; +var numSteps=Math.floor((now-this._lastTime)/TIMESTEP_MSEC); + +for(var i=0;ithis._toValue; +}else{ +isOvershooting=position18&&tension<=44){ +return b3Friction2(tension); +}else{ +return b3Friction3(tension); +} +} + +var b=normalize(bounciness/1.7,0,20); +b=projectNormal(b,0,0.8); +var s=normalize(speed/1.7,0,20); +var bouncyTension=projectNormal(s,0.5,200); +var bouncyFriction=quadraticOutInterpolation( +b, +b3Nobounce(bouncyTension), +0.01); + + +return{ +tension:tensionFromOrigamiValue(bouncyTension), +friction:frictionFromOrigamiValue(bouncyFriction)}; + +} + +module.exports={ +fromOrigamiTensionAndFriction:fromOrigamiTensionAndFriction, +fromBouncinessAndSpeed:fromBouncinessAndSpeed}; \ No newline at end of file diff --git a/lib/TimingAnimation.js b/lib/TimingAnimation.js new file mode 100644 index 0000000..b5c4fac --- /dev/null +++ b/lib/TimingAnimation.js @@ -0,0 +1,110 @@ + + + + + + + + + + +'use strict';var _createClass=function(){function defineProperties(target,props){for(var i=0;i=this._startTime+this._duration){ +if(this._duration===0){ +this._onUpdate(this._toValue); +}else{ +this._onUpdate( +this._fromValue+this._easing(1)*(this._toValue-this._fromValue)); + +} +this.__debouncedOnEnd({finished:true}); +return; +} + +this._onUpdate( +this._fromValue+ +this._easing((now-this._startTime)/this._duration)*( +this._toValue-this._fromValue)); + +if(this.__active){ +this._animationFrame=RequestAnimationFrame.current(this.onUpdate.bind(this)); +} +}},{key:'stop',value:function stop() + +{ +this.__active=false; +clearTimeout(this._timeout); +CancelAnimationFrame.current(this._animationFrame); +this.__debouncedOnEnd({finished:false}); +}}]);return TimingAnimation;}(Animation); + + +module.exports=TimingAnimation; \ No newline at end of file diff --git a/lib/__tests__/Animated-test.js b/lib/__tests__/Animated-test.js new file mode 100644 index 0000000..3aae369 --- /dev/null +++ b/lib/__tests__/Animated-test.js @@ -0,0 +1,427 @@ + + + + + + + + +'use strict';var _templateObject=_taggedTemplateLiteral(['width: 100px'],['width: 100px']),_templateObject2=_taggedTemplateLiteral(['width: ','px; height: ','px'],['width: ','px; height: ','px']);function _taggedTemplateLiteral(strings,raw){return Object.freeze(Object.defineProperties(strings,{raw:{value:Object.freeze(raw)}}));} + +jest. +autoMockOff(); + +var Animated=require('../index'); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +describe('Animated Templates',function(){ +it('works with fully literal template string',function(){ +var template=Animated.template(_templateObject); +expect(template.__getValue()).toBe('width: 100px'); +}); +it('works with literal template that uses static values',function(){ +var value=42; +var template=Animated.template(_templateObject2,value,value); +expect(template.__getValue()).toBe('width: 42px; height: 42px'); +}); +it('works with literal template that uses Animated values',function(){ +var value=new Animated.Value(42); +var template=Animated.template(_templateObject2,value,value); +expect(template.__getValue()).toBe('width: 42px; height: 42px'); +value.setValue(13); +expect(template.__getValue()).toBe('width: 13px; height: 13px'); +}); +it('works with multiple different Animated values',function(){ +var value1=new Animated.Value(42); +var value2=new Animated.Value(13); +var template=Animated.template(_templateObject2,value1,value2); +expect(template.__getValue()).toBe('width: 42px; height: 13px'); +value1.setValue(21); +expect(template.__getValue()).toBe('width: 21px; height: 13px'); +value2.setValue(66); +expect(template.__getValue()).toBe('width: 21px; height: 66px'); +}); +}); \ No newline at end of file diff --git a/lib/__tests__/Easing-test.js b/lib/__tests__/Easing-test.js new file mode 100644 index 0000000..c563e08 --- /dev/null +++ b/lib/__tests__/Easing-test.js @@ -0,0 +1,127 @@ + + + + + + + + +'use strict';var _slicedToArray=function(){function sliceIterator(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[typeof Symbol==='function'?Symbol.iterator:'@@iterator'](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break;}}catch(err){_d=true;_e=err;}finally{try{if(!_n&&_i["return"])_i["return"]();}finally{if(_d)throw _e;}}return _arr;}return function(arr,i){if(Array.isArray(arr)){return arr;}else if((typeof Symbol==='function'?Symbol.iterator:'@@iterator')in Object(arr)){return sliceIterator(arr,i);}else{throw new TypeError("Invalid attempt to destructure non-iterable instance");}};}(); + +jest.dontMock('Easing'); + +var Easing=require('Easing'); +describe('Easing',function(){ +it('should work with linear',function(){ +var easing=Easing.linear; + +expect(easing(0)).toBe(0); +expect(easing(0.5)).toBe(0.5); +expect(easing(0.8)).toBe(0.8); +expect(easing(1)).toBe(1); +}); + +it('should work with ease in linear',function(){ +var easing=Easing.in(Easing.linear); +expect(easing(0)).toBe(0); +expect(easing(0.5)).toBe(0.5); +expect(easing(0.8)).toBe(0.8); +expect(easing(1)).toBe(1); +}); + +it('should work with easy out linear',function(){ +var easing=Easing.out(Easing.linear); +expect(easing(0)).toBe(0); +expect(easing(0.5)).toBe(0.5); +expect(easing(0.6)).toBe(0.6); +expect(easing(1)).toBe(1); +}); + +it('should work with ease in quad',function(){ +function easeInQuad(t){ +return t*t; +} +var easing=Easing.in(Easing.quad); +for(var t=-0.5;t<1.5;t+=0.1){ +expect(easing(t)).toBe(easeInQuad(t)); +} +}); + +it('should work with ease out quad',function(){ +function easeOutQuad(t){ +return-t*(t-2); +} +var easing=Easing.out(Easing.quad); +for(var t=0;t<=1;t+=0.1){ +expect(easing(1)).toBe(easeOutQuad(1)); +} +}); + +it('should work with ease in-out quad',function(){ +function easeInOutQuad(t){ +t=t*2; +if(t<1){ +return 0.5*t*t; +} +return-((t-1)*(t-3)-1)/2; +} +var easing=Easing.inOut(Easing.quad); +for(var t=-0.5;t<1.5;t+=0.1){ +expect(easing(t)).toBeCloseTo(easeInOutQuad(t),4); +} +}); + +it('should satisfy boundary conditions with elastic',function(){ +for(var b=0;b<4;b+=0.3){ +var easing=Easing.elastic(b); +expect(easing(0)).toBe(0); +expect(easing(1)).toBe(1); +} +}); + +function sampleEasingFunction(easing){ +var DURATION=300; +var tickCount=Math.round(DURATION*60/1000); +var samples=[]; +for(var i=0;i<=tickCount;i++){ +samples.push(easing(i/tickCount)); +} +return samples; +} + +var Samples={ +in_quad:[0,0.0030864197530864196,0.012345679012345678,0.027777777777777776,0.04938271604938271,0.0771604938271605,0.1111111111111111,0.15123456790123457,0.19753086419753085,0.25,0.308641975308642,0.37345679012345684,0.4444444444444444,0.5216049382716049,0.6049382716049383,0.6944444444444445,0.7901234567901234,0.8919753086419753,1], +out_quad:[0,0.10802469135802469,0.20987654320987653,0.3055555555555555,0.3950617283950617,0.47839506172839513,0.5555555555555556,0.6265432098765432,0.691358024691358,0.75,0.8024691358024691,0.8487654320987654,0.888888888888889,0.9228395061728394,0.9506172839506174,0.9722222222222221,0.9876543209876543,0.9969135802469136,1], +inOut_quad:[0,0.006172839506172839,0.024691358024691357,0.05555555555555555,0.09876543209876543,0.154320987654321,0.2222222222222222,0.30246913580246915,0.3950617283950617,0.5,0.6049382716049383,0.697530864197531,0.7777777777777777,0.845679012345679,0.9012345679012346,0.9444444444444444,0.9753086419753086,0.9938271604938271,1], +in_cubic:[0,0.00017146776406035664,0.0013717421124828531,0.004629629629629629,0.010973936899862825,0.021433470507544586,0.037037037037037035,0.05881344307270234,0.0877914951989026,0.125,0.1714677640603567,0.22822359396433475,0.2962962962962963,0.37671467764060357,0.4705075445816187,0.5787037037037038,0.7023319615912208,0.8424211248285322,1], +out_cubic:[0,0.15757887517146785,0.2976680384087792,0.42129629629629617,0.5294924554183813,0.6232853223593964,0.7037037037037036,0.7717764060356652,0.8285322359396433,0.875,0.9122085048010974,0.9411865569272977,0.9629629629629629,0.9785665294924554,0.9890260631001372,0.9953703703703703,0.9986282578875172,0.9998285322359396,1], +inOut_cubic:[0,0.0006858710562414266,0.0054869684499314125,0.018518518518518517,0.0438957475994513,0.08573388203017834,0.14814814814814814,0.23525377229080935,0.3511659807956104,0.5,0.6488340192043895,0.7647462277091908,0.8518518518518519,0.9142661179698217,0.9561042524005487,0.9814814814814815,0.9945130315500685,0.9993141289437586,1], +in_sin:[0,0.003805301908254455,0.01519224698779198,0.03407417371093169,0.06030737921409157,0.09369221296335006,0.1339745962155613,0.1808479557110082,0.233955556881022,0.2928932188134524,0.35721239031346064,0.42642356364895384,0.4999999999999999,0.5773817382593005,0.6579798566743311,0.7411809548974793,0.8263518223330696,0.9128442572523416,0.9999999999999999], +out_sin:[0,0.08715574274765817,0.17364817766693033,0.25881904510252074,0.3420201433256687,0.42261826174069944,0.49999999999999994,0.573576436351046,0.6427876096865393,0.7071067811865475,0.766044443118978,0.8191520442889918,0.8660254037844386,0.9063077870366499,0.9396926207859083,0.9659258262890683,0.984807753012208,0.9961946980917455,1], +inOut_sin:[0,0.00759612349389599,0.030153689607045786,0.06698729810778065,0.116977778440511,0.17860619515673032,0.24999999999999994,0.32898992833716556,0.4131759111665348,0.49999999999999994,0.5868240888334652,0.6710100716628343,0.7499999999999999,0.8213938048432696,0.883022221559489,0.9330127018922194,0.9698463103929542,0.9924038765061041,1], +in_exp:[0,0.0014352875901128893,0.002109491677524035,0.0031003926796253885,0.004556754060844206,0.006697218616039631,0.009843133202303688,0.014466792379488908,0.021262343752724643,0.03125,0.045929202883612456,0.06750373368076916,0.09921256574801243,0.1458161299470146,0.2143109957132682,0.31498026247371835,0.46293735614364506,0.6803950000871883,1], +out_exp:[0,0.31960499991281155,0.5370626438563548,0.6850197375262816,0.7856890042867318,0.8541838700529854,0.9007874342519875,0.9324962663192309,0.9540707971163875,0.96875,0.9787376562472754,0.9855332076205111,0.9901568667976963,0.9933027813839603,0.9954432459391558,0.9968996073203746,0.9978905083224759,0.9985647124098871,1], +inOut_exp:[0,0.0010547458387620175,0.002278377030422103,0.004921566601151844,0.010631171876362321,0.022964601441806228,0.049606282874006216,0.1071554978566341,0.23146867807182253,0.5,0.7685313219281775,0.892844502143366,0.9503937171259937,0.9770353985581938,0.9893688281236377,0.9950784333988482,0.9977216229695779,0.998945254161238,1], +in_circle:[0,0.0015444024660317135,0.006192010000093506,0.013986702816730645,0.025003956956430873,0.03935464078941209,0.057190958417936644,0.07871533601238889,0.10419358352238339,0.1339745962155614,0.1685205807169019,0.20845517506805522,0.2546440075000701,0.3083389112228482,0.37146063894529113,0.4472292016074334,0.5418771527091488,0.6713289009389102,1], +out_circle:[0,0.3286710990610898,0.45812284729085123,0.5527707983925666,0.6285393610547089,0.6916610887771518,0.7453559924999298,0.7915448249319448,0.8314794192830981,0.8660254037844386,0.8958064164776166,0.9212846639876111,0.9428090415820634,0.9606453592105879,0.9749960430435691,0.9860132971832694,0.9938079899999065,0.9984555975339683,1], +inOut_circle:[0,0.003096005000046753,0.012501978478215436,0.028595479208968322,0.052096791761191696,0.08426029035845095,0.12732200375003505,0.18573031947264557,0.2709385763545744,0.5,0.7290614236454256,0.8142696805273546,0.8726779962499649,0.915739709641549,0.9479032082388084,0.9714045207910317,0.9874980215217846,0.9969039949999532,1], +in_back_:[0,-0.004788556241426612,-0.017301289437585736,-0.0347587962962963,-0.05438167352537723,-0.07339051783264748,-0.08900592592592595,-0.09844849451303156,-0.0989388203017833,-0.08769750000000004,-0.06194513031550073,-0.018902307956104283,0.044210370370370254,0.13017230795610413,0.2417629080932785,0.3817615740740742,0.5529477091906719,0.7581007167352535,0.9999999999999998], +out_back_:[2.220446049250313e-16,0.24189928326474652,0.44705229080932807,0.6182384259259258,0.7582370919067215,0.8698276920438959,0.9557896296296297,1.0189023079561044,1.0619451303155008,1.0876975,1.0989388203017834,1.0984484945130315,1.089005925925926,1.0733905178326475,1.0543816735253773,1.0347587962962963,1.0173012894375857,1.0047885562414267,1]}; + + +Object.keys(Samples).forEach(function(type){ +it('should ease '+type,function(){var _type$split= +type.split('_'),_type$split2=_slicedToArray(_type$split,3),modeName=_type$split2[0],easingName=_type$split2[1],isFunction=_type$split2[2]; +var easing=Easing[easingName]; +if(isFunction!==undefined){ +easing=easing(); +} +var computed=sampleEasingFunction(Easing[modeName](easing)); +var samples=Samples[type]; + +computed.forEach(function(value,key){ +expect(value).toBeCloseTo(samples[key],2); +}); +}); +}); +}); \ No newline at end of file diff --git a/lib/__tests__/Interpolation-test.js b/lib/__tests__/Interpolation-test.js new file mode 100644 index 0000000..9180703 --- /dev/null +++ b/lib/__tests__/Interpolation-test.js @@ -0,0 +1,297 @@ + + + + + + + + +'use strict'; + +jest. +dontMock('Interpolation'). +dontMock('Easing'). +dontMock('normalizeColor'); + +var Interpolation=require('Interpolation'); +var Easing=require('Easing'); + +describe('Interpolation',function(){ +it('should work with defaults',function(){ +var interpolation=Interpolation.create({ +inputRange:[0,1], +outputRange:[0,1]}); + + +expect(interpolation(0)).toBe(0); +expect(interpolation(0.5)).toBe(0.5); +expect(interpolation(0.8)).toBe(0.8); +expect(interpolation(1)).toBe(1); +}); + +it('should work with output range',function(){ +var interpolation=Interpolation.create({ +inputRange:[0,1], +outputRange:[100,200]}); + + +expect(interpolation(0)).toBe(100); +expect(interpolation(0.5)).toBe(150); +expect(interpolation(0.8)).toBe(180); +expect(interpolation(1)).toBe(200); +}); + +it('should work with input range',function(){ +var interpolation=Interpolation.create({ +inputRange:[100,200], +outputRange:[0,1]}); + + +expect(interpolation(100)).toBe(0); +expect(interpolation(150)).toBe(0.5); +expect(interpolation(180)).toBe(0.8); +expect(interpolation(200)).toBe(1); +}); + +it('should throw for non monotonic input ranges',function(){ +expect(function(){return Interpolation.create({ +inputRange:[0,2,1], +outputRange:[0,1,2]});}). +toThrow(); + +expect(function(){return Interpolation.create({ +inputRange:[0,1,2], +outputRange:[0,3,1]});}). +not.toThrow(); +}); + +it('should work with empty input range',function(){ +var interpolation=Interpolation.create({ +inputRange:[0,10,10], +outputRange:[1,2,3], +extrapolate:'extend'}); + + +expect(interpolation(0)).toBe(1); +expect(interpolation(5)).toBe(1.5); +expect(interpolation(10)).toBe(2); +expect(interpolation(10.1)).toBe(3); +expect(interpolation(15)).toBe(3); +}); + +it('should work with empty output range',function(){ +var interpolation=Interpolation.create({ +inputRange:[1,2,3], +outputRange:[0,10,10], +extrapolate:'extend'}); + + +expect(interpolation(0)).toBe(-10); +expect(interpolation(1.5)).toBe(5); +expect(interpolation(2)).toBe(10); +expect(interpolation(2.5)).toBe(10); +expect(interpolation(3)).toBe(10); +expect(interpolation(4)).toBe(10); +}); + +it('should work with easing',function(){ +var interpolation=Interpolation.create({ +inputRange:[0,1], +outputRange:[0,1], +easing:Easing.quad}); + + +expect(interpolation(0)).toBe(0); +expect(interpolation(0.5)).toBe(0.25); +expect(interpolation(0.9)).toBe(0.81); +expect(interpolation(1)).toBe(1); +}); + +it('should work with extrapolate',function(){ +var interpolation=Interpolation.create({ +inputRange:[0,1], +outputRange:[0,1], +extrapolate:'extend', +easing:Easing.quad}); + + +expect(interpolation(-2)).toBe(4); +expect(interpolation(2)).toBe(4); + +interpolation=Interpolation.create({ +inputRange:[0,1], +outputRange:[0,1], +extrapolate:'clamp', +easing:Easing.quad}); + + +expect(interpolation(-2)).toBe(0); +expect(interpolation(2)).toBe(1); + +interpolation=Interpolation.create({ +inputRange:[0,1], +outputRange:[0,1], +extrapolate:'identity', +easing:Easing.quad}); + + +expect(interpolation(-2)).toBe(-2); +expect(interpolation(2)).toBe(2); +}); + +it('should work with keyframes with extrapolate',function(){ +var interpolation=Interpolation.create({ +inputRange:[0,10,100,1000], +outputRange:[0,5,50,500], +extrapolate:true}); + + +expect(interpolation(-5)).toBe(-2.5); +expect(interpolation(0)).toBe(0); +expect(interpolation(5)).toBe(2.5); +expect(interpolation(10)).toBe(5); +expect(interpolation(50)).toBe(25); +expect(interpolation(100)).toBe(50); +expect(interpolation(500)).toBe(250); +expect(interpolation(1000)).toBe(500); +expect(interpolation(2000)).toBe(1000); +}); + +it('should work with keyframes without extrapolate',function(){ +var interpolation=Interpolation.create({ +inputRange:[0,1,2], +outputRange:[0.2,1,0.2], +extrapolate:'clamp'}); + + +expect(interpolation(5)).toBeCloseTo(0.2); +}); + +it('should throw for an infinite input range',function(){ +expect(function(){return Interpolation.create({ +inputRange:[-Infinity,Infinity], +outputRange:[0,1]});}). +toThrow(); + +expect(function(){return Interpolation.create({ +inputRange:[-Infinity,0,Infinity], +outputRange:[1,2,3]});}). +not.toThrow(); +}); + +it('should work with negative infinite',function(){ +var interpolation=Interpolation.create({ +inputRange:[-Infinity,0], +outputRange:[-Infinity,0], +easing:Easing.quad, +extrapolate:'identity'}); + + +expect(interpolation(-Infinity)).toBe(-Infinity); +expect(interpolation(-100)).toBeCloseTo(-10000); +expect(interpolation(-10)).toBeCloseTo(-100); +expect(interpolation(0)).toBeCloseTo(0); +expect(interpolation(1)).toBeCloseTo(1); +expect(interpolation(100)).toBeCloseTo(100); +}); + +it('should work with positive infinite',function(){ +var interpolation=Interpolation.create({ +inputRange:[5,Infinity], +outputRange:[5,Infinity], +easing:Easing.quad, +extrapolate:'identity'}); + + +expect(interpolation(-100)).toBeCloseTo(-100); +expect(interpolation(-10)).toBeCloseTo(-10); +expect(interpolation(0)).toBeCloseTo(0); +expect(interpolation(5)).toBeCloseTo(5); +expect(interpolation(6)).toBeCloseTo(5+1); +expect(interpolation(10)).toBeCloseTo(5+25); +expect(interpolation(100)).toBeCloseTo(5+95*95); +expect(interpolation(Infinity)).toBe(Infinity); +}); + +it('should work with output ranges as string',function(){ +var interpolation=Interpolation.create({ +inputRange:[0,1], +outputRange:['rgba(0, 100, 200, 0)','rgba(50, 150, 250, 0.4)']}); + + +expect(interpolation(0)).toBe('rgba(0, 100, 200, 0)'); +expect(interpolation(0.5)).toBe('rgba(25, 125, 225, 0.2)'); +expect(interpolation(1)).toBe('rgba(50, 150, 250, 0.4)'); +}); + +it('should work with output ranges as short hex string',function(){ +var interpolation=Interpolation.create({ +inputRange:[0,1], +outputRange:['#024','#9BF']}); + + +expect(interpolation(0)).toBe('rgba(0, 34, 68, 1)'); +expect(interpolation(0.5)).toBe('rgba(76.5, 110.5, 161.5, 1)'); +expect(interpolation(1)).toBe('rgba(153, 187, 255, 1)'); +}); + +it('should work with output ranges as long hex string',function(){ +var interpolation=Interpolation.create({ +inputRange:[0,1], +outputRange:['#FF9500','#87FC70']}); + + +expect(interpolation(0)).toBe('rgba(255, 149, 0, 1)'); +expect(interpolation(0.5)).toBe('rgba(195, 200.5, 56, 1)'); +expect(interpolation(1)).toBe('rgba(135, 252, 112, 1)'); +}); + +it('should work with output ranges with mixed hex and rgba strings',function(){ +var interpolation=Interpolation.create({ +inputRange:[0,1], +outputRange:['rgba(100, 120, 140, .4)','#87FC70']}); + + +expect(interpolation(0)).toBe('rgba(100, 120, 140, 0.4)'); +expect(interpolation(0.5)).toBe('rgba(117.5, 186, 126, 0.7)'); +expect(interpolation(1)).toBe('rgba(135, 252, 112, 1)'); +}); + +it('should work with negative and decimal values in string ranges',function(){ +var interpolation=Interpolation.create({ +inputRange:[0,1], +outputRange:['-100.5deg','100deg']}); + + +expect(interpolation(0)).toBe('-100.5deg'); +expect(interpolation(0.5)).toBe('-0.25deg'); +expect(interpolation(1)).toBe('100deg'); +}); + +it('should crash when chaining an interpolation that returns a string',function(){ +var interpolation=Interpolation.create({ +inputRange:[0,1], +outputRange:[0,1]}); + +expect(function(){interpolation('45rad');}).toThrow(); +}); + +it('should support a mix of color patterns',function(){ +var interpolation=Interpolation.create({ +inputRange:[0,1,2], +outputRange:['rgba(0, 100, 200, 0)','rgb(50, 150, 250)','red']}); + + +expect(interpolation(0)).toBe('rgba(0, 100, 200, 0)'); +expect(interpolation(0.5)).toBe('rgba(25, 125, 225, 0.5)'); +expect(interpolation(1.5)).toBe('rgba(152.5, 75, 125, 1)'); +expect(interpolation(2)).toBe('rgba(255, 0, 0, 1)'); +}); + +it('should crash when defining output range with different pattern',function(){ +expect(function(){return Interpolation.create({ +inputRange:[0,1], +outputRange:['20deg','30rad']});}). +toThrow(); +}); +}); \ No newline at end of file diff --git a/lib/bezier.js b/lib/bezier.js new file mode 100644 index 0000000..500d1a8 --- /dev/null +++ b/lib/bezier.js @@ -0,0 +1,105 @@ + + + + + + + + +var NEWTON_ITERATIONS=4; +var NEWTON_MIN_SLOPE=0.001; +var SUBDIVISION_PRECISION=0.0000001; +var SUBDIVISION_MAX_ITERATIONS=10; + +var kSplineTableSize=11; +var kSampleStepSize=1.0/(kSplineTableSize-1.0); + +var float32ArraySupported=typeof Float32Array==='function'; + +function A(aA1,aA2){return 1.0-3.0*aA2+3.0*aA1;} +function B(aA1,aA2){return 3.0*aA2-6.0*aA1;} +function C(aA1){return 3.0*aA1;} + + +function calcBezier(aT,aA1,aA2){return((A(aA1,aA2)*aT+B(aA1,aA2))*aT+C(aA1))*aT;} + + +function getSlope(aT,aA1,aA2){return 3.0*A(aA1,aA2)*aT*aT+2.0*B(aA1,aA2)*aT+C(aA1);} + +function binarySubdivide(aX,aA,aB,mX1,mX2){ +var currentX,currentT,i=0; +do{ +currentT=aA+(aB-aA)/2.0; +currentX=calcBezier(currentT,mX1,mX2)-aX; +if(currentX>0.0){ +aB=currentT; +}else{ +aA=currentT; +} +}while(Math.abs(currentX)>SUBDIVISION_PRECISION&&++i=NEWTON_MIN_SLOPE){ +return newtonRaphsonIterate(aX,guessForT,mX1,mX2); +}else if(initialSlope===0.0){ +return guessForT; +}else{ +return binarySubdivide(aX,intervalStart,intervalStart+kSampleStepSize,mX1,mX2); +} +} + +return function BezierEasing(x){ +if(mX1===mY1&&mX2===mY2){ +return x; +} + +if(x===0){ +return 0; +} +if(x===1){ +return 1; +} +return calcBezier(getTForX(x),mY1,mY2); +}; +}; \ No newline at end of file diff --git a/lib/createAnimatedComponent.js b/lib/createAnimatedComponent.js new file mode 100644 index 0000000..0ceac78 --- /dev/null +++ b/lib/createAnimatedComponent.js @@ -0,0 +1,108 @@ + + + + + + + + + + +'use strict';var _extends=Object.assign||function(target){for(var i=1;i1?_len2-1:0),_key2=1;_key2<_len2;_key2++){values[_key2-1]=arguments[_key2];} +return new AnimatedTemplate(strings,values); +}, + + + + +delay:delay, + + + + + +sequence:sequence, + + + + + +parallel:parallel, + + + + +stagger:stagger, + + + + + + + + + + + + + + + + + +event:event, + + + + + +isAnimated:isAnimated, + + + + +createAnimatedComponent:require('./createAnimatedComponent'), + +inject:{ +ApplyAnimatedValues:require('./injectable/ApplyAnimatedValues').inject, +InteractionManager:require('./injectable/InteractionManager').inject, +FlattenStyle:require('./injectable/FlattenStyle').inject, +RequestAnimationFrame:require('./injectable/RequestAnimationFrame').inject, +CancelAnimationFrame:require('./injectable/CancelAnimationFrame').inject}, + + +__PropsOnlyForTests:require('./AnimatedProps')}; \ No newline at end of file diff --git a/lib/injectable/ApplyAnimatedValues.js b/lib/injectable/ApplyAnimatedValues.js new file mode 100644 index 0000000..97ad115 --- /dev/null +++ b/lib/injectable/ApplyAnimatedValues.js @@ -0,0 +1,26 @@ + + + + + + + + + + +'use strict'; + +var ApplyAnimatedValues={ +current:function ApplyAnimatedValues(instance,props){ +if(instance.setNativeProps){ +instance.setNativeProps(props); +}else{ +return false; +} +}, +inject:function inject(apply){ +ApplyAnimatedValues.current=apply; +}}; + + +module.exports=ApplyAnimatedValues; \ No newline at end of file diff --git a/lib/injectable/CancelAnimationFrame.js b/lib/injectable/CancelAnimationFrame.js new file mode 100644 index 0000000..6c84db5 --- /dev/null +++ b/lib/injectable/CancelAnimationFrame.js @@ -0,0 +1,20 @@ + + + + + + + + + + +'use strict'; + +var CancelAnimationFrame={ +current:function current(id){return global.cancelAnimationFrame(id);}, +inject:function inject(injected){ +CancelAnimationFrame.current=injected; +}}; + + +module.exports=CancelAnimationFrame; \ No newline at end of file diff --git a/lib/injectable/FlattenStyle.js b/lib/injectable/FlattenStyle.js new file mode 100644 index 0000000..5a0a2ae --- /dev/null +++ b/lib/injectable/FlattenStyle.js @@ -0,0 +1,20 @@ + + + + + + + + + + +'use strict'; + +var FlattenStyle={ +current:function current(style){return style;}, +inject:function inject(flatten){ +FlattenStyle.current=flatten; +}}; + + +module.exports=FlattenStyle; \ No newline at end of file diff --git a/lib/injectable/InteractionManager.js b/lib/injectable/InteractionManager.js new file mode 100644 index 0000000..3e5a9df --- /dev/null +++ b/lib/injectable/InteractionManager.js @@ -0,0 +1,23 @@ + + + + + + + + + + +'use strict'; + +var InteractionManager={ +current:{ +createInteractionHandle:function createInteractionHandle(){}, +clearInteractionHandle:function clearInteractionHandle(){}}, + +inject:function inject(manager){ +InteractionManager.current=manager; +}}; + + +module.exports=InteractionManager; \ No newline at end of file diff --git a/lib/injectable/RequestAnimationFrame.js b/lib/injectable/RequestAnimationFrame.js new file mode 100644 index 0000000..653aff6 --- /dev/null +++ b/lib/injectable/RequestAnimationFrame.js @@ -0,0 +1,20 @@ + + + + + + + + + + +'use strict'; + +var RequestAnimationFrame={ +current:function current(cb){return global.requestAnimationFrame(cb);}, +inject:function inject(injected){ +RequestAnimationFrame.current=injected; +}}; + + +module.exports=RequestAnimationFrame; \ No newline at end of file diff --git a/lib/isAnimated.js b/lib/isAnimated.js new file mode 100644 index 0000000..e346e1b --- /dev/null +++ b/lib/isAnimated.js @@ -0,0 +1,19 @@ + + + + + + + + + + +'use strict'; + +var Animated=require('./Animated'); + +function isAnimated(obj){ +return obj instanceof Animated; +} + +module.exports=isAnimated; \ No newline at end of file diff --git a/lib/targets/react-dom.js b/lib/targets/react-dom.js new file mode 100644 index 0000000..d07ae86 --- /dev/null +++ b/lib/targets/react-dom.js @@ -0,0 +1,183 @@ + + + + + + + + + + +'use strict';var _extends=Object.assign||function(target){for(var i=1;i { + for (var key in this._listeners) { + this._listeners[key]({value: this.__getValue()}); + } + }) + } + if (!this._bListener && this._b.addListener) { + this._bListener = this._b.addListener(() => { + for (var key in this._listeners) { + this._listeners[key]({value: this.__getValue()}); + } + }) + } + var id = guid(); + this._listeners[id] = callback; + return id; + } + + removeListener(id: string): void { + delete this._listeners[id]; + } + + interpolate(config: InterpolationConfigType): AnimatedInterpolation { + return new AnimatedInterpolation(this, Interpolation.create(config)); + } + + __attach(): void { + this._a.__addChild(this); + this._b.__addChild(this); + } + + __detach(): void { + this._a.__removeChild(this); + this._b.__removeChild(this); + } +} + +module.exports = AnimatedMultiplication; diff --git a/src/index.js b/src/index.js index c65b515..45a02ac 100644 --- a/src/index.js +++ b/src/index.js @@ -16,6 +16,7 @@ var Animated = require('./Animated'); var AnimatedValue = require('./AnimatedValue'); var AnimatedValueXY = require('./AnimatedValueXY'); var AnimatedAddition = require('./AnimatedAddition'); +var AnimatedDivision = require('./AnimatedDivision'); var AnimatedMultiplication = require('./AnimatedMultiplication'); var AnimatedModulo = require('./AnimatedModulo'); var AnimatedTemplate = require('./AnimatedTemplate'); @@ -426,6 +427,13 @@ module.exports = { add: function add(a: Animated, b: Animated): AnimatedAddition { return new AnimatedAddition(a, b); }, + /** + * Creates a new Animated value composed from two Animated values divided + * together. + */ + divide: function multiply(a: Animated, b: Animated): AnimatedDivision { + return new AnimatedDivision(a, b); + }, /** * Creates a new Animated value composed from two Animated values multiplied * together.