Я относительно новичок в d3.js. Я работаю над проектом, в котором мне нужно отобразить графики в моем веб-приложении. Я нашел код, который частично делал то, что мне было нужно, но график - это горизонтальная гистограмма, а мне нужна вертикальная (столбчатая диаграмма).
Я попытался переключить ось, поскольку это имело логический смысл, но я думаю, что где-то запутался ... Может кто-нибудь помочь мне с преобразованием этой гистограммы в столбчатую диаграмму?
HTML-код:
<div class="container">
<div class="row">
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-body">
<form role="form" class="categories">
</form>
</div>
</div>
</div>
<div class="col-md-8">
<div class="graph"></div>
</div>
</div>
</div>
Графический код:
var data = [{
year: '1990',
stats: [454.2894, 2420.8398, 5122.7559]
},
{
year: '1995',
stats: [569.3625, 2387.0628, 5041.4598]
},
{
year: '2000',
stats: [ 783.59, 2337.01, 4877.29]
},
{
year: '2005',
stats: [ 807.86, 2555.67, 4634.35]
},
{
year: '2010',
stats: [ 1060.82, 2687.81, 4249.26]
},
{
year: '2015',
stats: [ 1215.32, 2757.62, 4024.94]
}
];
var ids = ['mangroves', 'water', 'others'];
var statistics = ['Mangroves', 'Water', 'Others'];
// Let's populate the categoeries checkboxes
d3.select('.categories').selectAll('.checkbox')
.data(ids)
.enter()
.append('div')
.attr('class', 'checkbox')
.append('label').html(function(id, index) {
var checkbox = '<input id="' + id + '" type="checkbox" class="category">';
return checkbox + statistics[index];
});
// some variables declarations
var margin = {
top: 20,
right: 20,
bottom: 30,
left: 40
},
width = 800 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
// the scale for the year statistic value
var x = d3.scale.linear().range([0, width]);
// the scale for each year
var y0 = d3.scale.ordinal().rangeBands([0, height], .1);
// the scale for each year statistic
var y1 = d3.scale.ordinal();
// just a simple scale of colors
var color = d3.scale.ordinal()
.range(["#00ff00", "#0000ff", "#cccccc"]);
//
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.format(".2s"));
var yAxis = d3.svg.axis()
.scale(y0)
.orient("left");
var svg = d3.select(".graph").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 + ")");
d3.select('.categories').selectAll('.category').on('change', function() {
var x = d3.select('.categories').selectAll('.category:checked');
var ids = x[0].map(function(category) {
return category.id;
});
updateGraph(ids);
});
renderGraph();
function renderGraph() {
x.domain([0, 0]);
// y0 domain is all the year names
y0.domain(data.map(function(d) {
return d.year;
}));
// y1 domain is all the statistic names, we limit the range to from 0 to a y0 band
y1.domain(statistics).rangeRoundBands([0, y0.rangeBand()]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
}
function updateGraph(selectedIds) {
var statesData = data.map(function(stateData) {
return {
year: stateData.year,
datas: selectedIds.map(function(selectedId) {
var index = ids.findIndex(function(id) {
return selectedId === id;
});
return {
id: ids[index],
name: statistics[index],
value: stateData.stats[index]
};
})
}
});
// x domain is between 0 and the maximun value in any datas.value
x.domain([0, d3.max(statesData, function(d) {
return d3.max(d.datas, function(d) {
return d.value
});
})]);
// y0 domain is all the year names
y0.domain(statesData.map(function(d) {
return d.year;
}));
// y1 domain is all the statistic names, we limit the range to from 0 to a y0 band
y1.domain(ids).rangeRoundBands([0, y0.rangeBand()]);
svg.selectAll('.axis.x').call(xAxis);
svg.selectAll('.axis.y').call(yAxis);
var year = svg.selectAll(".year")
.data(statesData);
year.enter().append("g")
.attr("class", "year")
.attr("transform", function(d) {
return "translate(0, " + y0(d.year) + ")";
});
var statistic = year.selectAll("rect")
.data(function(d) {
return d.datas;
});
// we append a new rect every time we have an extra data vs dom element
statistic.enter().append("rect")
.attr('width', 0);
// this updates will happend neither inserting new elements or updating them
statistic
.attr("x", 0)
.attr("y", function(d, index) {
return y1(ids[index]);
})
.attr("id", function(d) {
return d.id;
})
.style("fill", function(d) {
return color(d.name);
})
.text(function(d) {
return d.name
})
.transition()
.attr("width", function(d) {
return x(d.value);
})
.attr("height", y1.rangeBand());
statistic.exit().transition().attr("width", 0).remove();
var legend = svg.selectAll(".legend")
.data(statesData[0].datas.map(function(statistic) {
return statistic.name;
}));
legend.enter().append("g");
legend
.attr("class", "legend")
.attr("transform", function(d, i) {
return "translate(0," + (200 + i * 20) + ")";
});
var legendColor = legend.selectAll('.legend-color').data(function(d) {
return [d];
});
legendColor.enter().append("rect");
legendColor
.attr('class', 'legend-color')
.attr("x", width - 18)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
var legendText = legend.selectAll('.legend-text').data(function(d) {
return [d];
});;
legendText.enter().append("text");
legendText
.attr('class', 'legend-text')
.attr("x", width - 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) {
return d;
});
legend.exit().remove();
}