console
var canvas = document.getElementById('curve'),
ctx = canvas.getContext('2d'),
box = document.getElementById('box'),
code = document.getElementById('codeOutput'),
supportsTouch = ('createTouch' in document),
time = document.getElementById('time'),
timeVal = 500;
var supportsBezierRange = (function() {
var el = document.createElement('div');
el.style.WebkitTransitionTimingFunction = 'cubic-bezier(1,0,0,1.1)';
return !! el.style.WebkitTransitionTimingFunction.length;
})();
function BezierHandle(x, y) {
this.x = x;
this.y = y;
this.width = 12;
this.height = 12;
}
BezierHandle.prototype = {
getSides: function() {
this.left = this.x - (this.width / 2);
this.right = this.left + this.width;
this.top = this.y - (this.height / 2);
this.bottom = this.top + this.height;
},
draw: function() {
this.getSides();
ctx.fillStyle = "#222";
ctx.fillRect(this.left, this.top, this.width, this.height);
}
};
var handles = [new BezierHandle(50, 280), new BezierHandle(150, 180)];
function Graph() {
this.x = 0;
this.y = 130;
this.height = 200;
this.width = 200;
}
Graph.prototype = {
draw: function() {
ctx.save();
ctx.fillStyle = "#fff";
ctx.fillRect(this.x, this.y, this.width, this.height);
ctx.strokeStyle = '#666';
ctx.lineWidth = 1;
ctx.strokeRect(this.x + 0.5, this.y - 0.5, this.width - 1, this.height);
ctx.restore();
}
};
var graph = new Graph();
function getPos(event) {
var mouseX = event.pageX - getOffSet(event.target).left,
mouseY = event.pageY - getOffSet(event.target).top;
return {
x: mouseX,
y: mouseY
};
}
function getOffSet(obj) {
var curleft = curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while ( obj = obj . offsetParent );
return {
left: curleft,
top: curtop
};
}
}
var drag = false,
draggingObj, oldX, oldY;
function onPress(event) {
event.preventDefault();
event.stopPropagation();
var cursorEvent = supportsTouch ? event.touches[0] : event;
var mouseCoordinates = getPos(cursorEvent),
x = mouseCoordinates.x,
y = mouseCoordinates.y;
for (var i = 0; i < handles.length; i++) {
var current = handles[i],
curLeft = current.left,
curRight = current.right,
curTop = current.top,
curBottom = current.bottom;
if (supportsTouch) {
curLeft -= 20;
curRight += 20;
curTop -= 20;
curBottom += 20;
}
if (x >= curLeft && x <= curRight && y >= curTop && y <= curBottom) {
draggingObj = current;
oldX = event.pageX;
oldY = event.pageY;
var currentlySelected = $('#presets option:selected');
currentlySelected.removeAttr('selected')
.parent().parent().find('option').last().attr('selected', 'selected');
document.addEventListener('mouseup', onRelease, false);
document.addEventListener('touchend', touchEnd, false);
document.addEventListener('mousemove', onMove, false);
document.addEventListener('touchmove', touchMove, false);
document.body.style.cursor = canvas.style.cursor = 'move';
}
}
}
function onMove(event) {
var cursorEvent = supportsTouch ? event.touches[0] : event;
var x = cursorEvent.pageX - getOffSet(canvas).left,
y = cursorEvent.pageY - getOffSet(canvas).top;
if (x > graph.width) {
x = graph.width;
}
if (x < 0) {
x = 0;
}
if (y > canvas.height) {
y = canvas.height;
}
if (y < 0) {
y = 0;
}
draggingObj.x = x;
draggingObj.y = y;
updateDrawing();
}
function touchMove(event) {
onMove(event);
event.preventDefault();
}
function onRelease(event) {
drag = false;
canvas.style.cursor = 'pointer';
document.body.style.cursor = 'default';
document.removeEventListener('mousemove', onMove, false);
document.removeEventListener('touchmove', touchMove, false);
document.removeEventListener('mouseup', onRelease, false);
document.removeEventListener('touchend', touchEnd, false);
}
function touchEnd(event) {
onRelease(event);
event.preventDefault();
}
canvas.addEventListener('mousedown', onPress, false);
canvas.addEventListener('touchstart', function touchPress(event) {
onPress(event);
event.preventDefault();
},
false);
function updateDrawing() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
graph.draw();
var cp1 = handles[0],
cp2 = handles[1];
ctx.save();
ctx.strokeStyle = '#4C84D3';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(graph.x, graph.y + graph.height);
ctx.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, graph.width, graph.y);
ctx.stroke();
ctx.restore();
ctx.strokeStyle = '#f00';
ctx.beginPath();
ctx.moveTo(graph.x, graph.y + graph.height);
ctx.lineTo(cp1.x, cp1.y);
ctx.moveTo(graph.width, graph.y);
ctx.lineTo(cp2.x, cp2.y);
ctx.stroke();
for (var i = 0; i < handles.length; i++) {
handles[i].draw();
}
var x1 = (cp1.x / graph.width).toFixed(3),
y1 = ((graph.height + graph.y - cp1.y) / graph.height).toFixed(3),
x2 = (cp2.x / canvas.width).toFixed(3),
y2 = ((graph.height + graph.y - cp2.y) / graph.height).toFixed(3),
points = '(' + x1 + ', ' + y1 + ', ' + x2 + ', ' + y2 + ')',
bezier = 'cubic-bezier' + points,
easeName = $('#presets option:selected').text();
if (easeName.indexOf('custom') > -1) {
easeName = 'custom';
}
var webkitTrans = '-webkit-transition: all ' + timeVal + 'ms ' + bezier;
var webkitTiming = '-webkit-transition-timing-function: ' + bezier;
if (y1 > 1 || y1 < 0 || y2 > 1 || y2 < 0) {
var webkitY1 = y1,
webkitY2 = y2;
if (y1 > 1) webkitY1 = 1;
if (y1 < 0) webkitY1 = 0;
if (y2 > 1) webkitY2 = 1;
if (y2 < 0) webkitY2 = 0;
webkitTrans = '-webkit-transition: all ' + timeVal + 'ms ' + 'cubic-bezier(' + x1 + ', ' + webkitY1 + ', ' + x2 + ', ' + webkitY2 + ')' + '; /* older webkit */' + '<br>-webkit-transition: all ' + timeVal + 'ms ' + bezier;
webkitTiming = '-webkit-transition-timing-function: cubic-bezier(' + x1 + ', ' + webkitY1 + ', ' + x2 + ', ' + webkitY2 + ')' + '; /* older webkit */' + '<br>-webkit-transition-timing-function: ' + bezier;
}
code.innerHTML = '<p>' + webkitTrans + '; <br> -moz-transition: all ' + timeVal + 'ms ' + bezier + '; <br> -o-transition: all ' + timeVal + 'ms ' + bezier + '; <br> transition: all ' + timeVal + 'ms ' + bezier + '; /* ' + easeName + ' */</p>' + '<p>' + webkitTiming + '; <br> -moz-transition-timing-function: ' + bezier + '; <br> -o-transition-timing-function: ' + bezier + '; <br> transition-timing-function: ' + bezier + '; /* ' + easeName + ' */</p>';
}
function setTransitions() {
var cp1 = handles[0],
cp2 = handles[1];
var x1 = (cp1.x / graph.width).toFixed(3),
y1 = ((graph.height + graph.y - cp1.y) / graph.height).toFixed(3),
x2 = (cp2.x / canvas.width).toFixed(3),
y2 = ((graph.height + graph.y - cp2.y) / graph.height).toFixed(3),
points = '(' + x1 + ', ' + y1 + ', ' + x2 + ', ' + y2 + ')';
timeVal = time.value;
box.style.WebkitTransition = box.style.MozTransition = box.style.MsTransition = box.style.OTransition = box.style.transition = 'all ' + timeVal + 'ms cubic-bezier' + points;
if (!supportsBezierRange) {
var wy1, wy2;
if (y1 > 1) wy1 = 1;
if (y1 < 0) wy1 = 0;
if (y2 > 1) wy2 = 1;
if (y2 < 0) wy2 = 0;
box.style.WebkitTransition = 'all ' + timeVal + 'ms cubic-bezier' + '(' + x1 + ', ' + wy1 + ', ' + x2 + ', ' + wy2 + ')';
}
}
function presetChange() {
var coordinates = this.value.split(','),
cp1 = handles[0],
cp2 = handles[1];
cp1.x = coordinates[0] * graph.width;
cp1.y = graph.y + graph.height - (coordinates[1] * graph.height);
cp2.x = coordinates[2] * graph.width;
cp2.y = graph.y + graph.height - (coordinates[3] * graph.height);
updateDrawing();
}
var $presets = $('#presets'),
$time = $('#time'),
$presetOpts = $('#presets option');
$presets.change(presetChange);
$('.testButton').click(function() {
setTransitions();
$('#box').toggleClass($(this).val());
});
$time.change(function() {
setTransitions();
updateDrawing();
});
$time.keyup(function() {
$(this).trigger('change');
});
$(document).keydown(function(event) {
var currentlySelected, currentIdx;
if (event.keyCode === 39 && event.target !== time) {
currentlySelected = $('#presets option:selected');
currentIdx = $presetOpts.index(currentlySelected);
if (currentIdx < $presetOpts.length - 1) {
currentlySelected.attr('selected', '');
$presetOpts.eq(currentIdx + 1).attr('selected', 'selected');
$presets.trigger('change');
}
} else if (event.keyCode === 37 && event.target !== time) {
currentlySelected = $('#presets option:selected');
currentIdx = $presetOpts.index(currentlySelected);
if (currentIdx > 0) {
currentlySelected.attr('selected', '');
$presetOpts.eq(currentIdx - 1).attr('selected', 'selected');
$presets.trigger('change');
}
}
});
setTransitions();
$presets.trigger('change');
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" type="text/css" href="./css/style.css"/>
</head>
<body>
<section class="demo">
<div class="controls clearfix">
<div class="graph">
<figure>
<canvas id="curve" width="200" height="450"></canvas>
</figure>
</div>
<div class="options">
<label for="presets"><span class="text">Easing:</span>
<select name="presets" id="presets">
<optgroup label="defaults">
<option value="0.250, 0.250, 0.750, 0.750" selected>linear</option>
<option value="0.250, 0.100, 0.250, 1.000">ease (default)</option>
<option value="0.420, 0.000, 1.000, 1.000">ease-in</option>
<option value="0.000, 0.000, 0.580, 1.000">ease-out</option>
<option value="0.420, 0.000, 0.580, 1.000">ease-in-out</option>
</optgroup>
<optgroup label="Penner Equations (approximated)">
<option value="0.550, 0.085, 0.680, 0.530">easeInQuad</option>
<option value="0.550, 0.055, 0.675, 0.190">easeInCubic</option>
<option value="0.895, 0.030, 0.685, 0.220">easeInQuart</option>
<option value="0.755, 0.050, 0.855, 0.060">easeInQuint</option>
<option value="0.470, 0.000, 0.745, 0.715">easeInSine</option>
<option value="0.950, 0.050, 0.795, 0.035">easeInExpo</option>
<option value="0.600, 0.040, 0.980, 0.335">easeInCirc</option>
<option value="0.600, -0.280, 0.735, 0.045">easeInBack</option>
<option value="0.250, 0.460, 0.450, 0.940">easeOutQuad</option>
<option value="0.215, 0.610, 0.355, 1.000">easeOutCubic</option>
<option value="0.165, 0.840, 0.440, 1.000">easeOutQuart</option>
<option value="0.230, 1.000, 0.320, 1.000">easeOutQuint</option>
<option value="0.390, 0.575, 0.565, 1.000">easeOutSine</option>
<option value="0.190, 1.000, 0.220, 1.000">easeOutExpo</option>
<option value="0.075, 0.820, 0.165, 1.000">easeOutCirc</option>
<option value="0.175, 0.885, 0.320, 1.275">easeOutBack</option>
<option value="0.455, 0.030, 0.515, 0.955">easeInOutQuad</option>
<option value="0.645, 0.045, 0.355, 1.000">easeInOutCubic</option>
<option value="0.770, 0.000, 0.175, 1.000">easeInOutQuart</option>
<option value="0.860, 0.000, 0.070, 1.000">easeInOutQuint</option>
<option value="0.445, 0.050, 0.550, 0.950">easeInOutSine</option>
<option value="1.000, 0.000, 0.000, 1.000">easeInOutExpo</option>
<option value="0.785, 0.135, 0.150, 0.860">easeInOutCirc</option>
<option value="0.680, -0.550, 0.265, 1.550">easeInOutBack</option>
</optgroup>
<optgroup label="custom">
<option value="0.500, 0.250, 0.500, 0.750">custom (drag the handles)</option>
</optgroup>
</select>
</label>
<label for="time"><span class="text">Duration:</span>
<input type="number" step="100" value="500" size="7" maxlength="4" pattern="[0-9]*" name="time" value="time" id="time">
</label>
<label for="buttons"><span class="text">Effect:</span><br />
<input type="button" name="left" value="left" id="left" class="testButton">
<input type="button" name="width" value="width" id="width" class="testButton">
<input type="button" name="height" value="height" id="height" class="testButton">
<input type="button" name="opacity" value="opacity" id="opacity" class="testButton">
</label>
<div class="anim">
<div id="box">
</div>
</div>
</div>
</div>
</section>
<div id="codeOutput" style="float: left;width: 100%;"></div>
<script src="../js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script>
<script src="./js/common.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
canvas {
display: block;
cursor: pointer;
}
.demo {
padding: 0 0 30px 0;
border-top: 1px solid #F0EFEB;
}
.controls {
border-bottom: 1px solid #fff;
}
.graph {
float: left;
margin-left: -20px;
}
canvas {
display: block;
cursor: pointer;
}
figure {
display: block;
position: relative;
padding-left: 20px;
width: 200px;
}
figcaption {
display: block;
position: absolute;
}
#axisAnimation {
left: -33px;
top: 210px;
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
transform: rotate(-90deg);
}
#axisTime {
left: 100px;
top: 335px;
}
.options {
margin-top: 130px;
margin-left: 30px;
width: 300px;
float: left;
}
label {
display: block;
margin-bottom: 10px;
}
label .text {
display: inline-block;
width: 60px;
}
.options input[type="button"] {
width: 100px;
font-size: 15px;
color: #454545;
text-shadow: 0 -1px 0 #51c0e3, 0 1px 0 rgba(255, 255, 255, 0.22);
text-transform: capitalize;
padding: 5px;
margin-right: 5px;
border: none;
-webkit-border-radius: 50px;
-moz-border-radius: 50px;
border-radius: 50px;
-webkit-box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.65);
-moz-box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.65);
-ms-box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.65);
-o-box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.65);
box-shadow: 0px 0px 2px #00c2ff;
background: #F3F2EA;
background: -moz-linear-gradient(top, #F3F2EA 0%, #A39F5F 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #51c0e3));
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#F3F2EA', endColorstr='#A39F5F', GradientType=0);
outline: none;
margin-top: 10px;
}
.options input[type="button"]:active {
text-shadow: 0 -1px 0 rgba(255, 255, 255, 0.22), 0 1px 0 rgba(0, 0, 0, 0.40);
-webkit-box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.65);
-moz-box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.65);
-ms-box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.65);
-o-box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.65);
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.65);
background: #F3F2EA;
background: -moz-linear-gradient(top, #029ccc 0%, #F3F2EA 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #029ccc), color-stop(100%, #F3F2EA));
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#029ccc', endColorstr='#F3F2EA', GradientType=0);
}
.anim {
background: repeat-y top left, repeat-y top right;
}
#box {
width: 100px;
height: 100px;
background: #00c2ff no-repeat center center;
position: relative;
margin-top: 3px;
left: 0px;
opacity: 1;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
-webkit-transform: translateZ(0);
-moz-transform: translateZ(0);
-ms-transform: translateZ(0);
-o-transform: translateZ(0);
transform: translateZ(0);
}
#box.left {
left: 460px;
}
#box.opacity {
opacity: 0;
}
#box.width {
width: 560px;
}
#box.height {
height: 560px;
}
#snippets {
clear: both;
border-top: 1px solid #F0EFEB;
padding-top: 15px;
}
#codeOutput {
font-family: Courier, monospace;
}
#donate {
margin-top: 20px;
}
#donate .donation {
display: inline-block;
text-align: center;
text-decoration: none;
width: 87px;
font-size: 14px;
margin: 0 3px;
color: #454545;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.40), 0 1px 0 rgba(255, 255, 255, 0.22);
text-transform: capitalize;
padding: 4px;
border: none;
-webkit-border-radius: 50px;
-moz-border-radius: 50px;
border-radius: 50px;
-webkit-box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.65);
-moz-box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.65);
-ms-box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.65);
-o-box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.65);
box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.65);
background: #EFF2EA;
background: -moz-linear-gradient(top, #EFF2EA 0%, #9BAF7E 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #EFF2EA), color-stop(100%, #9BAF7E));
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#EFF2EA', endColorstr='#9BAF7E', GradientType=0);
position: relative;
}
#donate .donation:active {
text-shadow: 0 -1px 0 rgba(255, 255, 255, 0.22), 0 1px 0 rgba(0, 0, 0, 0.40);
-webkit-box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.65);
-moz-box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.65);
-ms-box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.65);
-o-box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.65);
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.65);
background: #9BAF7E;
background: -moz-linear-gradient(top, #9BAF7E 0%, #EFF2EA 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #9BAF7E), color-stop(100%, #EFF2EA));
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#9BAF7E', endColorstr='#EFF2EA', GradientType=0);
}
#resources {
padding-bottom: 30px;
}
#resources li {
margin-bottom: 4px;
}
#needs {
margin-bottom: 35px;
}
#oldBrowser {
display: none;
visibility: hidden;
}
.no-csstransitions #oldBrowser {
display: block;
visibility: visible;
position: absolute;
top: 130px;
background-color: rgba(0, 0, 0, 0.8);
font-size: 25px;
color: #fff;
text-align: center;
width: 100%;
padding: 20px 0;
}