Related
I am using legends for d3 charts. Below is code -
var padding = { left:50, right:100, top:30, bottom:30 };
var legend = svgColorCode.selectAll(".legend")
.data(keyText) //.filter(x=>x!="Completed On Time")
.enter().append("g")
.attr("class", "legend")
.attr("transform", function (d, i) { return "translate(" + (((keys.length - (i)) * -25) + (i == 0 ? 0 : (i == 1 ? 60 : (i == 2 ? 90 : (i == 3 ? 100 : 0))))) + "," + (height - 190) + ")"; })
.attr("fill", function (d, i) { return colors[i]; });
legend.append("rect")
.attr("x", (x, i) => (padding.top * 2 + labHeight * (i)) + 40)
.attr("width", 18)
.attr("height", 18)
.style("fill", function (d, i) { return colors[operationalKeys[i]]; })
legend.append("text")
.attr("x", (x, i) => (padding.top * 2 + labHeight * i) + 60)
.attr("y", 9)
.attr("font-size", "0.65rem")
.attr("dy", ".35em")
.style("text-anchor", "start")
.text(function (d) { console.log("d");console.log(d); return d.replace(" ","\n"); })
.call(wrap)
;
Here I have long texts for legends and small place to accomodate it. I want to wrap the text for legends.
For that I followed this SO answer and used wrap method. But seems wrap is not working in this case.
How can I wrap my text for legends in d3 js?
This is my data : https://api.myjson.com/bins/b0m6s
I want to create a nested treemap that shows the parent element and the child elements inside it, like this example : https://bl.ocks.org/mbostock/911ad09bdead40ec0061
Here is my treemap code currently :
var defaultColors = d3.scale.ordinal().range(["#00AEEF", "#8DC63F", "#FFC20E", "#F06EAA", "#AE9986", "#009BA5", "#00A651", "#F7941D", "#B656AB", "#ABA000", "#F3716D", "#8D7B6B", "#EF413D", "#AD772B", "#878787"]);
var treemap;
var h_pad = 2, // 2 pixels vertical padding
v_pad = 4; // 4 pixels of horizontal padding (2 px at each side)
var canvas = d3
.select(id)
.append("svg")
.attr("class", "chart")
.attr("width", cfg.width + cfg.margin.left + cfg.margin.right)
.attr("height", cfg.height + cfg.margin.top + cfg.margin.bottom)
.attr("viewBox", "0 0 960 500")
.attr("preserveAspectRatio", "xMidYMid meet")
.attr("id", "canvas")
var innercanvas = canvas
.append("g")
.attr("class", "innercanvas")
.attr("transform", "translate(" + cfg.margin.left + "," + cfg.margin.top + ")");
treemap = d3.layout
.treemap()
.round(false)
.size([cfg.width, cfg.height])
.padding(.25)
.sticky(true)
.nodes(data);
var cells = innercanvas
.selectAll(".newcell")
.data(treemap)
.enter()
.append("g")
.attr("class", function (d, i) {
return 'newcell _' + i // i provides a unique identifier for each node
+ ' cell-level-' + d.depth // cell-level-0 for root, cell-level-1, cell-level-2, etc
+ (d.name ? ' ' + safe_name(d.name) : '') // if d.name exists, use the 'safe' version
+ (!d.children
? ' leaf' // d has no children => it's a leaf node
: (d.depth === 0
? ' root' // d.depth = 0 => it's the root node
: ' internal ')); // has children, depth > 0 => internal node
})
cells
.append("rect")
.attr("x", function (d) {
return d.x;
})
.attr("y", function (d) {
return d.y;
})
.attr("id", "rectangle")
.attr("width", function (d) {
return d.dx;
})
.attr("height", function (d) {
return d.dy;
})
.style("fill", function (d) {
return d.children && d.parent ? defaultColors(d.name) : cfg.color ? cfg.color(d.name) : null;
})
.attr("stroke", "#000000")
.attr('pointer-events', 'all');
cells
.append("text")
.attr("x", function (d) {
return d.x + d.dx / 2;
})
.attr("y", function (d) {
return d.y + d.dy / 2;
})
.attr("text-anchor", "middle")
.text(function (d) { return d.parent ? d.name : '' })
cells
.append('title')
.text(function (d) {
if (d.parent) {
return categoryKey + " : " + d.parent.name + "\n" + groupKey + " : " + d.name + "\n" + sizeKey + " : " + toCommas(d.value.toFixed(2))
}
return d.name;
});
Wrapping the texts into multiple lines
function groupAddText(selection) {
var v_pad = 2, // vertical padding
h_pad = 4 // horizontal padding
selection.selectAll('.leaf text')
.classed('groupOversize', function (d) {
if (!d.name) {
return false;
}
var bbox = this.getBBox();
if (d.dx <= bbox.width + h_pad || d.dy <= bbox.height + v_pad) {
d3.select(this).node().textContent = "";
var lines = wordwrap2(d.name, d.dx).split('\n');
for (var i = 0; i < lines.length; i++) {
d3.select(this)
.append("tspan")
.attr("dy", 15)
.attr("x", d.x + d.dx / 2)
.text(lines[i]);
}
d3.selectAll(".groupOversize").attr("y", function (d) {
return (d.y + d.dy / 2) - 20;
})
return true;
}
return false;
});
}
function wordwrap2(str, width, brk, cut) {
brk = brk || '\n';
width = width || 75;
cut = cut || false;
if (!str) { return str; }
var regex = '.{1,' + width + '}(\\s|$)' + (cut ? '|.{' + width + '}|.+$' : '|\\S+?(\\s|$)');
return str.match(RegExp(regex, 'g')).join(brk);
}
This produces the following treemap visualization :
As you can see, I separated my cells into 3 classes, root for the root node, internal for the parents and leaf for the children. Right now, it is just showing the children rects. How do I show the parent elements with the children nested inside them?
I want something like this :
[![enter image description here][2]][2]
You can view the parent cells by adding padding to your treemap:
treemap = d3.layout
.treemap()
.round(false)
.size([cfg.width, cfg.height])
.padding(20) // 20px padding all around
.sticky(true)
.nodes(data);
or
treemap = d3.layout
.treemap()
.round(false)
.size([cfg.width, cfg.height])
.padding([20,5,5,5]) // 20px top, 5px sides and bottom
.sticky(true)
.nodes(data);
I made a little demo showing the effects of altering the padding in a d3 treemap here - although note that that is d3 v5, so the options are slightly different.
Here's a demo with your code:
var data = {"children":[{"name":"Central","children":[{"name":"Cellophane Tape","value":"419141.4728"},{"name":"File Separator","value":"327285.0157"},{"name":"Hard Cover File","value":"422707.1194"},{"name":"Highlighter","value":"488978.5362"},{"name":"Office Chair","value":"453843.621"},{"name":"Pencil","value":"416819.1027"},{"name":"Tape Dispenser","value":"393290.5862"},{"name":"File Cabinet","value":"424647.6003"},{"name":"Plastic Comb Binding","value":"230299.6657"},{"name":"White Board Markers","value":"383157.5055"},{"name":"Binder","value":"415871.6793"},{"name":"Eraser","value":"477885.9162"},{"name":"Pen","value":"444834.4362"},{"name":"Pen Set","value":"434495.1303"},{"name":"Desk","value":"247046.3919"}]},{"name":"East","children":[{"name":"Pencil","value":"441970.1055"},{"name":"White Board Markers","value":"416822.5561"},{"name":"Eraser","value":"393738.4951"},{"name":"Hard Cover File","value":"407371.1911"},{"name":"Office Chair","value":"382574.6347"},{"name":"Tape Dispenser","value":"481960.7562"},{"name":"Cellophane Tape","value":"441438.7362"},{"name":"File Cabinet","value":"333187.8858"},{"name":"Binder","value":"462926.3793"},{"name":"File Separator","value":"441311.7555"},{"name":"Plastic Comb Binding","value":"330059.7762"},{"name":"Highlighter","value":"399332.0562"},{"name":"Pen","value":"492374.2362"},{"name":"Pen Set","value":"477206.7762"},{"name":"Desk","value":"254464.9453"}]},{"name":"North","children":[{"name":"Office Chair","value":"459306.6555"},{"name":"Pencil","value":"465763.0477"},{"name":"Eraser","value":"441687.1652"},{"name":"File Cabinet","value":"463598.5893"},{"name":"File Separator","value":"430346.1162"},
{"name":"Hard Cover File","value":"346325.0175"},{"name":"Highlighter","value":"223199.4072"},{"name":"Tape Dispenser","value":"311201.7216"},{"name":"Plastic Comb Binding","value":"445513.5762"},{"name":"Binder","value":"453219.921"},{"name":"White Board Markers","value":"334737.9189"},{"name":"Cellophane Tape","value":"372554.952"},{"name":"Pen","value":"435830.2872"},{"name":"Pen Set","value":"460001.8962"},{"name":"Desk","value":"260294.2303"}]},{"name":"South","children":[{"name":"Pencil","value":"457331.6055"},{"name":"Tape Dispenser","value":"442628.4555"},{"name":"Cellophane Tape","value":"468037.3351"},{"name":"Eraser","value":"341469.2127"},{"name":"File Cabinet","value":"408198.2058"},{"name":"File Separator","value":"416543.8893"},{"name":"Office Chair","value":"466438.7227"},{"name":"Plastic Comb Binding","value":"436440.1272"},{"name":"White Board Markers","value":"437968.1344"},{"name":"Highlighter","value":"411905.4555"},{"name":"Binder","value":"456806.1151"},{"name":"Hard Cover File","value":"493053.3762"},{"name":"Pen","value":"413820.3762"},{"name":"Pen Set","value":"488299.3962"},{"name":"Desk","value":"264499.5623"}]},{"name":"West","children":[{"name":"Pencil","value":"458648.3055"},{"name":"Cellophane Tape","value":"299045.7162"},{"name":"File Cabinet","value":"386045.352"},{"name":"File Separator","value":"435098.0403"},{"name":"Highlighter","value":"457454.0701"},{"name":"Office Chair","value":"262021.1055"},{"name":"Plastic Comb Binding","value":"413222.1555"},{"name":"Eraser","value":"449997.2978"},{"name":"Hard Cover File","value":"364335.5793"},{"name":"Binder","value":"467389.3801"},{"name":"Tape Dispenser","value":"394066.5845"},{"name":"White Board Markers","value":"408833.4789"},{"name":"Pen","value":"481281.6162"},{"name":"Pen Set","value":"398652.9162"},{"name":"Desk","value":"229482.2954"}]}]};
data.name = 'root'
var defaultColors = d3.scale.ordinal().range(["#00AEEF", "#8DC63F", "#FFC20E", "#F06EAA", "#AE9986", "#009BA5", "#00A651", "#F7941D", "#B656AB", "#ABA000", "#F3716D", "#8D7B6B", "#EF413D", "#AD772B", "#878787"]);
var treemap;
var h_pad = 2, // 2 pixels vertical padding
v_pad = 4; // 4 pixels of horizontal padding (2 px at each side)
var id = 'treemap';
var cfg = { width: 960, height: 500, margin: { left: 10, right: 10, bottom: 10, top: 10 }, color: d3.scale.category20() }
var canvas = d3
.select('#' + id)
.append("svg")
.attr("class", "chart")
.attr("width", cfg.width + cfg.margin.left + cfg.margin.right)
.attr("height", cfg.height + cfg.margin.top + cfg.margin.bottom)
.attr("viewBox", "0 0 960 500")
.attr("preserveAspectRatio", "xMidYMid meet")
.attr("id", "canvas")
var innercanvas = canvas
.append("g")
.attr("class", "innercanvas")
.attr("transform", "translate(" + cfg.margin.left + "," + cfg.margin.top + ")");
treemap = d3.layout
.treemap()
.round(false)
.size([cfg.width, cfg.height])
.padding([20,5,5,5])
.sticky(true)
.nodes(data);
var cells = innercanvas
.selectAll(".newcell")
.data(treemap)
.enter()
.append("g")
.attr("class", function (d, i) {
return 'newcell _' + i // i provides a unique identifier for each node
+ ' cell-level-' + d.depth // cell-level-0 for root, cell-level-1, cell-level-2, etc
+ (d.name ? ' ' + d.name : '') // if d.name exists, use the 'safe' version
+ (!d.children
? ' leaf' // d has no children => it's a leaf node
: (d.depth === 0
? ' root' // d.depth = 0 => it's the root node
: ' internal ')); // has children, depth > 0 => internal node
})
cells
.append("rect")
.attr("x", function (d) {
return d.x;
})
.attr("y", function (d) {
return d.y;
})
.attr("id", function(d,i){ return 'rect_' + i; })
.attr("width", function (d) {
return d.dx;
})
.attr("height", function (d) {
return d.dy;
})
.style("fill", function (d) {
return d.children && d.parent ? defaultColors(d.name) : cfg.color ? cfg.color(d.name) : null;
})
.attr("stroke", "#000000")
.attr('pointer-events', 'all');
cells.append("clipPath")
.attr("id", function(d,i) { return "clip_" + i ; })
.append("use")
.attr("xlink:href", function(d,i) {
return "#rect_" + i;
});
cells
.append("text")
.attr("clip-path", function(d,i) { return "url(#clip_" + i })
.attr("x", function (d) {
return d.x + d.dx / 2;
})
.attr("y", function (d) {
return d.children ? d.y + 12 : d.y + d.dy / 2 ;
})
.attr("text-anchor", "middle")
.text(function (d) { return d.name })
cells
.append('title')
.text(function (d) {
if (d.parent) {
return "categoryKey : " + d.parent.name + "\ngroupKey : " + d.name + "\nsizeKey : " + d.value.toFixed(2)
}
return d.name;
});
svg text {
font-size: 10px;
}
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script><div id="treemap"></div>
I'm very new to D3.js and I'm trying to learn how to put things together correctly. I have a day/hour heatmap based on this example here: http://bl.ocks.org/tjdecke/5558084
I'm trying to write an updateHeatMap method so that I can dynamically update the heatmap with new data. I've been researching and researching, and I honestly haven't found a successful solution. Any help would be appreciated, code snippets below
I have changed the original day/hour heatmap example slightly to look like this:
$scope.heatMapData = $http.get(...
$scope.initHeatMap = function() {
var margin = { top: 50, right: 0, bottom: 100, left: 30 },
width = 960 - margin.left - margin.right,
height = 430 - margin.top - margin.bottom,
gridSize = Math.floor(width / 24),
legendElementWidth = gridSize*2,
buckets = 9,
colors = ["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"], // alternatively colorbrewer.YlGnBu[9]
days = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
times = ["1a", "2a", "3a", "4a", "5a", "6a", "7a", "8a", "9a", "10a", "11a", "12a", "1p", "2p", "3p", "4p", "5p", "6p", "7p", "8p", "9p", "10p", "11p", "12p"];
$scope.colorScale = d3.scale.quantile()
.domain([0, buckets - 1, d3.max($scope.heatMapData, function (d) { return d.value; })])
.range(colors);
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var dayLabels = svg.selectAll(".dayLabel")
.data(days)
.enter().append("text")
.text(function (d) { return d; })
.attr("x", 0)
.attr("y", function (d, i) { return i * gridSize; })
.style("text-anchor", "end")
.attr("transform", "translate(-6," + gridSize / 1.5 + ")")
.attr("class", function (d, i) { return ((i >= 0 && i <= 4) ? "dayLabel mono axis axis-workweek" : "dayLabel mono axis"); });
var timeLabels = svg.selectAll(".timeLabel")
.data(times)
.enter().append("text")
.text(function(d) { return d; })
.attr("x", function(d, i) { return i * gridSize; })
.attr("y", 0)
.style("text-anchor", "middle")
.attr("transform", "translate(" + gridSize / 2 + ", -6)")
.attr("class", function(d, i) { return ((i >= 7 && i <= 16) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis"); });
var heatMap = svg.selectAll(".hour")
.data($scope.heatMapData)
.enter().append("rect")
.attr("x", function(d) { return (d.hour - 1) * gridSize; })
.attr("y", function(d) { return (d.day - 1) * gridSize; })
.attr("rx", 4)
.attr("ry", 4)
.attr("class", "hour bordered")
.attr("width", gridSize)
.attr("height", gridSize)
.style("fill", colors[0]);
heatMap.transition().duration(1000)
.style("fill", function(d) { return $scope.colorScale(d.value); });
heatMap.append("title").text(function(d) { return d.value; });
var legend = svg.selectAll(".legend")
.data([0].concat($scope.colorScale.quantiles()), function(d) { return d; })
.enter().append("g")
.attr("class", "legend");
legend.append("rect")
.attr("x", function(d, i) { return legendElementWidth * i; })
.attr("y", height)
.attr("width", legendElementWidth)
.attr("height", gridSize / 2)
.style("fill", function(d, i) { return colors[i]; });
legend.append("text")
.attr("class", "mono")
.text(function(d) { return "≥ " + Math.round(d); })
.attr("x", function(d, i) { return legendElementWidth * i; })
.attr("y", height + gridSize);
};
Here is what I have so far with the update method. This isn't working, because I'm not sure how to get the updated $scope.heatMapData into the new heatMap variable. I also need to update the legend to match the new color scale, but that's second in priority under this.
$scope.rowSelected() = function(){
$http.get(...).then(function(result){
$scope.heatMapData = result.data;
$scope.updateHeatMap();
});
}
$scope.updateHeatMap = function(){
var svg = d3.select("body").transition();
var heatMap = svg.selectAll(".hour")
.duration(250)
.attr("x", function(d) { return (d.hour - 1) * gridSize; })
.attr("y", function(d) { return (d.day - 1) * gridSize; })
.attr("rx", 4)
.attr("ry", 4)
.attr("class", "hour bordered")
.attr("width", gridSize)
.attr("height", gridSize)
.style("fill", colors[0]);
heatMap.transition().duration(1000)
.style("fill", function(d) { return colorScale(d.value); });
}
I am trying to add text to a working Marimekko chart. I understand that adding text to a rect requires that the rect and text need to be in a group. But the code I used as a base already uses a group. That is my main question, but I'd also like to make the x axes display the month rather than a %value.
Is this mission impossible for a marimekko chart?
<div id="chart"> </div>
<div id="legend"> </div>
<script>
var width = 800,
height = 500,
margin = 20;
var color = d3.scale.category10();
var x = d3.scale.linear()
.range([0, width - 3 * margin]);
var y = d3.scale.linear()
.range([0, height - 2 * margin]);
var n = d3.format(",d"),
p = d3.format("%");
var svg = d3.select("#chart") .append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + 2 * margin + "," + margin + ")");
d3.json("/mydrupal/sites/default/d3_files/json/marimekko6.json", function(error,data) {
var offset = 0;
// Nest values by month. We assume each month + cause is unique.
var months = d3.nest()
.key(function(d) {
return d.month;
})
.entries(data);
// Compute the total sum, the per-month sum, and the per-cause offset.
// You can use reduce rather than reduceRight to reverse the ordering.
// We also record a reference to the parent cause for each month.
var sum = months.reduce(function(v, p) {
return (p.offset = v) + (p.sum = p.values.reduceRight(function(v, d) {
d.parent = p;
return (d.offset = v) + d.deaths;
}, 0));
}, 0);
// Add x-axis ticks.
var xtick = svg.selectAll(".x")
.data(x.ticks(10))
.enter().append("g")
.attr("class", "x")
.attr("transform", function(d) {
return "translate(" + x(d) + "," + y(1) + ")";
});
xtick.append("line")
.attr("y2", 6)
.style("stroke", "#000");
xtick.append("text")
.attr("y", 8)
.attr("text-anchor", "middle")
.attr("dy", ".71em")
.text(p);
// Add y-axis ticks.
var ytick = svg.selectAll(".y")
.data(y.ticks(10))
.enter().append("g")
.attr("class", "y")
.attr("transform", function(d) {
return "translate(0," + y(1 - d) + ")";
});
ytick.append("line")
.attr("x1", -6)
.style("stroke", "#000");
ytick.append("text")
.attr("x", -8)
.attr("text-anchor", "end")
.attr("dy", ".35em")
.text(p);
// Add a group for each cause.
var months = svg.selectAll(".month")
.data(months)
.enter().append("g")
.attr("class", "month")
.attr("xlink:title", function(d) { return d.key; })
.attr("transform", function(d) {
return "translate(" + x(d.offset / sum) + ")";
});
// Add a rect for each month.
var causes = months.selectAll (".cause")
.data(function(d) { return d.values; })
.enter().append("a")
.attr("class", "month")
.attr("xlink:title", function(d) { return d.cause + " " + d.parent.key + ": " + n(d.deaths); })
.append("rect")
.attr("y", function(d) {
return y(d.offset / d.parent.sum); })
.attr("height", function(d) {
return y(d.deaths / d.parent.sum); })
.attr("width", function(d) {
return x(d.parent.sum / sum); })
.style("fill", function(d) {
return color(d.cause);
});
});
</script>
As noted above:
<!--HTML-->
<p>Marimekko Chart see http://bl.ocks.org/mbostock/1005090</p>
<div id="chart"> </div>
<!--CSS-->
<style type="text/css">body {
font: 10px sans-serif;
}
rect {
stroke: #000;
}
.label {
font-size: 12px;
fill: white;
}
.label2 {
font-size: 14px;
fill: black;
}
svg {
shape-rendering: crispEdges;
}
#chart {
margin-bottom: 20px;
}
</style>
<!--JavaScript-->
<script>
var width = 700,
height = 500,
margin = 20;
var color = d3.scale.category20();
var x = d3.scale.linear()
.range([0, width - 3 * margin]);
var y = d3.scale.linear()
.range([0, height - 2 * margin]);
var n = d3.format(",d"),
p = d3.format("%");
var svg = d3.select("#chart") .append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + 2 * margin + "," + margin + ")");
d3.json("/mydrupal/sites/default/d3_files/json/marimekko6.json", function(error,data) {
var offset = 0;
// Nest values by month. We assume each month + cause is unique.
var months = d3.nest()
.key(function(d) {
return d.month;
})
.entries(data);
// Compute the total sum, the per-month sum, and the per-cause offset.
// You can use reduce rather than reduceRight to reverse the ordering.
// We also record a reference to the parent cause for each month.
var sum = months.reduce(function(v, p) {
return (p.offset = v) + (p.sum = p.values.reduceRight(function(v, d) {
d.parent = p;
return (d.offset = v) + d.deaths;
}, 0));
}, 0);
// Add a group for each cause.
var months = svg.selectAll(".month")
.data(months)
.enter().append("g")
.attr("class", "month")
.attr("xlink:title", function(d) {
return d.key; })
.attr("transform", function(d) {
return "translate(" + x(d.offset / sum) + ")";
});
// Add a rect for each month.
var causes = months.selectAll (".cause")
.data(function(d) {
return d.values; })
.enter().append("a")
.attr("class", "month")
.attr("xlink:title", function(d) {
return d.cause + " " + d.parent.key + ": " + n(d.deaths); });
causes.append("rect")
.attr("y", function(d) {
return y(d.offset / d.parent.sum); })
.attr("height", function(d) {
return y(d.deaths / d.parent.sum); })
.attr("width", function(d) {
return x(d.parent.sum / sum); })
.style("fill", function(d) {
return color(d.cause);
});
// http://stackoverflow.com/questions/17574621/text-on-each-bar-of-a-stacked-bar-chart-d3-js
causes.append("text")
.text(function(d) {
return d.cause + " " + n(d.deaths);})
.attr("x", 5)
.attr("y", function(d) {
return (y(d.offset / d.parent.sum)+20); })
.attr("class", "label")
;
causes.append("text")
.text(function(d) {
return (" Total: " + d.parent.sum);}) // total
.attr("x", 5)
.attr("y", function(d) {
return 450 })
.attr("class", "label2")
;
causes.append("text")
.text(function(d) {
return d.parent.key;}) // month
.attr("x", 5)
.attr("y", function(d) {
return 480; })
.attr("class", "label2")
;
});
</script>
I have a http.server running on my 8888 port using python.
I am attempting to a load tsv file into the Day/Hour Heatmap:
[a link]http://bl.ocks.org/tjdecke/5558084#data.tsv
Note that both the data.tsv file and the code
The output below is what I'm seeing in my Chrome browser when navigating to the appropriate file. It is not loading the full amount of data.
(this is admittedly my first pass using D3)
<!DOCTYPE html>
<meta charset="utf-8">
<html>
<head>
<style>
rect.bordered {
stroke: #E6E6E6;
stroke-width:2px;
}
text.mono {
font-size: 9pt;
font-family: Consolas, courier;
fill: #aaa;
}
text.axis-workweek {
fill: #000;
}
text.axis-worktime {
fill: #000;
}
</style>
<script src="http://d3js.org/d3.v3.js"></script>
</head>
<body>
<div id="chart"></div>
<script type="text/javascript">
var margin = { top: 50, right: 0, bottom: 100, left: 30 },
width = 960 - margin.left - margin.right,
height = 430 - margin.top - margin.bottom,
gridSize = Math.floor(width / 24),
legendElementWidth = gridSize*2,
buckets = 9,
colors = ["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"], // alternatively colorbrewer.YlGnBu[9]
days = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"],
times = ["1a", "2a", "3a", "4a", "5a", "6a", "7a", "8a", "9a", "10a", "11a", "12a", "1p", "2p", "3p", "4p", "5p", "6p", "7p", "8p", "9p", "10p", "11p", "12p"];
d3.tsv("data.csv",
function(d) {
return {
day: +d.day,
hour: +d.hour,
value: +d.value
};
},
function(error, data) {
var colorScale = d3.scale.quantile()
.domain([0, buckets - 1, d3.max(data, function (d) { return d.value; })])
.range(colors);
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var dayLabels = svg.selectAll(".dayLabel")
.data(days)
.enter().append("text")
.text(function (d) { return d; })
.attr("x", 0)
.attr("y", function (d, i) { return i * gridSize; })
.style("text-anchor", "end")
.attr("transform", "translate(-6," + gridSize / 1.5 + ")")
.attr("class", function (d, i) { return ((i >= 0 && i <= 4) ? "dayLabel mono axis axis-workweek" : "dayLabel mono axis"); });
var timeLabels = svg.selectAll(".timeLabel")
.data(times)
.enter().append("text")
.text(function(d) { return d; })
.attr("x", function(d, i) { return i * gridSize; })
.attr("y", 0)
.style("text-anchor", "middle")
.attr("transform", "translate(" + gridSize / 2 + ", -6)")
.attr("class", function(d, i) { return ((i >= 7 && i <= 16) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis"); });
var heatMap = svg.selectAll(".hour")
.data(data)
.enter().append("rect")
.attr("x", function(d) { return (d.hour - 1) * gridSize; })
.attr("y", function(d) { return (d.day - 1) * gridSize; })
.attr("rx", 4)
.attr("ry", 4)
.attr("class", "hour bordered")
.attr("width", gridSize)
.attr("height", gridSize)
.style("fill", colors[0]);
heatMap.transition().duration(1000)
.style("fill", function(d) { return colorScale(d.value); });
heatMap.append("title").text(function(d) { return d.value; });
var legend = svg.selectAll(".legend")
.data([0].concat(colorScale.quantiles()), function(d) { return d; })
.enter().append("g")
.attr("class", "legend");
legend.append("rect")
.attr("x", function(d, i) { return legendElementWidth * i; })
.attr("y", height)
.attr("width", legendElementWidth)
.attr("height", gridSize / 2)
.style("fill", function(d, i) { return colors[i]; });
legend.append("text")
.attr("class", "mono")
.text(function(d) { return "≥ " + Math.round(d); })
.attr("x", function(d, i) { return legendElementWidth * i; })
.attr("y", height + gridSize);
});
</script>
</body>
</html>
The code looks right and since its exactly the way it is shown in the example, the problem might be with your data file.
Getting data only in the first grid means your x and y values are not getting properly rendered.
.attr("x", function(d) { return (d.hour - 1) * gridSize; })
.attr("y", function(d) { return (d.day - 1) * gridSize; })
Are the names day and hour correctly written? (even caps creates problem - something like Day and Hour instead of day and hour)
Hope this helps.