D3 plot of the cantor distribution. The result is on bl.ocks.org
3 Jan 2018, Pablo Marcos
D3 plot of the cantor distribution. The result is on bl.ocks.org
3 Jan 2018, Pablo Marcos
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<link rel="stylesheet" type="text/css" href="style.css"> | |
<body> | |
<button type="button" onclick="animation()">Animation</button> | |
<div id="chart"> | |
<div class="svg-container"></div> | |
</div> | |
<script src="https://d3js.org/d3.v3.min.js"></script> | |
<script src="script.js"></script> | |
</body> |
/* | |
* Zoomable graph of the cantor's distribution function | |
* Modificated version of Matjaz Zeleznik code snippet | |
* https://jsfiddle.net/matjazzeleznik/hara70wa/ | |
* Uses d3.js v3 | |
*/ | |
var chartBody; | |
var clip; | |
var line; | |
var x; | |
var y; | |
var zoom; | |
var make_x_axis; | |
var make_y_axis; | |
var xAxis; | |
var yAxis; | |
var area; | |
var areaPath; | |
var width; | |
var height; | |
var margin; | |
var epsilon = .05; | |
var data = []; | |
/** | |
* Generates the points needed to interpolate the cantor's function, | |
* and stores them in the global variable 'data' | |
* @param {int} Number of iterations | |
*/ | |
function CantorDistibution(n) { | |
data = [{ x: 0, y: 0 }]; | |
CantorStep(1, n, 1./3., 0.5, 0,0); | |
data.push({ x: 1, y: 1 }); | |
} | |
function CantorStep(i,n, dx, dy, bx, by){ | |
if(i > n) return; | |
CantorStep(i+1, n, dx/3., dy/2., bx, by); | |
data.push({ x: bx + dx, y: by + dy}); | |
data.push({ x: bx + 2*dx, y: by + dy}); | |
CantorStep(i+1, n, dx/3., dy/2., bx + 2*dx, by + dy); | |
} | |
var counter; | |
function initAll() { | |
CantorDistibution(12); | |
initGraph(); | |
plotData(); | |
} | |
function animation() { | |
/* Clears all timeouts */ | |
var id = window.setTimeout(function() {}, 0); | |
while (id--) { | |
window.clearTimeout(id); | |
} | |
counter = 0; | |
animationTimer(); | |
} | |
function animationTimer() { | |
counter++; | |
CantorDistibution(counter); | |
plotData(); | |
if(counter < 12) { | |
setTimeout(animationTimer, 1000); | |
} | |
} | |
/** | |
* Plots the axis and an empty chart | |
* in the html element with id #chart | |
*/ | |
function initGraph() { | |
margin = { | |
top: 0, | |
right: 20, | |
bottom: 20, | |
left: 45 | |
}; | |
width = 600 - margin.left - margin.right; | |
height = 400 - margin.top - margin.bottom; | |
x = d3.scale.linear() | |
.domain(d3.extent(data, function(d) { | |
return d.x; | |
})) | |
.range([0, width]); | |
y = d3.scale.linear() | |
.domain([0, 1. + epsilon]) | |
.range([height, 0]); | |
line = d3.svg.line() | |
.interpolate('linear') | |
.x(function(d) { | |
return x(d.x); | |
}) | |
.y(function(d) { | |
return y(d.y); | |
}); | |
zoom = d3.behavior.zoom() | |
.x(x) | |
.y(y) | |
.on("zoom", zoomed); | |
svg = d3.select('#chart > .svg-container') | |
.append("svg:svg") | |
.attr("preserveAspectRatio", "xMinYMin meet") | |
.attr("viewBox", "0 0 600 400") | |
.classed("svg-content-responsive", true) | |
.append("svg:g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")") | |
.call(zoom); | |
svg.append("svg:rect") | |
.attr("width", width) | |
.attr("height", height) | |
.attr("class", "plot"); | |
make_x_axis = function() { | |
return d3.svg.axis() | |
.scale(x) | |
.orient("bottom") | |
.ticks(5); | |
}; | |
make_y_axis = function() { | |
return d3.svg.axis() | |
.scale(y) | |
.orient("left") | |
.ticks(5); | |
}; | |
xAxis = d3.svg.axis() | |
.scale(x) | |
.orient("bottom") | |
.ticks(5); | |
svg.append("svg:g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0, " + height + ")") | |
.call(xAxis); | |
yAxis = d3.svg.axis() | |
.scale(y) | |
.orient("left") | |
.ticks(5); | |
svg.append("g") | |
.attr("class", "y axis") | |
.call(yAxis) | |
.append("text") | |
.attr("transform", "rotate(-90)") | |
.attr("y", 6) | |
.attr("x", -5) | |
.attr("dy", ".71em") | |
.style("text-anchor", "end"); | |
svg.append("g") | |
.attr("class", "x grid") | |
.attr("transform", "translate(0," + height + ")") | |
.call(make_x_axis() | |
.tickSize(-height, 0, 0) | |
.tickFormat("")); | |
svg.append("g") | |
.attr("class", "y grid") | |
.call(make_y_axis() | |
.tickSize(-width, 0, 0) | |
.tickFormat("")); | |
clip = svg.append("svg:clipPath") | |
.attr("id", "clip") | |
.append("svg:rect") | |
.attr("x", 0) | |
.attr("y", 0) | |
.attr("width", width) | |
.attr("height", height); | |
chartBody = svg.append("g") | |
.attr("clip-path", "url(#clip)"); | |
} | |
function zoomed() { | |
svg.select(".x.axis").call(xAxis); | |
svg.select(".y.axis").call(yAxis); | |
svg.select(".x.grid") | |
.call(make_x_axis() | |
.tickSize(-height, 0, 0) | |
.tickFormat("")); | |
svg.select(".y.grid") | |
.call(make_y_axis() | |
.tickSize(-width, 0, 0) | |
.tickFormat("")); | |
svg.select(".line") | |
.attr("class", "line") | |
.attr("d", line); | |
svg.select("path.area").attr("d", area); | |
} | |
function plotData() { | |
svg.selectAll("path").remove(); | |
chartBody.append("svg:path") | |
.datum(data) | |
.attr("class", "line") | |
.attr("d", line); | |
area = d3.svg.area() | |
.interpolate('linear') | |
.x(function(d) { | |
return x(d.x); | |
}) | |
.y0(height) | |
.y1(function(d) { | |
return y(d.y); | |
}); | |
// Add the filled area | |
areaPath = chartBody.append("path") | |
.datum(data) | |
.attr("class", "area") | |
.attr("d", area); | |
} | |
initAll(); |
svg { | |
font-size: 11px; | |
} | |
.plot { | |
fill: #FFF; | |
} | |
.tick > text{ | |
fill: #414141; | |
font-weight: bold; | |
} | |
.area { | |
fill: lightsteelblue; | |
stroke-width: 0; | |
opacity:0.5; | |
} | |
.grid .tick { | |
stroke: lightgrey; | |
opacity: 0.7; | |
} | |
.grid path { | |
stroke-width: 0; | |
} | |
.axis path, .axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.line { | |
fill: none; | |
stroke: steelblue; | |
stroke-width: 1.5px; | |
} | |
.svg-content-responsive { | |
display: inline-block; | |
position: absolute; | |
top: 10px; | |
left: 0; | |
} | |
.svg-container { | |
display: inline-block; | |
position: relative; | |
width: 100%; | |
padding-bottom: 75%; | |
vertical-align: top; | |
overflow: hidden; | |
} | |
#chart { | |
width: 700px; | |
height: 512px; | |
} |
Result of the code snippet on bl.ocks.org