Skip to content

Instantly share code, notes, and snippets.

@enjalot
Last active November 26, 2015 06:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save enjalot/2753c53ae396bb92727a to your computer and use it in GitHub Desktop.
Save enjalot/2753c53ae396bb92727a to your computer and use it in GitHub Desktop.
custom ease

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

<!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="http://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("cubic")
var lineEase = d3.svg.line()
.x(function(d) { return moEaseXScale(d.x) })
.y(function(d) { return moEaseYScale(d.y) })
.interpolate("cubic")
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment