text: function Point(a,b){this.x=a||0,this.y=b||0}function validateBezierPoint(a){return!!(a&&a.x>=0&&a.x<=1&&a.y<2&&a.y>-2)}function CompareBezier(a,b,c){if(!a)throw"Provide proper selector";if(this.canvas=$(a)[0],this.ctx=this.canvas.getContext("2d"),!validateBezierPoint(b))throw b+" is not valid";if(!validateBezierPoint(c))throw c+" is not valid";this.P0=b,this.P1=c,this.selector=a;var d=this;$(a).on("click",function(a){$(".cb-tick").hide(),$(this).next().show(),activeCompareCurve=d,plotPlayCurve()}),this.click=function(){$(this.selector).click()},this.draw=function(){this.ctx.canvas.width=this.ctx.canvas.width;var a=this.ctx.canvas.width,b=this.ctx.canvas.height;if(a!=b)throw a+" !="+b+" in compare bezier";var c=parseInt(this.P0.x*a),d=parseInt(this.P1.x*a),e=parseInt(this.P0.y>1?(1-this.P0.y)*a:this.P0.y<0?Math.abs(this.P0.y)*a+a:a-this.P0.y*a),f=parseInt(this.P1.y>1?(1-this.P1.y)*a:this.P1.y<0?Math.abs(this.P1.y)*a+a:a-this.P1.y*a);this.ctx.beginPath(),this.ctx.moveTo(0,a),this.ctx.bezierCurveTo(c,e,d,f,a,0),this.ctx.lineWidth=2,this.ctx.strokeStyle="rgba(255, 255, 255, 1)",this.ctx.stroke()}}function initPlot(a,b){context.canvas.width=context.canvas.width,context.fillStyle="rgba(0, 0, 0, 0.025)";for(var c=a/10,d=a+b-c,e=a/c-1;d>=b;d-=c,e-=1)5==e?context.fillStyle="rgba(55, 80, 190, 0.25)":context.fillStyle="rgba(100, 90, 90, 0.1)",context.fillRect(.5,d,a,1),context.fillRect(e*c-.5,b,1,a);context.fillRect(a-.5,b,1,a),context.moveTo(0,b),context.lineTo(0,a+b),context.lineTo(a+b,a+b),context.lineWidth=2,context.strokeStyle="rgba(0, 0, 0, 0.4)",context.stroke(),context.fillStyle="rgba(255,0,202,0.055)",context.beginPath();var f=$("#FP0").height()-2,g=$("#FP0").width()-2;context.moveTo(0,a+b-(g+f-5)),context.lineTo(a+b-(g+f-5),0),context.lineTo(a+b,Math.abs(f-g)),context.lineTo(Math.abs(f-g),a+b),context.closePath(),context.fill()}function plotCurve(a){var b=$("#P0").data(),c=$("#P1").data(),d=$("#cubic-bezier").width(),e=$("#cubic-bezier").height();if(d>e)throw"height is not greater than width";var f=(e-d)/2,g=$("#cubic-bezier").parent(),h=g.outerHeight(!0)-g.innerHeight(),i=g.outerWidth(!0)-g.innerWidth();initPlot(d,f);var j=e-2*f,k=+(1*(b.x-i)/d).toFixed(2),l=+((j-(b.y-h-f))/j).toFixed(2),m=+(1*(c.x-i)/d).toFixed(2),n=+((j-(c.y-h-f))/j).toFixed(2);$(".cb-x1").text(k),$(".cb-x2").text(m),$(".cb-y1").text(l),$(".cb-y2").text(n),window.history.replaceState({},"Cubic bezier curve generator","/cubic-bezier.html?x1="+k+"&y1="+l+"&x2="+m+"&y2="+n);$("#FP0").height()-2,$("#FP0").width()-2;context.beginPath(),context.moveTo(0,d+f),context.lineTo(b.x-i,b.y-h),context.closePath(),context.lineWidth=5,context.strokeStyle="deepskyblue",context.stroke(),context.beginPath(),context.moveTo(d,f),context.lineTo(c.x-i,c.y-h),context.closePath(),context.lineWidth=5,context.strokeStyle="rgba(50, 205, 149, 0.86)",context.stroke(),context.beginPath(),context.moveTo(0,d+f),context.bezierCurveTo(b.x-i,b.y-h,c.x-i,c.y-h,d,f),context.lineWidth=5,context.strokeStyle="deeppink",context.stroke();var o=d+h+f;$("#FP0").css("top",o+"px"),$("#FP0").css("left","0px");var p=h+f,q=d;$("#FP1").css("top",p+"px"),$("#FP1").css("left",q+"px"),timeDelay(a),animateBezier(k,l,m,n),plotPlayCurve()}function drag(a){var b=$(this).position(),c=b.top,d=b.left;$(this).data();$(this).data("x",d),$(this).data("y",c),plotCurve(a),clippy()}function getParameterByName(a){a=a.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var b=new RegExp("[\\?&]"+a+"=([^&#]*)"),c=b.exec(location.search);return null===c?"":decodeURIComponent(c[1].replace(/\+/g," "))}var canvas=document.getElementById("cubic-bezier"),context=canvas.getContext("2d"),animateCanvas=document.getElementById("animate-bezier"),animateContext=animateCanvas.getContext("2d"),playCanvas=document.getElementById("cubic-bezier-play"),playContext=playCanvas.getContext("2d"),playingAnimation=!1,compareCurves=[new CompareBezier("#linear",new Point(0,0),new Point(1,1)),new CompareBezier("#ease",new Point(.25,.1),new Point(.25,1)),new CompareBezier("#ease-in",new Point(.42,0),new Point(1,1)),new CompareBezier("#ease-in-out",new Point(.42,0),new Point(.58,1)),new CompareBezier("#ease-out",new Point(0,0),new Point(.58,1))],activeCompareCurve=compareCurves[0];Point.prototype.toString=function(){return"("+this.x+", "+this.y+")"};var drawCompareCurves=function(){_.each(compareCurves,function(a){a.draw()}),compareCurves[0].click()};CompareBezier.prototype.toString=function(){return"{"+this.p0+", "+p1+"}"};var movePointerRatio=function(){var a=$("#P0").position(),b=$("#P1").position(),c=$("#cubic-bezier"),d=c.width(),e=c.height(),f=(e-d)/2;return[{x:a.left/d,y:(a.top-f)/d},{x:b.left/d,y:(b.top-f)/d}]},coordinatesToPoints=function(a,b,c){var d=c.width(),e=c.height();if(d>e)throw"height is not greater than width";var f=(e-d)/2,g=c.parent(),h=(g.outerHeight(!0)-g.innerHeight(),g.outerWidth(!0)-g.innerWidth()),i=d-h;if(a.left>1||a.left<0||b.left>1||b.left<0)throw"x axis should be in a range [0,1]";var j=parseInt(a.left*i),k=parseInt(b.left*i),l=parseInt(a.top>1?(1-a.top)*d+f:a.top<0?Math.abs(a.top)*d+d+f:d-a.top*d+f),m=parseInt(b.top>1?(1-b.top)*d+f:b.top<0?Math.abs(b.top)*d+d+f:d-b.top*d+f);return[j,l,k,m]},drawPoints=function(a){if(!a||4!=a.length)throw"Invalid points: "+a;$("#P0").css("top",a[1]),$("#P0").css("left",a[0]),$("#P1").css("top",a[3]),$("#P1").css("left",a[2]),$("#P0").data("x",a[0]),$("#P0").data("y",a[1]),$("#P1").data("x",a[2]),$("#P1").data("y",a[3])},animateBezier=function(a,b,c,d){var e=animateContext.canvas.width,f=animateContext.canvas.height;if(e!=f)throw"w != h in animate bezier";animateContext.canvas.width=animateContext.canvas.width;var g=($("#animate-bezier"),_.map(movePointerRatio(),function(a){return{x:parseInt(a.x*e),y:parseInt(a.y*e)}}));animateContext.beginPath(),animateContext.moveTo(0,f),animateContext.bezierCurveTo(g[0].x,g[0].y,g[1].x,g[1].y,e,0),animateContext.lineWidth=2,animateContext.strokeStyle="rgba(255,255,255,1)",animateContext.stroke()},timeDelay=function(a){context.font="14px times",context.fillStyle="rgba(0, 0, 0, 0.4)";var b=a&&(a.offsetX||a.clientX-$(a.target).offset().left),c=a&&(a.offsetY||a.clientY-$(a.target).offset().top),d=context.canvas.width,e=context.canvas.height,f=(e-d)/2;if(a&&"mousemove"==a.type&&b&&c){var g=e-2*f,h=$("#cubic-bezier").parent(),i=h.outerHeight(!0)-h.innerHeight(),j=parseInt(100*+((g-(c-i-f))/g).toFixed(2)),k=parseInt(Math.ceil(b/d*100));context.fillText("DURATION("+k+"%)",d/3.5,d+f+30),context.fillText("TRANSITION("+j+"%)",d/3.5,f-10)}else context.fillText("DURATION",d/3.5,d+f+30),context.fillText("TRANSITION",d/3.5,f-10)},clippy=function(){var a=$(".cb-code").text().replace(/\s+/g," ").trim(),b=["-moz-","-o-","-webkit-",""],c=_.chain(b).map(function(b){return b+a+";\n"}).reduce(function(a,b){return a+b},"").value().trim();$(".cb-copy").attr("data-clipboard-text",c),$(".cb-copy").show()},initSlider=function(){$("#cb-slider").slider({animate:!0,min:1,max:100,value:10,handle:!0,slide:function(a,b){var c=b.value;$(".cb-duration").text(c/10+"s")}}).slider("pips",{rest:"label",suffix:"&#8243",formatLabel:function(a){return a%20===0?a/10+'<b class="seconds">'+this.suffix+"</b>":""}}).slider("float",{suffix:"s",formatLabel:function(a){return(a/10).toFixed(1)+this.suffix}})},plotPlayCurve=function(){if(!playingAnimation){var a=playContext.canvas.width,b=playContext.canvas.height;playContext.canvas.width=playContext.canvas.width;var c=(b-a)/2;playContext.fillStyle="rgba(0, 0, 0, 0.025)";for(var d=a/10,e=c,f=a+e-d,g=a/d-1;f>=e;f-=d,g-=1)5==g?playContext.fillStyle="rgba(55, 80, 190, 0.25)":playContext.fillStyle="rgba(100, 90, 90, 0.1)",playContext.fillRect(.5,f,a,1),playContext.fillRect(g*d-.5,e,1,a);playContext.fillRect(a-.5,e,1,a),playContext.beginPath(),playContext.moveTo(0,c),playContext.lineTo(0,a+c),playContext.lineTo(a,a+c),playContext.lineTo(a,c),playContext.closePath(),playContext.lineWidth=2,playContext.strokeStyle="darkgrey",playContext.stroke();var h=activeCompareCurve,i=parseInt(h.P0.x*a),j=parseInt(h.P1.x*a),k=parseInt(h.P0.y>1?(1-h.P0.y)*a+c:h.P0.y<0?Math.abs(h.P0.y)*a+a+c:a-h.P0.y*a+c),l=parseInt(h.P1.y>1?(1-h.P1.y)*a+c:h.P1.y<0?Math.abs(h.P1.y)*a+a+c:a-h.P1.y*a+c);playContext.beginPath(),playContext.moveTo(0,a+c),playContext.bezierCurveTo(i,k,j,l,a,c),playContext.lineWidth=5,playContext.strokeStyle="rgba(105, 105, 105, 0.3)",playContext.stroke();var m=_.map(movePointerRatio(),function(b){return{x:parseInt(b.x*a),y:parseInt(b.y*a)}});playContext.beginPath(),playContext.moveTo(0,a+c),playContext.bezierCurveTo(m[0].x,m[0].y+c,m[1].x,m[1].y+c,a,c),playContext.lineWidth=5,playContext.strokeStyle="rgba(50, 205, 149, 0.3)",playContext.stroke()}},cubicBezier={};cubicBezier.B1=function(a){return a*a*a},cubicBezier.B2=function(a){return 3*a*a*(1-a)},cubicBezier.B3=function(a){return 3*a*(1-a)*(1-a)},cubicBezier.B4=function(a){return(1-a)*(1-a)*(1-a)},cubicBezier.getBezier=function(a,b,c,d,e){var f=b.x*this.B1(a)+c.x*this.B2(a)+d.x*this.B3(a)+e.x*this.B4(a),g=b.y*this.B1(a)+c.y*this.B2(a)+d.y*this.B3(a)+e.y*this.B4(a);return{x:f,y:g}};var playAnimation=function(){plotPlayCurve(),playingAnimation=!0,$("#cb-compare").attr("disabled","disabled"),$("#cb-compare").css("opacity","0.5"),$("#cb-compare").css("cursor","not-allowed");var a=20*$("#cb-slider").slider("value"),b=0,c=playContext.canvas.width,d=playContext.canvas.height,e=(d-c)/2,f=_.map(movePointerRatio(),function(a){return{x:parseInt(a.x*c),y:parseInt(a.y*c)}}),g=activeCompareCurve,h=parseInt(g.P0.x*c),i=parseInt(g.P1.x*c),j=parseInt(g.P0.y>1?(1-g.P0.y)*c+e:g.P0.y<0?Math.abs(g.P0.y)*c+c+e:c-g.P0.y*c+e),k=parseInt(g.P1.y>1?(1-g.P1.y)*c+e:g.P1.y<0?Math.abs(g.P1.y)*c+c+e:c-g.P1.y*c+e),l=[{x:c,y:e},{x:i,y:k},{x:h,y:j},{x:0,y:c+e}],m=[{x:c,y:e},{x:f[1].x,y:f[1].y+e},{x:f[0].x,y:f[0].y+e},{x:0,y:c+e}],n=function(){if(b>a)clearInterval(o),$("#cb-compare").removeAttr("disabled"),$("#cb-compare").css("opacity","1"),$("#cb-compare").css("cursor","pointer"),playingAnimation=!1;else{var c=b/a;if(b>0){var d=(b-1)/a,e=cubicBezier.getBezier(c,m[0],m[1],m[2],m[3]),f=cubicBezier.getBezier(d,m[0],m[1],m[2],m[3]);playContext.beginPath(),playContext.quadraticCurveTo(f.x,f.y,e.x,e.y),playContext.strokeStyle="rgba(50, 205, 149, 1)",playContext.stroke();var g=cubicBezier.getBezier(c,l[0],l[1],l[2],l[3]),h=cubicBezier.getBezier(d,l[0],l[1],l[2],l[3]);playContext.beginPath(),playContext.quadraticCurveTo(h.x,h.y,g.x,g.y),playContext.strokeStyle="rgba(105, 105, 105, 1)",playContext.stroke()}b+=1}},o=setInterval(n,5)},drawInitialCurve=function(){var a,b=getParameterByName("x1"),c=getParameterByName("y1"),d=getParameterByName("x2"),e=getParameterByName("y2");a=b&&d&&validateBezierPoint(new Point(b,c))&&d&&e&&validateBezierPoint(new Point(d,e))?coordinatesToPoints({top:c,left:b},{top:e,left:d},$("#cubic-bezier")):coordinatesToPoints({top:.31,left:.74},{top:.8,left:.37},$("#cubic-bezier")),drawPoints(a)};$(function(){$("#cubic-bezier").on("mousemove",drag),$("#cubic-bezier").on("mouseout",drag),$("#P0, #P1").draggable({containment:"#cubic-bezier",scroll:!1,drag:drag,stop:drag,cancel:!1,stack:".curve-pointer"}),drawInitialCurve(),plotCurve(),$(".cb-code").on("mouseenter",clippy),ZeroClipboard.config({trustedDomains:["*"]});new ZeroClipboard($(".cb-copy"));drawCompareCurves(),initSlider(),$("#cb-compare").on("click",function(a){playAnimation()})});