#d3.js #data-visualization
#d3.js #данные-визуализация
Вопрос:
Я пытаюсь создать многострочный график для моего веб-приложения angular, чтобы визуализировать некоторые данные, которые будут добавлять строки в соответствии с элементами в переменной data. Поскольку я пытаюсь добавить строку path в элемент svg, мне не удается ее отобразить. Прямо сейчас корректно отображаются только две оси.
var margin = {
top: 20,
right: 80,
bottom: 30,
left: 50
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scaleTime().domain([new Date(2000, 0, 0), new Date(2017, 0, 0)]).range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var svg = d3.select(this.htmlElement).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 ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," height ")")
.call(d3.axisBottom(x).tickFormat(d3.timeFormat("%Y")).ticks(d3.timeYear, 1));
// Add the Y Axis
svg.append("g")
.call(d3.axisLeft(y))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end");
// define the line
var line = d3.line()
.x(function(d) {
return d.name;
})
.y(function(d) {
return d.value;
});
data.forEach(function(d) {
svg.append("path")
.attr("class", "line")
.attr('d', line(d.series))
.attr('stroke', 'blue')
.attr('stroke-width', 2)
.attr('fill', 'none');
});
структура данных такая
var data = [{
"key": "Germany",
"series": [
{
"a": "Germany",
"name": "2010",
"value": 0.2
},
{
"a": "Germany",
"name": "2011",
"value": 0.5
}
]
}, {
"key": "uk",
"series": [
{
"a":"uk",
"name": "2010",
"value": 0.3
},
{
"a":"uk",
"name": "2011",
"value": 0.6
}
]
}];
я предполагаю, что проблема заключается в цикле data.foreach, но мне не удается его найти.
Комментарии:
1. Вы не используете свои шкалы в генераторе строк. Т.Е. вместо этого
.x(function(d) { return d.name; })
должно быть.x(function(d) { return x(d.name); })
(аналогично для.y()
части).2. В дополнение к исправлениям @matthias.rocks, вы также не устанавливаете
.domain
в своей y-шкале.3. Подождите, вам также необходимо преобразовать год, сохраненный в
name
свойствах, иначе scaleTime D3 интерпретирует его как временную метку (т. Е. через несколько секунд после эпохи). Что-то вроде.x(function(d) { return x(new Date(d.name, 0)); })
должно сработать.4. @Mark True действительно — хороший улов.
5. да, спасибо, это были проблемы, я опубликовал рабочий код в качестве ответа ниже.
Ответ №1:
согласно комментариям выше, рабочий код можно увидеть ниже
var margin = {
top: 20,
right: 80,
bottom: 30,
left: 50
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scaleTime().domain([new Date(2000, 0, 0), new Date(2017, 0, 0)]).range([0, width]);
var y = d3.scaleLinear().domain([0,1]).range([height, 0]);
var svg = d3.select(this.htmlElement).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 ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," height ")")
.call(d3.axisBottom(x).tickFormat(d3.timeFormat("%Y")).ticks(d3.timeYear, 1));
// Add the Y Axis
svg.append("g")
.call(d3.axisLeft(y))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end");
// define the line
var line = d3.line()
.x(function(d) {
return x(new Date(d.name, 0));
})
.y(function(d) {
return y(d.value);
});
data.forEach(function(d) {
svg.append("path")
.attr("class", "line")
.attr('d', line(d.series))
.attr('stroke', 'blue')
.attr('stroke-width', 2)
.attr('fill', 'none');
});