Ответ немного ниже на странице:
Диапазон действительно от 0 до 61; в соответствии с стандартом Posix, это означает, что это означает прыжок секунд и (очень редкий) двойной прыжок секунд. Модуль времени может создавать и принимать прыжковые секунды, так как он основан на стандарте Posix, но модуль datetime не принимает секунды прыжка в входе strptime () и не будет производить их в выводе strftime ().
blockquote>Это действительно интересное поведение.
Жесткое кодирование позиции slice
не очень гибкое.
Определите индекс первой точки со статусом = 0, а затем разделите данные на основе этого индекса.
var firstStatus0 = data.findIndex( e => e.status === 0);
firstStatus0 = firstStatus0 === -1 ? data.length : firstStatus0;
// Add the valueline path.
var lineGraph2 = lineSvg.append("path")
.attr("class", "line")
.attr("d", valueline(data.slice(0, firstStatus0)))
.attr("stroke", "blue").attr("stroke-width", 2)
.attr("fill", "none");
var lineGraph1 = lineSvg.append("path")
.attr("class", "line")
.attr("d", valueline(data.slice(Math.max(0, firstStatus0 - 1))))
.attr("stroke", "red").attr("stroke-width", 2)
.attr("fill", "none");
Код делает именно то, что вы ему сказали: есть только 2 объекта данных с status:0
. Таким образом, при фильтрации данных ...
.attr("d", valueline(data.filter(function(d) {
return d.status <= 0;
})))
... есть только 2 точки для генерации синей линии, которая создает одну линию, идущую от первой ко второй.
Вместо этого просто получите последние три объекта:
.attr("d", valueline(data.slice(-3)))
Таким образом, у вас будет три точки и, следовательно, две линии.
Вот ваш код с этим изменением:
var data = [{
"date": "2018-1",
"value": 40.13,
"status": 1
},
{
"date": "2018-2",
"value": 45.88,
"status": 1
},
{
"date": "2018-3",
"value": 50.89,
"status": 1
},
{
"date": "2018-4",
"value": 55.87,
"status": 1
},
{
"date": "2018-5",
"value": 88.54,
"status": 1
},
{
"date": "2018-6",
"value": 74.41,
"status": 1
},
{
"date": "2018-7",
"value": 98.56,
"status": 1
},
{
"date": "2018-8",
"value": 81.05,
"status": 1
},
{
"date": "2018-9",
"value": 58.13,
"status": 1
},
{
"date": "2018-10",
"value": 95.86,
"status": 1
},
{
"date": "2018-11",
"value": 78.13,
"status": 1
},
{
"date": "2018-12",
"value": 98.86,
"status": 1
},
{
"date": "2019-1",
"value": 105.86,
"status": 0
},
{
"date": "2019-2",
"value": 110.86,
"status": 0
}
];
/* Monday 2012 */
var data1 = data
var dateformat = "%Y-%m"
drawTimeSeriesGraph(data1, dateformat);
/*
Tooltip from: http://bl.ocks.org/d3noob/6eb506b129f585ce5c8a
line graph from here: http://www.d3noob.org/2012/12/starting-with-basic-d3-line-graph.html
*/
function drawTimeSeriesGraph(data, dateformat) {
//Set bounds for red dots
var lbound = 0.045,
ubound = 0.075;
// Set the dimensions of the canvas / graph
var margin = {
top: 50,
right: 150,
bottom: 50,
left: 50
},
width = 900 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format(dateformat).parse,
formatDate = d3.time.format(dateformat),
bisectDate = d3.bisector(function(d) {
return d.date;
}).left;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(10);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(10);
// Define the line
var valueline = d3.svg.line()
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.value);
}).interpolate("linear");
var full_date = new Date();
var day = full_date.getDay(); //returns 0 - 6
var month = full_date.getMonth() + 1; //returns 0 - 11
var year = full_date.getFullYear(); //returns 4 digit year ex: 2000
var my = year + "-" + month;
//alert(my);
// Adds the svg canvas
var svg = d3.select("body")
.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 lineSvg = svg.append("g");
var focus = svg.append("g")
.style("display", "none");
// Get the data
data.forEach(function(d) {
d.date = parseDate(d.date);
d.value = +d.value;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) {
return d.date;
}));
y.domain([0, d3.max(data, function(d) {
return d.value;
})]);
//Use below if instead you want to define the y limits:
//y.domain([0, 0.11]);
// Add the valueline path.
var lineGraph2 = lineSvg.append("path")
.attr("class", "line")
.attr("d", valueline(data.filter(function(d) {
return d.status > 0;
}))).attr("stroke", "blue").attr("stroke-width", 2)
.attr("fill", "none");
var lineGraph1 = lineSvg.append("path")
.attr("class", "line")
.attr("d", valueline(data.slice(-3))).attr("stroke", "red").attr("stroke-width", 2)
.attr("fill", "none");
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// append the x line
focus.append("line")
.attr("class", "x")
.style("stroke", "blue")
.style("stroke-dasharray", "3,3")
.style("opacity", 0.5)
.attr("y1", 0)
.attr("y2", height);
// append the y line
focus.append("line")
.attr("class", "y")
.style("stroke", "blue")
.style("stroke-dasharray", "3,3")
.style("opacity", 0.5)
.attr("x1", width)
.attr("x2", width);
// append the circle at the intersection
focus.append("circle")
.attr("class", "y")
.style("fill", "none")
.style("stroke", "blue")
.attr("r", 4);
// place the value at the intersection
focus.append("text")
.attr("class", "y1")
.style("stroke", "white")
.style("stroke-width", "3.5px")
.style("opacity", 0.8)
.attr("dx", 8)
.attr("dy", "-.3em");
focus.append("text")
.attr("class", "y2")
.attr("dx", 8)
.attr("dy", "-.3em");
// place the date at the intersection
focus.append("text")
.attr("class", "y3")
.style("stroke", "white")
.style("stroke-width", "3.5px")
.style("opacity", 0.8)
.attr("dx", 8)
.attr("dy", "1em");
focus.append("text")
.attr("class", "y4")
.attr("dx", 8)
.attr("dy", "1em");
// append the rectangle to capture mouse
svg.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", "none")
.style("pointer-events", "all")
.on("mouseover", function() {
focus.style("display", null);
})
.on("mouseout", function() {
focus.style("display", "none");
})
.on("mousemove", mousemove);
function mousemove() {
var x0 = x.invert(d3.mouse(this)[0]),
i = bisectDate(data, x0, 1),
d0 = data[i - 1],
d1 = data[i],
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
focus.select("circle.y")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.value) + ")");
focus.select("text.y1")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.value) + ")")
.text(d.value.toFixed(2));
focus.select("text.y2")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.value) + ")")
.text(d.value.toFixed(2));
focus.select("text.y3")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.value) + ")")
.text(formatDate(d.date));
focus.select("text.y4")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.value) + ")")
.text(formatDate(d.date));
focus.select(".x")
.attr("transform",
"translate(" + x(d.date) + "," +
y(d.value) + ")")
.attr("y2", height - y(d.value));
focus.select(".y")
.attr("transform",
"translate(" + width * -1 + "," +
y(d.value) + ")")
.attr("x2", width + width);
};
svg.append("text")
.attr("x", (width / 2))
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("text-decoration", "underline")
};
.axis text {
font-family: sans-serif;
font-size: 9px;
}
.axis path {
fill: none;
stroke: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>