Partially an update to one of my previous blocks, the original intention here was to more clearly convey what is happening during the transitions between shapes by drawing lines from the vertices of the old shape to those of the new shapes.
It uses a kinda-sorta add-on I made called d3-shape-tween, which helps smoother transitions between complex shapes, especially when transitioning between shapes of varying complexity.
I also had some fun experimenting with rotating the shape as if it's on a turntable...
xxxxxxxxxx
<meta charset="utf-8">
<head>
<style>
div {
position:absolute
}
input[type=range][orient=vertical] {
writing-mode: bt-lr; /* IE */
-webkit-appearance: slider-vertical; /* WebKit */
width: 5px;
height: 400px;
margin-left: 50px;
margin-top: 50px;
}
span {
margin-left: 75px;
}
polygon {
fill-opacity: 0;
}
</style>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="shapes_test.js"></script>
<script src="//cdn.jsdelivr.net/gh/alexmacy/d3-shape-tween/shapetween.js"></script>
</head>
<body style="background-color:#343633">
<div>
<input type="range" id="slider" max=200 value=0 orient="vertical">
</div>
<div>
<h3><span id="sliderVal" style="color:#ecf0f1"></span></h3>
</div>
</body>
<script>
var width = Math.max(960, innerWidth),
height = Math.max(500, innerHeight);
d3.select("#slider")
.on("input", function() {
d3.select("#sliderVal").html("Revolutions per minute: " + this.value)
rotate(this.value)
})
d3.select("#sliderVal").html("Revolutions per minute: " + 0)
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width/2 + ", " + height/2 + ")rotate(0)scale(1.5)");
var startingShape = shapes[0]
var shape = svg.append("polygon")
.style("stroke", "#d35400")
.attr("points", startingShape)
var wires = svg.append("g").selectAll("line")
.data(startingShape)
.enter().append("line")
.style("stroke", "#2980b9")
.attr("x1", function(d) {return d[0]})
.attr("y1", function(d) {return d[1]})
.attr("x2", function(d) {return d[0]})
.attr("y2", function(d) {return d[1]})
var dots1 = svg.append("g").selectAll("circle")
.data(startingShape)
.enter().append("circle")
.style("fill", "#2980b9")
.attr("r", 1)
.attr("cx", function(d) {return d[0]})
.attr("cy", function(d) {return d[1]})
var dots2 = svg.append("g").selectAll("circle")
.data(startingShape)
.enter().append("circle")
.style("fill", "#d35400")
.attr("r", 1)
.attr("cx", function(d) {return d[0]})
.attr("cy", function(d) {return d[1]})
loop(startingShape, 1)
function loop(passedShape, n) {
var newShape = shapeTweenSides(passedShape, shapes[n], true);
wires.each(function(d, i) {
d3.select(this).transition().duration(2000).ease(d3.easeSinInOut)
.attr("x2", newShape[i][0])
.attr("y2", newShape[i][1])
.transition().duration(2500).ease(d3.easeSinInOut)
.attr("x1", newShape[i][0])
.attr("y1", newShape[i][1])
})
dots1.each(function(d, i) {
d3.select(this)
.transition().duration(2000).ease(d3.easeSinInOut)
.attr("cx", newShape[i][0])
.attr("cy", newShape[i][1])
})
dots2.each(function(d, i) {
d3.select(this)
.transition().delay(2000).duration(2500).ease(d3.easeSinInOut)
.attr("cx", newShape[i][0])
.attr("cy", newShape[i][1])
})
shape.interrupt().transition().delay(2000).duration(2500).ease(d3.easeSinInOut)
.attr("points", newShape)
.on("end", function() {
(n < shapes.length - 1) ? loop(newShape, ++n) : loop(newShape, 0);
});
}
function rotate(rpm) {
if (rpm == 0) {
svg.interrupt()
} else {
var newAngle = svg._groups[0][0].transform.animVal[1].angle + 120;
svg.transition().duration(20000/rpm).ease(d3.easeLinear)
.attr("transform", "translate(" + width/2 + ", " + height/2 + ")rotate(" + newAngle + ")scale(1.5)")
.on("end", function() {rotate(rpm)})
}
}
</script>
Updated missing url //cdn.rawgit.com/alexmacy/d3-shape-tween/master/shapeTween.js to //cdn.jsdelivr.net/gh/alexmacy/d3-shape-tween/shapetween.js
https://d3js.org/d3.v4.min.js
https://cdn.rawgit.com/alexmacy/d3-shape-tween/master/shapeTween.js