#javascript #d3.js
#javascript #d3.js
Вопрос:
Я пытаюсь нарисовать многострочную диаграмму с D3.js . Диаграмма нарисована правильно, но отметки по оси x неправильно выровнены с окружностью точек данных. Найдите пример кода здесь:https://jsfiddle.net/gopal31795/qsLd7pc5/9 /
Я предполагаю, что в коде для создания точек есть какая-то ошибка.
// Creating Dots on line
segment.selectAll("dot")
.data(function(d) {
return d.linedata;
})
.enter().append("circle")
.attr("r", 5)
.attr("cx", function(d) {
//return x(parseDate(new Date(d.mins))) x.rangeBand() / 2;
return x(d.mins);
})
.attr("cy", function(d) {
return y(d.value);
})
.style("stroke", "white")
.style("fill", function(d) {
return color(this.parentNode.__data__.name);
})
.on("mouseenter", function(d) {
d3.select(this).transition().style("opacity", "0.25");
tooltip.html("<span style='color:" color(this.parentNode.__data__.name) ";'>" this.parentNode.__data__.name "</span>: " (d.value "s")).style("visibility", "visible").style("top", (event.pageY 10) "px").style("left", (event.pageX) "px");
})
.on("mouseleave", function(d) {
d3.select(this).transition().style("opacity", "1");
tooltip.style("visibility", "hidden");
});
Ответ №1:
Проблема в вашем коде (который использует старый v3) заключается в том, что вы используете rangeRoundBands
. Это был бы правильный выбор, если бы у вас была столбчатая диаграмма, например.
Однако, поскольку вы имеете дело с точками данных, вам следует использовать rangePoints
или rangeRoundPoints
, который:
Задает диапазон выходных данных от указанного непрерывного интервала. Интервал массива содержит два элемента, представляющих минимальное и максимальное числовое значение. Этот интервал разделен на n равномерно расположенных точек, где n — количество (уникальных) значений во входном домене.
Итак, это должно быть:
var x = d3.scale.ordinal()
.rangeRoundPoints([0, width]);
Вот ваш код с этим изменением:
var Data = [{
"name": "R",
"linedata": [{
"mins": 0,
"value": 1120
},
{
"mins": 2,
"value": 1040
},
{
"mins": 4,
"value": 1400
},
{
"mins": 6,
"value": 1500
}
]
},
{
"name": "E",
"linedata": [{
"mins": 0,
"value": 1220
},
{
"mins": 2,
"value": 1500
},
{
"mins": 4,
"value": 1610
},
{
"mins": 6,
"value": 1700
}
]
}
];
var margin = {
top: 20,
right: 90,
bottom: 35,
left: 90
},
width = $("#lineChart").width() - margin.left - margin.right,
height = $("#lineChart").width() * 0.3745 - margin.top - margin.bottom;
//var parseDate = d3.time.format("%d-%b");
var x = d3.scale.ordinal()
.rangeRoundPoints([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5);
var xData = Data[0].linedata.map(function(d) {
return d.mins;
});
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) {
return x(d.mins);
})
.y(function(d) {
return y(d.value);
});
function transition(path) {
path.transition()
.duration(4000)
.attrTween("stroke-dasharray", tweenDash);
}
function tweenDash() {
var l = this.getTotalLength(),
i = d3.interpolateString("0," l, l "," l);
return function(t) {
return i(t);
};
}
var svg = d3.select("#lineChart").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 ")");
color.domain(Data.map(function(d) {
return d.name;
}));
x.domain(xData);
var valueMax = d3.max(Data, function(r) {
return d3.max(r.linedata, function(d) {
return d.value;
})
});
var valueMin = d3.min(Data, function(r) {
return d3.min(r.linedata, function(d) {
return d.value;
})
});
y.domain([valueMin, valueMax]);
//Drawing X Axis
svg.append("g")
.attr("class", "x-axis")
.attr("transform", "translate(0," height ")")
.call(xAxis)
.append("text")
.attr("class", "xAxisText")
.attr("x", width)
.attr("dy", "-.41em")
.style("text-anchor", "end")
.style("fill", "white")
.text("Time(m)");
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")
.style("fill", "none")
.style("stroke", "white")
.style("stroke-width", 0.8)
.text("Duration(s)");
// Drawing Lines for each segments
var segment = svg.selectAll(".segment")
.data(Data)
.enter().append("g")
.attr("class", "segment");
segment.append("path")
.attr("class", "line")
.attr("id", function(d) {
return d.name;
})
.attr("visible", 1)
.call(transition)
//.delay(750)
//.duration(1000)
//.ease('linear')
.attr("d", function(d) {
return line(d.linedata);
})
.style("stroke", function(d) {
return color(d.name);
});
// Creating Dots on line
segment.selectAll("dot")
.data(function(d) {
return d.linedata;
})
.enter().append("circle")
.attr("r", 5)
.attr("cx", function(d) {
//return x(parseDate(new Date(d.mins))) x.rangeBand() / 2;
return x(d.mins);
})
.attr("cy", function(d) {
return y(d.value);
})
.style("stroke", "white")
.style("fill", function(d) {
return color(this.parentNode.__data__.name);
})
.on("mouseenter", function(d) {
d3.select(this).transition().style("opacity", "0.25");
tooltip.html("<span style='color:" color(this.parentNode.__data__.name) ";'>" this.parentNode.__data__.name "</span>: " (d.value "s")).style("visibility", "visible").style("top", (event.pageY 10) "px").style("left", (event.pageX) "px");
})
.on("mouseleave", function(d) {
d3.select(this).transition().style("opacity", "1");
tooltip.style("visibility", "hidden");
});
path {
fill: none;
stroke: black;
}
line {
stroke: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<div class="card-body" id="lineChart">
</div>
Наконец, в качестве совета: не смешивайте D3 и jQuery.
Комментарии:
1. Спасибо @Gerardo Furtado. Это именно то, что я хочу, и спасибо за совет тоже.