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' })