Folding a 1-dimensional line with alternating creases (mountains and valleys).
xxxxxxxxxx
<meta charset="utf-8">
<style>
line {
stroke: rgba(0, 0, 0, 0.2);
fill: none;
stroke-width: 3px;
stroke-linecap: round;
}
circle {
stroke: 0.5px;
stroke: rgb(0, 0, 0);
}
</style>
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<body>
<svg width="960px" height="960px"></svg>
</body>
<script>
var svg = d3.select("svg"),
margin = { top: 20, left: 20, right: 20, bottom: 20},
width = 960,
height = 960,
radius = 3;
svg = svg.append("g")
.attr("transform", translate(margin.left, height / 2));
var X = d3.scaleLinear()
.domain([0, 1])
.range([0, width - margin.left - margin.right])
// Create random creases in a unit interval [0, 1].
var data = d3.range(d3.randomUniform(7, 12)() | 0).map((d, i, arr) => {
return d3.randomUniform()();
}).sort((a, b) => a - b).filter((d, i, arr) => {
// Ensure minimum distance between creases to avoid vertex overlaps.
return i === 0 || (X(d) - X(arr[i - 1]) > 3 * radius);
});
data = [0].concat(data).concat([1]);
var chain = svg;
// Create nested chain of groups.
for (let i = 0; i < data.length - 1; i++) {
chain = chain.selectAll("g")
.data([data[i]])
.enter().append("g")
.attr("transform", translate((i > 0 ? X(data[i] - data[i - 1]) : X(data[i])), 0))
.style("fill", (i % 2 === 0) ? "#FF0000" : "#0000FF")
chain.append("line")
.attr("x1", 0)
.attr("y1", 0)
.attr("y2", 0)
.attr("x2", X(data[i + 1]) - X(data[i]));
// The endpoints are not creases.
if (i > 0 && i < data.length - 1) {
chain.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", radius);
}
}
var stopped = false;
// Keep the segments centered in the viewport.
var timer = d3.timer(function() {
let bbox = svg.node().getBBox();
let center = [bbox.x + bbox.width / 2, bbox.y + bbox.height / 2];
svg.transition()
.ease(d3.easeLinear)
.duration(1000) // Provide a little hysteresis.
.attr("transform", (d, i) => {
return translate(width / 2 - center[0], height / 2 - center[1]);
});
if (stopped) timer.stop();
});
// Perform alternating pleated fold.
svg.select("g").selectAll("g")
.transition()
// .ease(d3.easeCubicOut)
.duration(5000)
.delay((d, i) => 1000 * (data.length - 2 - i))
.attr("transform", (d, i) => {
return translate((i > 0 ? X(data[i + 1] - data[i]) : X(data[i + 1])), 0)
+ rotate(180 * ((i % 2 === 0) ? 1 : -1));
})
.style("fill", "#000000")
.on("end", function(d, i) {
// First crease has finished folding.
if (i === 1) {
window.setTimeout(() => { stopped = true; }, 1000);
}
});
function translate(x, y) {
return "translate(" + x + "," + y + ")";
}
function rotate(degrees) {
return "rotate(" + degrees + ")";
}
</script>
https://d3js.org/d3.v4.min.js