Draw a custom easing function in the white box on the left by clicking and dragging on it. When you let go the shapes on the right will be animated by converting the drawn path into an easing function with mojs and transitioned with d3.js
Built with blockbuilder.org
forked from enjalot‘s block: custom ease
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
#ease {
position: absolute;
top: 50px;
left: 50px;
width: 400px; height: 400px;
background-color: #eaf4fa;
}
#ease .container {
cursor: pointer;
}
#anim {
position: absolute;
top: 50px;
left: 520px;
width: 400px; height: 400px;
background-color: #eafaf2;
cursor: pointer;
}
path.ease {
fill: none;
stroke: #ff8e9d;
stroke-width: 5;
pointer-events: none;
}
.yaxis {
pointer-events: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.yaxis path {
fill: none;
stroke: #111;
}
</style>
</head>
<body>
<script src="//cdn.jsdelivr.net/mojs/latest/mo.min.js"></script>
<svg id="ease"></svg>
<svg id="anim"></svg>
<script>
var easesvg = d3.select("#ease");
var easeWidth = 400;
var easeHeight = 400;
var animsvg = d3.select("#anim");
var ey0 = 50;
var ey1 = 350;
var ex0 = 50;
var ex1 = 300;
var easeYscale = d3.scale.linear()
.range([ey1, ey0])
var easeXscale = d3.scale.linear()
.range([0, ex1])
var moEaseXScale = d3.scale.linear()
.range([0, 100])
var moEaseYScale = d3.scale.linear()
//.domain([ey1, ey0])
.range([0, 100])
var line = d3.svg.line()
.x(function(d) { return easeXscale(d.x) })
.y(function(d) { return ey1 - easeYscale(d.y) })
.interpolate("linear")
var lineEase = d3.svg.line()
.x(function(d) { return moEaseXScale(d.x) })
.y(function(d) { return moEaseYScale(d.y) })
// note: changed interpolation from "linear" to "basis" here
.interpolate("basis")
var points = [];
var drag = d3.behavior.drag()
.on("dragstart", function() {
points = [{
x: 0,
y: 1
}]
})
.on("drag", function() {
var x = (d3.mouse(this)[0]-ex0)/ex1;
var pm1 = points[points.length-1];
if(x < pm1.x) x = pm1.x+1;
if(x > 1) return;
var point = {
x: x,
y: (d3.mouse(this)[1]-ey0/2)/ey1
}
// TODO smooth?
points.push(point)
update();
})
.on("dragend", function() {
var pm1 = points[points.length-1];
if(pm1.x < 1) {
points.push({
x: 1,
y: pm1.y
})
}
update();
animate()
})
var yg = easesvg.append("g")
.classed("yaxis", true)
.attr("transform", "translate(50,0)")
var axis = d3.svg.axis()
.scale(easeYscale)
.orient("left")
.tickValues([0, 1])
yg.call(axis);
var easecontainer = easesvg.append("rect").classed("container", true)
.attr({
x: ex0,
y: ey0,
width: ex1,
height: ey1-ey0,
"fill-opacity": 0.5,
"fill": "#fff"
})
var path = easesvg.append("path")
.classed("ease", true)
.attr("transform", "translate(" + [ex0, ey0] + ")");
function update() {
path.datum(points)
.attr("d", line)
}
var rectStart = {
x: 50, y: ey1 - 25,
width: 50, height: 50,
fill: "#333"
}
var rectEnd = {
x: 50, y: ey0 - 25,
width: 50, height: 50
}
var circleStart = {
cx: 200,cy: 200, r: 5,
fill: "#312"
}
var circleEnd = {
cx: 200,cy: 200, r: 50,
fill: "#efe"
}
var rect = animsvg.append("rect")
.attr(rectStart)
var circle = animsvg.append("circle")
.attr(circleStart);
var easeLine = easesvg.append("line")
.attr({
x1: ex0, y1: ey0,
x2: ex0, y2: ey1,
stroke: "#111"
})
var duration = 1500;
var endDuration = 1000;
function animate() {
//we pass the svg line string to the mojs easing function creator
var ease = mojs.easing.path(lineEase(points));
console.log("0, 0.5, 1: ", ease(0), ease(0.5), ease(1))
rect.transition()
.duration(duration)
.ease(ease)
.attr(rectEnd)
.transition()
.duration(endDuration)
//.ease("linear")
.ease(ease)
.attr(rectStart)
circle.transition()
.duration(duration)
.ease(ease)
.attr(circleEnd)
.transition()
.duration(endDuration)
//.ease("linear")
.ease(ease)
.attr(circleStart)
easeLine.transition()
.duration(duration)
.ease("linear")
.attr({
x1: ex1+ex0, x2: ex1+ex0
})
.transition()
.duration(endDuration)
.ease("linear")
.attr({
x1: ex0, x2: ex0
})
}
animsvg.on("click", animate);
easecontainer.call(drag)
</script>
</body>