Skip to content

Instantly share code, notes, and snippets.

@nobitagit
Last active November 7, 2016 23:41
Show Gist options
  • Save nobitagit/6606b93f38d555e148827e6f46bb4f79 to your computer and use it in GitHub Desktop.
Save nobitagit/6606b93f38d555e148827e6f46bb4f79 to your computer and use it in GitHub Desktop.
ordinal vs quantize in D3.js
// https://jsfiddle.net/q6xk2hqv/
const data = [{
val: 4,
month: 1,
voters: 22,
name: 'A'
},{
val: 10,
month: 2,
voters: 12,
name: 'B'
},{
val: 21,
month: 3,
voters: 55,
name: 'C'
},{
val: 12,
month: 4,
voters: 33,
name: 'D'
},{
val: 22,
month: 5,
voters: 11,
name: 'E'
},{
val: 15,
month: 6,
voters: 29,
name: 'F'
},{
val: 19,
month: 7,
voters: 43,
name: 'G'
},{
val: 22,
month: 7,
voters: 3,
name: 'G'
},{
val: 12,
month: 8,
voters: 51,
name: 'G'
},{
val: 21,
month: 9,
voters: 21,
name: 'G'
},{
val: 33,
month: 10,
voters: 3,
name: 'G'
}];
const sel = d3.select('#chart')
var margin = {top: 40, right: 10, bottom: 20, left: 10};
var width = 460 - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
const fullWidth = width + margin.left + margin.right;
const fullHeight = height + margin.top + margin.bottom;
var svg = sel
.attr("width", fullWidth)
.attr("height", fullHeight)
//.attr('viewBox', `0 0 ${fullWidth} ${fullHeight}`)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
const xScale =
d3.scaleLinear()
.domain([0,d3.max(data, d => d.month)])
.range([0, width]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.val)])
.range([height, 0]);
const rScale = d3.scaleSqrt() // NB: => scale Square root to have the right scale of radius of bubbles
.domain([0, d3.max(data, d => d.voters)])
.range([0, 40]); // => how big we want our circles
var sequentialScale = d3.scaleSequential()
.domain([0, 55])
.interpolator(d3.interpolateViridis);
const bubbles = svg
.selectAll('.bubbles')
.data(data)
.enter()
.append('g')
.classed('bubbles', 1)
.attr('transform', d =>
`translate(${xScale(d.month)}, ${yScale(d.val)})`
)
bubbles
.append('circle')
.attr('cx', 0)
.attr('cy', 0)
.attr('r', d => rScale(d.voters))
.style('fill-opacity', 0.8)
.style('fill', d => sequentialScale(d.voters))
.exit()
const areaScale =
d3.area()
.x(d => xScale(d.month))
.y0(yScale(yScale.domain()[0])) // the lowest bound of the area is the bottom of our graph, or the min value of the domain (in this case it will be 0)
.y1(d => yScale(d.val)) // upper bound, the normal point where the data would be plotted
.curve(d3.curveCatmullRom.alpha(0.5))
svg
.append('path')
.classed('.areaG', 1)
.attr('d', areaScale(data))
.style('fill', 'rgb(34, 168, 132)')
.style('fill-opacity', 0.7)
.attr('stroke', 'steelblue')
.attr('stroke-width', 4)
//https://jsfiddle.net/kg8jfyn0/
// bar chart with rangeBand
const data = [{
val: 4,
name: 'A'
},{
val: 10,
name: 'B'
},{
val: 21,
name: 'C'
},{
val: 12,
name: 'D'
},{
val: 22,
name: 'E'
},{
val: 15,
name: 'F'
},{
val: 19,
name: 'G'
}];
const sel = d3.select('#chart')
var margin = {top: 40, right: 10, bottom: 20, left: 10};
var width = 460 - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
const fullWidth = width + margin.left + margin.right;
const fullHeight = height + margin.top + margin.bottom;
var svg = sel
.attr("width", fullWidth)
.attr("height", fullHeight)
//.attr('viewBox', `0 0 ${fullWidth} ${fullHeight}`)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
const scaleB =
d3.scaleBand()
.padding(0.2)
.align(0) // 0 is left aligned
.domain(data.map(o => o.name)) // notice: not an array of min + max as usual, but an array of all the plotted values
.range([0, width]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.val)])
.range([height, 0]);
var sequentialScale = d3.scaleSequential()
.domain([0, 10])
.interpolator(d3.interpolateMagma);
const gr = svg
.append('g')
.attr('transform', (d, i) => `translate(0, ${i * 33})`)
gr
.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr('x', d => scaleB(d.name))
.attr('y', d => yScale(d.val))
.attr('width', d => scaleB.bandwidth())
.attr('height', d => height - yScale(d.val))
// From the above code we can start plotting a bar chart
// that gets a discrete range of colors (in this case 5)
// see https://jsfiddle.net/gleezer/0hc0k4p4/
const data = [1,2,3,4,5,6,7,8,9];
const sel = d3.select('#chart')
const scaleOrd =
d3.scaleQuantize()
.domain([0,10])
.range(['#ff0000', '#ff6300', '#ffd900', '#a3ff00', '#00ff01']);
const gr = sel
.selectAll('g')
.data(data)
.enter()
.append('g')
// note, instead of incrementally translating each bar
// we translate each <g> group of bars
.attr('transform', (d, i) => `translate(0, ${i * 33})`)
gr
.append('rect')
.attr('width', d => d * 10)
.attr('height', 30)
.attr('fill', d => scaleOrd(d))
// d3 quantize scale
// From an ordinal domain maps to a discrete range according to its cardinality
// (so, "poor" is 1, "below average" is 2 ecc. forming a succession of values
// from low to high)
const scaleQ =
d3.scaleQuantize()
.domain([0,10])
.range(['poor', 'below average', 'average', 'good', 'excellent']);
[1,3,5,7,8,10].forEach(i => console.log(scaleQ(i)));
console.log(scaleQ.invertExtent('average'));
const scaleO =
d3.scaleOrdinal()
.domain(['poor', 'below average', 'average', 'good', 'excellent'])
.range(['#ff0000', '#ff6300', '#ffd900', '#a3ff00', '#00ff01']);
['poor', 'below average', 'average'].forEach(i => console.log(scaleQ(i)));
console.log(scaleQ.invertExtent('average'));
//https://jsfiddle.net/r5wv5nod/
const data = [{
val: 4,
month: 1,
voters: 22,
name: 'A'
},{
val: 10,
month: 2,
voters: 12,
name: 'B'
},{
val: 21,
month: 3,
voters: 55,
name: 'C'
},{
val: 12,
month: 4,
voters: 33,
name: 'D'
},{
val: 22,
month: 5,
voters: 11,
name: 'E'
},{
val: 15,
month: 6,
voters: 29,
name: 'F'
},{
val: 19,
month: 7,
voters: 43,
name: 'G'
},{
val: 22,
month: 7,
voters: 3,
name: 'G'
},{
val: 12,
month: 8,
voters: 51,
name: 'G'
},{
val: 21,
month: 9,
voters: 21,
name: 'G'
},{
val: 33,
month: 10,
voters: 3,
name: 'G'
}];
const sel = d3.select('#chart')
var margin = {top: 40, right: 10, bottom: 20, left: 10};
var width = 460 - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
const fullWidth = width + margin.left + margin.right;
const fullHeight = height + margin.top + margin.bottom;
var svg = sel
.attr("width", fullWidth)
.attr("height", fullHeight)
//.attr('viewBox', `0 0 ${fullWidth} ${fullHeight}`)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
const xScale =
d3.scaleLinear()
.domain([0,d3.max(data, d => d.month)])
.range([0, width]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.val)])
.range([height, 0]);
const rScale = d3.scaleSqrt() // NB: => scale Square root to have the right scale of radius of bubbles
.domain([0, d3.max(data, d => d.voters)])
.range([0, 40]); // => how big we want our circles
var sequentialScale = d3.scaleSequential()
.domain([0, 55])
.interpolator(d3.interpolateViridis);
const bubbles = svg
.selectAll('.bubbles')
.data(data)
.enter()
.append('g')
.classed('bubbles', 1)
.attr('transform', d =>
`translate(${xScale(d.month)}, ${yScale(d.val)})`
)
bubbles
.append('circle')
.attr('cx', 0)
.attr('cy', 0)
.attr('r', d => rScale(d.voters))
.style('fill-opacity', 0.8)
.style('fill', d => sequentialScale(d.voters))
.exit()
var line = d3.line()
.x(d => xScale(d.month))
.y(d => yScale(d.val))
.curve(d3.curveCatmullRom.alpha(0.5))
svg
.append('g')
.selectAll('.line')
.data(data)
.enter()
.append('path')
.attr('class', 'line')
.attr('d', d => {
return line(data)})
.style('stroke', 'steelblue')
.style('stroke-width', 2)
.style('fill', 'none')
.style('opacity', 0.3)
// see: http://jsfiddle.net/ramnathv/qpg286nh/
// and http://brendansudol.com/writing/responsive-d3
// see also: https://jsfiddle.net/ccnjowa2/
function responsivefy(svg) {
var container = d3.select(svg.node().parentNode),
width = parseInt(svg.style("width")),
height = parseInt(svg.style("height")),
aspect = width / height;
svg.attr("viewBox", "0 0 " + width + " " + height)
.attr("perserveAspectRatio", "xMinYMid")
.call(resize);
d3.select(window).on("resize." + container.attr("id"), resize);
function resize() {
var targetWidth = parseInt(container.style("width"));
svg.attr("width", targetWidth);
svg.attr("height", Math.round(targetWidth / aspect));
}
}
//https://jsfiddle.net/9ex4jz0c/1/
//========== VERSION 1 ================== //
const data = [{
val: 4,
month: 1,
voters: 22,
name: 'A'
},{
val: 10,
month: 2,
voters: 12,
name: 'B'
},{
val: 21,
month: 3,
voters: 55,
name: 'C'
},{
val: 12,
month: 4,
voters: 33,
name: 'D'
},{
val: 22,
month: 5,
voters: 11,
name: 'E'
},{
val: 15,
month: 6,
voters: 29,
name: 'F'
},{
val: 19,
month: 7,
voters: 43,
name: 'G'
},{
val: 22,
month: 7,
voters: 3,
name: 'G'
},{
val: 12,
month: 8,
voters: 51,
name: 'G'
},{
val: 21,
month: 9,
voters: 21,
name: 'G'
},{
val: 33,
month: 10,
voters: 3,
name: 'G'
}];
const sel = d3.select('#chart')
var margin = {top: 40, right: 10, bottom: 20, left: 10};
var width = 460 - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
const fullWidth = width + margin.left + margin.right;
const fullHeight = height + margin.top + margin.bottom;
var svg = sel
.attr("width", fullWidth)
.attr("height", fullHeight)
//.attr('viewBox', `0 0 ${fullWidth} ${fullHeight}`)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
const xScale =
d3.scaleLinear()
.domain([0,d3.max(data, d => d.month)])
.range([0, width]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.val)])
.range([height, 0]);
const rScale = d3.scaleSqrt() // NB: => scale Square root to have the right scale of radius of bubbles
.domain([0, d3.max(data, d => d.voters)])
.range([0, 40]); // => how big we want our circles
var sequentialScale = d3.scaleSequential()
.domain([0, 55])
.interpolator(d3.interpolateViridis);
const gr = svg
.append('g')
.attr('transform', (d, i) => `translate(0, ${i * 33})`)
gr
.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', d => xScale(d.month))
.attr('cy', d => yScale(d.val))
.attr('r', d => rScale(d.voters))
.style('fill-opacity', 0.8)
.style('fill', d => sequentialScale(d.voters))
// https://jsfiddle.net/xk49vx2w/
//========== VERSION 2 ================== //
// Same output as https://jsfiddle.net/9ex4jz0c/1/
// But the bubbles are within a graphics container each
const data = [{
val: 4,
month: 1,
voters: 22,
name: 'A'
},{
val: 10,
month: 2,
voters: 12,
name: 'B'
},{
val: 21,
month: 3,
voters: 55,
name: 'C'
},{
val: 12,
month: 4,
voters: 33,
name: 'D'
},{
val: 22,
month: 5,
voters: 11,
name: 'E'
},{
val: 15,
month: 6,
voters: 29,
name: 'F'
},{
val: 19,
month: 7,
voters: 43,
name: 'G'
},{
val: 22,
month: 7,
voters: 3,
name: 'G'
},{
val: 12,
month: 8,
voters: 51,
name: 'G'
},{
val: 21,
month: 9,
voters: 21,
name: 'G'
},{
val: 33,
month: 10,
voters: 3,
name: 'G'
}];
const sel = d3.select('#chart')
var margin = {top: 40, right: 10, bottom: 20, left: 10};
var width = 460 - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
const fullWidth = width + margin.left + margin.right;
const fullHeight = height + margin.top + margin.bottom;
var svg = sel
.attr("width", fullWidth)
.attr("height", fullHeight)
//.attr('viewBox', `0 0 ${fullWidth} ${fullHeight}`)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
const xScale =
d3.scaleLinear()
.domain([0,d3.max(data, d => d.month)])
.range([0, width]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.val)])
.range([height, 0]);
const rScale = d3.scaleSqrt() // NB: => scale Square root to have the right scale of radius of bubbles
.domain([0, d3.max(data, d => d.voters)])
.range([0, 40]); // => how big we want our circles
var sequentialScale = d3.scaleSequential()
.domain([0, 55])
.interpolator(d3.interpolateViridis);
const bubbles = svg
.selectAll('.bubbles')
.data(data)
.enter()
.append('g')
.classed('bubbles', 1)
.attr('transform', d =>
`translate(${xScale(d.month)}, ${yScale(d.val)})`
)
bubbles
.append('circle')
.attr('cx', 0)
.attr('cy', 0)
.attr('r', d => rScale(d.voters))
.style('fill-opacity', 0.8)
.style('fill', d => sequentialScale(d.voters))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment