重构d3条形图为水平条形图

问题描述:

我试图在d3中将此条形图重构为水平条形图。我想我已经分离出需要改变的三个方面:重构d3条形图为水平条形图

原有规模声明:

var x0 = d3.scale.ordinal() 
     .rangeRoundBands([0, width], 0.1); 

    var x1 = d3.scale.ordinal(); 

    var y = d3.scale.linear() 
     .range([height, 0]); 

的域定义:

x0.domain(data.map(function(d) { return d.deviceType; })); 
x1.domain(deviceClass).rangeRoundBands([0, x0.rangeBand()]); 
y.domain([0, d3.max(data, function(d) { return d3.max(d.whenPurchased, function(d) { return d.value; }); })]); 

的矩形追加和定位:

device.selectAll("rect") 
    .data(function(d) { return d.whenPurchased; }) 
    .enter().append("rect") 
    .attr("width", x1.rangeBand()) 
    .attr("x", function(d) { return x1(d.device); }) 
    .attr("y", function(d) { return y(d.value); }) 
    .attr("height", function(d) { return height - y(d.value); }) 
    .style("fill", function(d) { return color(d.device); }); 

我似乎无法得到重构的权利,我认为这是因为我不exa很好地了解域如何为x0工作,基本上没有得到正确的瀑布效果,其他所有工作都不起作用。

我把完整的例子在这里:JSFIDDLE

+0

查看https://*.com/questions/16202721/d3js-change-vertical-bar-chart-to-horizo​​ntal-bar-chart –

这里有一个快速重构:

var margin = {top: 20, right: 20, bottom: 30, left: 270}, 
 
    width = 960 - margin.left - margin.right, 
 
    height = 500 - margin.top - margin.bottom; 
 

 
var y0 = d3.scale.ordinal() 
 
    .rangeRoundBands([0, height], 0.1); 
 

 
var y1 = d3.scale.ordinal(); 
 

 
var x = d3.scale.linear() 
 
    .range([0, width]); 
 

 
var color = d3.scale.ordinal() 
 
    .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]); 
 

 
var xAxis = d3.svg.axis() 
 
    .scale(x) 
 
    .orient("bottom"); 
 

 
var yAxis = d3.svg.axis() 
 
    .scale(y0) 
 
    .orient("left"); 
 
    // .tickFormat(d3.format(".2s")); 
 

 
var svg = d3.select("#deviceown-barchart").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 data = d3.csv.parse(d3.select("pre#data").text()); 
 

 

 
    var deviceClass = d3.keys(data[0]).filter(function(key) { return key !== "deviceType"; }); 
 

 
    data.forEach(function(d) { 
 
    d.whenPurchased = deviceClass.map(function(device) { return {device: device, value: +d[device]}; }); 
 
    }); 
 

 
    y0.domain(data.map(function(d) { return d.deviceType; })); 
 
    y1.domain(deviceClass).rangeRoundBands([0, y0.rangeBand()]); 
 
    x.domain([0, d3.max(data, function(d) { return d3.max(d.whenPurchased, function(d) { return d.value; }); })]); 
 

 
    svg.append("g") 
 
     .attr("class", "x axis") 
 
     .attr("transform", "translate(0," + height + ")") 
 
     .call(xAxis); 
 

 
    svg.append("g") 
 
     .attr("class", "y axis") 
 
     .call(yAxis) 
 
    .append("text") 
 
     .attr("transform", "rotate(-90)") 
 
     .attr("y", 6) 
 
     .attr("dy", ".71em") 
 
     .style("text-anchor", "end"); 
 

 
    var device = svg.selectAll(".device") 
 
     .data(data) 
 
    .enter().append("g") 
 
     .attr("class", "device") 
 
     .attr("transform", function(d) { return "translate(0," + y0(d.deviceType) + ")"; }); 
 

 
device.selectAll("rect") 
 
     .data(function(d) { return d.whenPurchased; }) 
 
    .enter().append("rect") 
 
     .attr("height", y1.rangeBand()) 
 
     .attr("y", function(d) { return y1(d.device); }) 
 
     .attr("x", 0) 
 
     .style("fill", function(d) { return color(d.device); }) 
 
     .attr("width", 0) 
 
     .transition() 
 
     .duration(1500) 
 
     .attr("width", function(d) { return x(d.value); }); 
 

 
    var legend = svg.selectAll(".legend") 
 
     .data(deviceClass.slice().reverse()) 
 
    .enter().append("g") 
 
     .attr("class", "legend") 
 
     .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; }); 
 

 
    legend.append("rect") 
 
     .attr("x", width - 18) 
 
     .attr("width", 18) 
 
     .attr("height", 18) 
 
     .style("fill", color); 
 

 
    legend.append("text") 
 
     .attr("x", width - 24) 
 
     .attr("y", 9) 
 
     .attr("dy", ".35em") 
 
     .style("text-anchor", "end") 
 
     .text(function(d) { return d; }); 
 

 
// });
.axis path, 
 
.axis line { 
 
    fill: none; 
 
    stroke: #000; 
 
    shape-rendering: crispEdges; 
 
} 
 

 
.bar { 
 
    fill: steelblue; 
 
} 
 

 
.y.axis path { 
 
    display: none; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<div id="deviceown-barchart"></div> 
 

 
<pre id="data"> 
 
deviceType,Within the last 6 months,More than 6 months ago 
 
Netatmo Weather Station,0.14,0.09 
 
Nest Learning Thermostat,0.13,0.14 
 
Philips Hue Connected Bulb,0.13,0.08 
 
Nest Cam,0.12,0.12 
 
Belkin WeMo Switch + Motion,0.09,0.08 
 
Nest Protect,0.08,0.12 
 
Canary,0.08,0.03 
 
Other smart home security device,0.08,0.12 
 
August Smart Lock,0.06,0.07 
 
Other connected home appliance,0.05,0.08 
 
GE/Quirky Aros Smart AC,0.04,0.04 
 
Other smart energy monitor,0,0.03 
 
</pre>

更新fiddle

+0

这太棒了。我不得不把它变成一个堆积的条形图,现在我想知道如何使渲染的矩形元素动起来,你知道吗? – moku

+0

@moku,查看上面代码的更新。 – Mark

+0

啊我看你必须首先将任何“增长”初始化为零。谢了哥们。 – moku