Skip to content

Instantly share code, notes, and snippets.

@zanarmstrong
Last active November 20, 2015 19:21
Show Gist options
  • Save zanarmstrong/efd2d76e3455e9a35a51 to your computer and use it in GitHub Desktop.
Save zanarmstrong/efd2d76e3455e9a35a51 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

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="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("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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment