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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more