|
<!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> |