Published
Edited
Jul 17, 2020
Importers
Insert cell
md`# Animated Canvas Axis`
Insert cell
final_canvas4={
const height = 100;
const width = 800;
var transitionTime=500;
const ctx = DOM.context2d(width+100, height);
var dataArray=[12,15,25,38,45,51,64,87,92,112,234,345,456,567,678,789,899,999,1023,1123,1234,1345,1456,678,567,456,345,234,999];
var detachedContainer = document.createElement("custom");
var dataContainer = d3.select(detachedContainer);
function drawCustom(data) {
var allowedUnits=allowedAxisUnits(data);
var allowedUnitsDict=[];
allowedUnits.forEach(function(d){
allowedUnitsDict.push({"name":d.toString(),"value":d,"highest_value":data})
});
var dataBinding = dataContainer.selectAll("custom.ticks")
.data(allowedUnitsDict,d=>d.name);
dataBinding
.transition()
.ease(d3.easeLinear)
.duration(transitionTime)
.delay(index*transitionTime)
.attr("tickColor","rgba(252, 110, 34,0.9)")
.attr("x", function(d, i) {
return d.value;})
.attr("highest_val",d=>d.highest_value)
.attr("tickSize",7);
dataBinding
.enter()
.append("custom")
.classed("ticks", true)
.attr("tickColor","rgba(252, 110, 34,0)")
.attr("tickLabel",function(d, i) {
return d.value;
})
.attr("x", function(d, i) {
return d.value;
})
.attr("tickSize",7)
.attr("highest_val",d=>d.highest_value);
dataBinding.exit()
.transition()
.duration(transitionTime)
.delay(index*transitionTime)
//.attr("x",0)
.attr("tickColor","rgba(252, 110, 34,0)")
.remove();
}
function drawCanvas() {
// Wipe it all
ctx.fillStyle = "#fff";
ctx.rect(0,0,width+100,height);
ctx.fill();
// Draw Main Line
ctx.beginPath();
ctx.strokeStyle="black";
ctx.moveTo(axis_rectangle[0],axis_rectangle[1]);
ctx.lineTo(axis_rectangle[2],axis_rectangle[3]-tick_length);
ctx.stroke();
// Draw Ticks and Tick Labels
var elements = dataContainer.selectAll("custom.ticks");
elements.each(function(d) {
var node = d3.select(this);
var tick_len=parseFloat(node.attr("tickSize"));
var xVal=parseFloat(node.attr("x"));
// Ticks
var point=scaleLin(xVal,[0,parseFloat(node.attr("highest_val"))],[axis_rectangle[0],axis_rectangle[2]]);
ctx.beginPath();
ctx.strokeStyle=node.attr("tickColor");
ctx.moveTo(point+axis_rectangle[0],axis_rectangle[1]);
ctx.lineTo(point+axis_rectangle[0],axis_rectangle[1]+tick_len);
ctx.stroke();
// Tick Labels
ctx.fillStyle = node.attr("tickColor");
ctx.font = "14px Arial";
ctx.textAlign = "center";
ctx.fillText(node.attr("tickLabel"), point+axis_rectangle[0],axis_rectangle[1]+tick_len+15);
ctx.closePath();
})
};

d3.timer(drawCanvas);
for (var index = 0; index < dataArray.length; index++) {
drawCustom(dataArray[index]);
}
return ctx.canvas;
}
Insert cell
axis = {
const height = 100;
const width = 600;
const ctx = DOM.context2d(width, height);

const no_ticks=5;
const tick_width=1;
const tick_length=5;
var axis_rectangle=[0,50 - tick_length ,500, 50];
var count;
var axisFunction=function(){
// Draw Main Line
ctx.beginPath();
ctx.moveTo(axis_rectangle[0],axis_rectangle[1]);
ctx.lineTo(axis_rectangle[2],axis_rectangle[3]-tick_length);
ctx.stroke();
for(count=0;count<no_ticks; count++) {
ctx.beginPath();
ctx.moveTo(axis_rectangle[0],axis_rectangle[1]);
ctx.lineTo(axis_rectangle[0],axis_rectangle[1]+tick_length);
ctx.stroke();
};
};
axisFunction();
return ctx.canvas;
}
Insert cell
canvas={
const height = 100;
const width = 800;
const ctx = DOM.context2d(width, height);

const no_ticks=5;
const tick_width=1;
const tick_length=7;
var axis_rectangle=[30,50 - tick_length ,width-100, 50];
var data=[9,23,45,207,90];
var m=d3.max(data);
var d=no_ticks;
var u=m/d ;
var domain= [0,d3.max(data)];
var range= [axis_rectangle[0],axis_rectangle[2]]
var axis=function(){
// Draw Main Line
ctx.beginPath();
ctx.moveTo(axis_rectangle[0],axis_rectangle[1]);
ctx.lineTo(axis_rectangle[2],axis_rectangle[3]-tick_length);
ctx.stroke();
// Draw Ticks and Tick Labels
for(var count=0;count<=no_ticks; count++) {
// Ticks
ctx.beginPath();
var point=count*scaleLin(u,domain,range);
ctx.moveTo(point-(count-1)*axis_rectangle[0],axis_rectangle[1]);
ctx.lineTo(point-(count-1)*axis_rectangle[0],axis_rectangle[1]+tick_length);
ctx.stroke();
// Tick Labels
ctx.fillStyle = "rgba(252, 110, 34,0.9)";
ctx.font = "10px Arial";
ctx.textAlign = "center";
ctx.fillText(u*count, point-(count-1)*axis_rectangle[0],axis_rectangle[1]+tick_length+15);
};
};
axis();
return ctx.canvas;
}
Insert cell
scaleLin(206,[0,207],[10,700])
Insert cell
function scaleLin(value,domain,range){
var domainDiff=domain[1]-domain[0];
var rangeDiff=range[1]-range[0];
var ratio=rangeDiff/domainDiff ;
return range[0]+value*ratio ;
}
Insert cell
canvas2={
const height = 100;
const width = 800;
const ctx = DOM.context2d(width, height);

const no_ticks=5;
const tick_width=1;
const tick_length=7;
var axis_rectangle=[30,50 - tick_length ,width-100, 50];
var data=[9,23,45,407,90];
var m=d3.max(data);
var d=no_ticks;
var u=axisNiceUnit(m) ;
var domain= [0,d3.max(data)];
var range= [axis_rectangle[0],axis_rectangle[2]]
var axis=function(){
// Draw Main Line
ctx.beginPath();
ctx.moveTo(axis_rectangle[0],axis_rectangle[1]);
ctx.lineTo(axis_rectangle[2],axis_rectangle[3]-tick_length);
ctx.stroke();
// Draw Ticks and Tick Labels
for(var count=0;count<=no_ticks; count++) {
// Ticks
ctx.beginPath();
var point=count*scaleLin(u,domain,range);
ctx.moveTo(point-(count-1)*axis_rectangle[0],axis_rectangle[1]);
ctx.lineTo(point-(count-1)*axis_rectangle[0],axis_rectangle[1]+tick_length);
ctx.stroke();
// Tick Labels
ctx.fillStyle = "rgba(252, 110, 34,0.9)";
ctx.font = "10px Arial";
ctx.textAlign = "center";
ctx.fillText(u*count, point-(count-1)*axis_rectangle[0],axis_rectangle[1]+tick_length+15);
};
};
axis();
return ctx.canvas;
}
Insert cell
10**3
Insert cell
5*10**-4
Insert cell
firstDigitPower(58)
Insert cell
function firstDigitPower(n){
if (n<0){
n*=(-1);
}
var count = 0;
if (n>=1){
var n1=parseInt(n);
return n1.toString().length-1;
}
else {
while (n<1){
console.log(n);
count=count-1;
n=n*10;
}
return count;
}
}
Insert cell
function axisNiceUnit(n){
const f=firstDigitPower(n);
if (n<0.5*10**(f+1)){
return 1*10**f;
}
else{
return 2*10**f
}
}
Insert cell
axisNiceUnit(234)
Insert cell
canvas3={
const height = 100;
const width = 800;
var transitionTime=3000;
const ctx = DOM.context2d(width, height);

const no_ticks=5;
const tick_width=1;
const tick_length=7;
var axis_rectangle=[30,50 - tick_length ,width-100, 50];
var dataArray=[4,23,45,409,590];
var detachedContainer = document.createElement("custom");
var dataContainer = d3.select(detachedContainer);
function drawCustom(data) {
var allowedUnits=allowedAxisUnits(data);
var dataBinding = dataContainer.selectAll("custom.rect")
.data(allowedUnits);
dataBinding
.transition()
.ease(d3.easeLinear)
.duration(transitionTime)
.delay(index*transitionTime)
.attr("x", function(d, i) {
return d;});
dataBinding
.enter()
.append("custom")
.classed("rect", true)
.attr("x", function(d, i) {
return d;
})
dataBinding.exit()
.transition()
.duration(transitionTime)
.delay(index*transitionTime)
.attr("x", 0)
.remove();
}
function drawCanvas() {
// Wipe it all
ctx.fillStyle = "#fff";
ctx.rect(0,0,width,height);
ctx.fill();
// Draw Main Line
ctx.beginPath();
ctx.moveTo(axis_rectangle[0],axis_rectangle[1]);
ctx.lineTo(axis_rectangle[2],axis_rectangle[3]-tick_length);
ctx.stroke();
// Draw Ticks and Tick Labels
var elements = dataContainer.selectAll("custom.rect");
elements.each(function(d) {
var node = d3.select(this);
// Ticks
//var point=count*scaleLin(node.attr("x"),domain,range);
ctx.beginPath();
ctx.moveTo(node.attr("x")+axis_rectangle[0],axis_rectangle[1]);
ctx.lineTo(node.attr("x")+axis_rectangle[0],axis_rectangle[1]+tick_length);
ctx.stroke();
// Tick Labels
ctx.font = "10px Arial";
ctx.textAlign = "center";
ctx.fillText(node.attr("x"), node.attr("x")+axis_rectangle[0],axis_rectangle[1]+tick_length+15);
ctx.closePath();
})
};

d3.timer(drawCanvas);
for (var index = 0; index < dataArray.length; index++) {
drawCustom(dataArray[index]);
}
return ctx.canvas;
}
Insert cell
allowedAxisUnits(434)
Insert cell
function allowedAxisUnits(n){
var u=axisNiceUnit(n);
var returnArray=[];
var count=0;
while (u*count<=n){
returnArray.push(u*count);
count++;
}
returnArray.push(u*count);
count++
returnArray.push(u*count);
return returnArray;
}
Insert cell
allowedAxisUnits(523)
Insert cell
rdffsd={
var arr=[];
const darr=[490,234,523,845,409,190,680]
darr.forEach(function(d){
arr.push(allowedAxisUnits(d));
});
return arr;
}
Insert cell
Insert cell
canvas4={
const height = 100;
const width = 800;
var transitionTime=3000;
const ctx = DOM.context2d(width, height);
var dataArray=[12,112,234,345,456,567,678,789,678,567,456,345,234];
var detachedContainer = document.createElement("custom");
var dataContainer = d3.select(detachedContainer);
function drawCustom(data) {
var allowedUnits=allowedAxisUnits(data);
var allowedUnitsDict=[];
allowedUnits.forEach(function(d){
allowedUnitsDict.push({"name":d.toString(),"value":d,"highest_value":data})
});
var dataBinding = dataContainer.selectAll("custom.ticks")
.data(allowedUnitsDict,d=>d.name);
dataBinding
.transition()
.ease(d3.easeLinear)
.duration(transitionTime)
.delay(index*transitionTime)
.attr("tickColor","rgba(252, 110, 34,0.9)")
.attr("x", function(d, i) {
return d.value;})
.attr("highest_val",d=>d.highest_value)
.attr("tickSize",7);
dataBinding
.enter()
.append("custom")
.classed("ticks", true)
.attr("tickColor","rgba(252, 110, 34,0)")
.attr("tickLabel",function(d, i) {
return d.value;
})
.attr("x", function(d, i) {
return d.value;
})
.attr("tickSize",7)
.attr("highest_val",d=>d.highest_value);
dataBinding.exit()
.transition()
.duration(transitionTime)
.delay(index*transitionTime)
//.attr("x",0)
.attr("tickColor","rgba(252, 110, 34,0)")
.remove();
}
function drawCanvas() {
// Wipe it all
ctx.fillStyle = "#fff";
ctx.rect(0,0,width,height);
ctx.fill();
// Draw Main Line
ctx.beginPath();
ctx.strokeStyle="black";
ctx.moveTo(axis_rectangle[0],axis_rectangle[1]);
ctx.lineTo(axis_rectangle[2],axis_rectangle[3]-tick_length);
ctx.stroke();
// Draw Ticks and Tick Labels
var elements = dataContainer.selectAll("custom.ticks");
elements.each(function(d) {
var node = d3.select(this);
var tick_len=parseFloat(node.attr("tickSize"));
var xVal=parseFloat(node.attr("x"));
// Ticks
var point=scaleLin(xVal,[0,parseFloat(node.attr("highest_val"))],[axis_rectangle[0],axis_rectangle[2]]);
ctx.beginPath();
ctx.strokeStyle=node.attr("tickColor");
ctx.moveTo(point+axis_rectangle[0],axis_rectangle[1]);
ctx.lineTo(point+axis_rectangle[0],axis_rectangle[1]+tick_len);
ctx.stroke();
// Tick Labels
ctx.fillStyle = node.attr("tickColor");
ctx.font = "14px Arial";
ctx.textAlign = "center";
ctx.fillText(node.attr("tickLabel"), point+axis_rectangle[0],axis_rectangle[1]+tick_len+15);
ctx.closePath();
})
};

d3.timer(drawCanvas);
for (var index = 0; index < dataArray.length; index++) {
drawCustom(dataArray[index]);
}
return ctx.canvas;
}
Insert cell
tick_length=20;
Insert cell
axis_rectangle=[5,50 - tick_length ,width-100, 50];
Insert cell
axis_container=({'width':axis_rectangle[2]-axis_rectangle[0],
'height':axis_rectangle[3]-axis_rectangle[1]})
Insert cell
axis_container.height
Insert cell
// rerun the cell to see the animation

