Skip to content

Instantly share code, notes, and snippets.

@lsquaredleland
Last active August 14, 2016 08:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lsquaredleland/fa619bca6e4e327cebcf to your computer and use it in GitHub Desktop.
Save lsquaredleland/fa619bca6e4e327cebcf to your computer and use it in GitHub Desktop.
Isotype - Circle

#Isotype - Circles

Circle based isotypes with masking. Note: masking is done via covering with another element that has the same colour as the background rather than using a clip-path. While isotype does not actually represent the data correctly, as they are based off heigh rather than actual values.

###ToDo:

  • Try to make real isotypes (might be issues with scaling + deformation)
  • Try animations
  • Fix on hover issues
const dataSet1 = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,
11, 12, 15, 20, 18, 17, 16, 18, 23, 25, 10, 13, 16, 5, 2];
const w = 600;
const h = 450;
const stroke_width = 3;//can change, will auto scale
var svg = d3.select("#chart").append("svg")
.attr('width', w)
.attr('height', h)
const spacing = stroke_width/(w/dataSet1.length);
const xScale = d3.scale.ordinal()
.domain(d3.range(dataSet1.length))
.rangeRoundBands([0, w], spacing);
const yScale = d3.scale.linear()
.domain([0, d3.max(dataSet1) + 1])
.range([0, h]);
const colourScale = d3.scale.category20b();
var isotype = [];
var width_subtraction = 5
svg.selectAll("rect.base") //can be anything
.data(dataSet1)
.enter()
.append("rect")
.classed('base', true)
.attr('id', function(d, i){ return 'a'+i})
.attr({
x: function(d, i) { return xScale(i) + width_subtraction; },
y: function(d) { return h - yScale(d) - 20; },
width: xScale.rangeBand() - width_subtraction*2,
height: function(d){ return yScale(d); },
fill: 'maroon'
})//try making the bars horizontal??? interesting to try?
.each(function(d, i){ //data is all contained in isotype...is there a way to push it to rect's data?? So pull from rect???
isotype.push({
x: xScale(i),
y: h - yScale(d),
width: xScale.rangeBand(),
height: yScale(d),
fill: colourScale(d),
i: 'a' + i
})
});
drawCircle(isotype)
function drawCircle(lines){
for(i in lines){
var bar = lines[i];
for(var l = bar.y + bar.height - bar.width/2 - stroke_width; l > bar.y - bar.width/2; l = l - bar.width - stroke_width){
//would it be better to do base off value rather than the current way..Current way allows for funny scaling -> as circles are not
var x = bar.x + bar.width/2
var y = l
svg.append("circle")
.style('stroke', 'maroon')
.style('stroke-width', stroke_width)
.style("fill", bar.fill) //switch to 'colourScale(l)' if want to draw colours horizontal, rather than vertical
.attr('cx', x)
.attr('cy', y)
.attr('r', bar.width/2)
.attr('id', bar.i)
.classed('circle', true)
.on("mouseover", function(){
d3.selectAll('#' + this.id).filter('.circle').style('stroke', 'orange')
d3.selectAll('#' + this.id).filter('.base').style('fill', 'orange')
})
.on("mouseout", function(){
d3.selectAll('#' + this.id).filter('.circle').transition().duration(500).style('stroke', 'maroon')
d3.selectAll('#' + this.id).filter('.base').transition().duration(500).style('fill', 'maroon')
})
}
}
}
//fake clip path....
svg.selectAll("rect.mask")
.data(dataSet1)
.enter()
.append("rect")
.classed('mask', true)
.attr({
x: function(d, i) { return xScale(i) - stroke_width/2; },
y: function(d) { return h - yScale(d) - 30; },
width: xScale.rangeBand() + stroke_width,
height: function(d){ return 30; },
fill: 'white'
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Isotype - Circle</title>
<script src="https://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<div id="chart" style="border: 2px dashed black"></div>
</body>
<script src="chart.js"></script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment