Если я правильно понял, это то, что вам нужно. Плункер с рабочим кодом .
Прежде всего я бы рекомендовал использовать маржинальный объект, который обеспечит большую гибкость при работе с диаграммами
var margin = {
top: 20,
right: 20,
bottom: 20,
left: 20
};
Мы хотим отобразитьданные с единичной шкалой из приведенных вами данных и примера.
{key: "bedrijfsvestigingen_Sbi2008_BedrijfsvestigingenTotaal", value: 490}
{key: "bedrijfsvestigingen_Sbi2008_BedrijfsvestigingenNaarActiviteit_M_nZakelijkeDienstverlening", value: 165}
{key: "bedrijfsvestigingen_Sbi2008_BedrijfsvestigingenNaarActiviteit_R_uCultuur_Recreatie_OverigeDiensten", value: 120}
{key: "bedrijfsvestigingen_Sbi2008_BedrijfsvestigingenNaarActiviteit_K_lFinancieleDiensten_OnroerendGoed", value: 15}
{key: "bedrijfsvestigingen_Sbi2008_BedrijfsvestigingenNaarActiviteit_ALandbouw_BosbouwEnVisserij", value: 0}
{key: "bedrijfsvestigingen_Sbi2008_BedrijfsvestigingenNaarActiviteit_H_p_JVervoer_InformatieEnCommunicatie", value: 85}];
Учитывая, что, вероятно, первый элемент представляет собой сумму видов набора данных, я думаю, что он не долженне может быть включен в диаграмму, поскольку это совокупность элементов, которые мы хотим отобразить.(Если вам нужно отобразить его как элемент, вы сможете быстро сделать это после просмотра ответа)
Структура элемента в вашем наборе данных следующая:
{
key: "bedrijfsvestigingen_Sbi2008_BedrijfsvestigingenNaarActiviteit_H_p_JVervoer_InformatieEnCommunicatie",
value: 85
}
домен нашего xScale
должен быть всеми значениями ключа в нашем наборе данных, так как ключ является огромной строкой, я создал собственное свойство в каждом элементе с именем label
{
key:
"bedrijfsvestigingen_Sbi2008_BedrijfsvestigingenNaarActiviteit_M_nZakelijkeDienstverlening",
label: "Business Services",
value: 165
}
Давайте создадим наш масштаб с правильнымдомен и диапазон:
var xScale = d3
.scaleBand()
.domain(dataset.map(d => d.label)) // All our label properties
.rangeRound([0, w - margin.left - margin.right]) // This scale will map our values from [0, width - margin.left - margin.right]
.paddingInner(0.05);
yScale был почти верен, нам просто нужно немного изменить его, чтобы использовать наш маржинальный объект и использовать правильный диапазон. Диапазон должен начинаться с 0, если мы использовали заполнение какНачальная точка наших значений будет иметь смещение, поскольку наши значения будут отображаться из [padding, h - padding].Если бы мы хотели отобразить ноль, значение было бы сопоставлено со значением заполнения, если вы хотите, чтобы информация отображалась таким образом.В этом случае мы изменим масштаб.
var yScale = d3
.scaleLinear()
.domain([
0,
d3.max(dataset, function(d) {
return d.value;
})
])
.range([0, h - margin.top - margin.bottom]);
Далее мы создадим функцию для получения желаемого значения из наших элементов
var xKey = function(d) {
return d.label;
};
Добавьте наш SVG с некоторыми визуальными подсказками, чтобы помочьвизуализируя расположение элементов:
var svg = d3
.select("#barchart")
.append("svg")
.style("background", "rgb(243, 243, 243)")
.style("border", "1px dashed #b4b4b4")
.attr("width", w)
.attr("height", h);
Мы хотим использовать маржу, поэтому для этого воспользуемся групповым тегом, мы можем индивидуально установить маржу в каждой группе / элементе, которые нам нужны, но янайти этот способ проще и понятнее
var g = svg
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
Нам понадобятся ширина и высота графика с учетом полей, давайте определим их очень быстро:
const customWidth = w - margin.left - margin.right;
const customHeight = h - margin.top - margin.bottom;
Давайте добавимПрямоугольник, чтобы показать, где будут отображаться наши ректы:
g.append("rect")
.attr("fill", "#e3e3e3")
.attr("width", customWidth)
.attr("height", customHeight);
Позволяет разобраться с созданием прямоугольника, в вашем коде у вас была пользовательская функция заполнения, которая изменила значение b в пределах значений цвета RGB.В этом случае, поскольку мы имеем дело с категориальными данными, мы будем использовать массив цветов для ректов.
g.append("g")
.attr("class", "rect__container")
.selectAll("rect")
.data(dataset, xKey) //Bind data with custom key function
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScale(xKey(d)); // use our key function
})
.attr("y", function(d) {
return customHeight - yScale(d.value); // use our custom size values
})
.attr("width", xScale.bandwidth())
.attr("height", function(d) {
return yScale(d.value);
})
.attr("fill", function(d, i) {
return d3.schemeCategory10[i]; // use an array of colors and use the index to decide which color to use
});
У нас есть два варианта отображения меток диаграммы:
Мы можемсоздать ось X или желаемые легенды.Мы сделаем и то и другое, так как это не повлияет на результат графика, и любой из них можно удалить.
var margin = {
top: 20,
right: 300, // modifiy our margin to have space to display the legends
bottom: 50,
left: 20
};
var legendElement = g
.append("g")
.attr("class", "legend__container")
.attr("transform", `translate(${customWidth}, ${margin.top})`) // set our group position to the end of the chart
.selectAll("g.legend__element")
.data(xScale.domain()) // use the scale domain as data
.enter()
.append("g")
.attr("transform", function(d, i) {
return `translate(${10}, ${i * 30})`; // provide an offset for each element found in the domain
});
legendElement
.append("text")
.attr("x", 30)
.attr("font-size", "14px")
.text(d => d);
legendElement
.append("rect")
.attr("x", 0)
.attr("y", -15)
.attr("width", 20)
.attr("height", 20)
.attr("fill", function(d, i) {
return d3.schemeCategory10[i]; // use the same category color that we previously used in rects
});
Теперь давайте используем осевой подход:
// create axis
var x_axis = d3.axisBottom().scale(xScale);
//Append group and insert axis
g.append("g")
.attr("transform", `translate(${0}, ${customHeight})`)
.call(x_axis);
g.append("g")
.attr("transform", `translate(${customWidth / 2}, ${customHeight + 40})`)
.append("text")
.text("Activities")
.attr("font-family", "sans-serif")
.attr("font-size", "14px")
.attr("font-weight", "bold")
.style("text-transform", "uppercase")
.attr("text-anchor", "middle");
Инаконец, создайте метки для значения в наших данных:
//Create labels
g.append("g")
.attr("class", "text__container")
.selectAll("text")
.data(dataset, xKey) //Bind data with custom key function
.enter()
.append("text")
.text(function(d) {
return d.value;
})
.attr("text-anchor", "middle")
.attr("x", function(d, i) {
return xScale(xKey(d)) + xScale.bandwidth() / 2;
})
.attr("y", function(d) {
return customHeight - yScale(d.value) + 14;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "white");