canvas6 = {
const height = 250;
const width = 1000;
const transitionTime=500;
const context = DOM.context2d(width, height);
var detachedContainer = document.createElement("custom");
var dataContainer = d3.select(detachedContainer);
function drawCustom(data) {
var dataBinding = dataContainer.selectAll("custom.rect")
.data(data);
dataBinding
.transition()
.ease(d3.easeLinear)
.duration(transitionTime)
.delay(index*transitionTime)
.attr("size", function(d, i) {
return d;});
dataBinding
.enter()
.append("custom")
.classed("rect", true)
.attr("x", function(d, i) {
return i * 200 + 100;
})
.attr("y", 100)
.attr("size", function(d, i) {
return d;}
)
.attr("fillStyle", "rgba(255, 170, 1,0.8)");
dataBinding.exit()
.transition()
.duration(transitionTime)
.delay(index*transitionTime)
.attr("size", 0)
.remove();
}
function drawCanvas() {
context.fillStyle = "#fff";
context.rect(0,0,width,height);
context.fill();
var elements = dataContainer.selectAll("custom.rect");
elements.each(function(d) {
var node = d3.select(this);
context.beginPath();
context.fillStyle = node.attr("fillStyle");
context.rect(node.attr("x"), node.attr("y"), 40, node.attr("size"));
context.fill();
context.closePath();
})
}

d3.timer(drawCanvas);
var dataArray = [
[10],
[35, 45, 23],
[80, 100,13,10,45],
[55, 70],
[20, 10,34],
[100,23],
];
for (var index = 0; index < dataArray.length; index++) {
drawCustom(dataArray[index]);
}
//drawCustom([1,7,13,20,23]);
//drawCustom([1,7,12,16,20]);


return context.canvas;
}
Insert cell
5-8
Insert cell
view={
var width = 800,
height = 40;

var data = [0,3.1];
// Append SVG
const svg= d3.create('svg')
.attr('viewBox',[0,0,width,height]);

// Create scale
var scale = d3.scaleLinear()
.domain([d3.min(data), d3.max(data)])
.range([0, width - 100])
.nice()
;

// Add scales to axis
var x_axis = d3.axisBottom()
.scale(scale);

//Append group and insert axis
svg.append("g")
.call(x_axis);
return svg.node();
}
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
d3=require('d3@5')
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more