Reputation: 283
I'm trying to flip a graph in JS without changing the axis. JavaScript isn't my specialty and after googling for 4 hours I'm starting to think it isn't possible. Can someone point me in the right direction please?
var width = 960,
height = 500;
d3.json("data2.json", function(error, heatmap) {
var dx = heatmap[0].length,
dy = heatmap.length;
// Fix the aspect ratio.
// var ka = dy / dx, kb = height / width;
// if (ka < kb) height = width * ka;
// else width = height / ka;
var x = d3.scale.linear()
.domain([0, dx])
.range([0, width]);
var y = d3.scale.linear()
.domain([0, dy])
.range([height, 0]);
var color = d3.scale.linear()
.domain([null, 0, 30, 60, 90, 120])
.range(["#FFFFFF", "#FF0000", "#FF9933", "#FFFF00", "#99FF33", "#00FF00"]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("top")
.ticks(20);
var yAxis = d3.svg.axis()
.scale(y)
.orient("right");
d3.select("body").append("canvas")
.attr("width", dx)
.attr("height", dy)
.style("width", width + "px")
.style("height", height + "px")
.call(drawImage);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.call(removeZero);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.call(removeZero);
function drawImage(canvas) {
var context = canvas.node().getContext("2d"),
image = context.createImageData(dx, dy);
for (var y = 0, p = -1; y < dy; ++y) {
for (var x = 0; x < dx; ++x) {
var c = d3.rgb(color(heatmap[y][x]));
image.data[++p] = c.r;
image.data[++p] = c.g;
image.data[++p] = c.b;
image.data[++p] = 255;
}
}
context.putImageData(image, 0, 0);
}
function removeZero(axis) {
axis.selectAll("g").filter(function(d) { return !d; }).remove();
}
});
Upvotes: 3
Views: 1520
Reputation: 2659
I see that you're actually not really using D3 for the part of the code that makes the image itself. In the nested loops, when you're manually producing the bitmap image, you can just traverse the data in reverse. Instead of indexing the row heatmap[y]
directly on x
, you should index on dx - x - 1
, the column number counting from the right.
As an aside, it seems a little strange to be mixing SVG and canvas drawing techniques here. Depending on how much data you're showing, it may be valuable to draw the heatmap with SVG as well, which would allow you to use just a single API to draw the chart and would enable interactions as well. Alternatively, you could go for drawing the whole thing on canvas, if a static image is more appropriate, for instance if the scale of data is massive.
Upvotes: 1