admin管理员组文章数量:1302404
Demo jsFiddle
I have a basic d3 line graph, using a simple JSON array of UNIX timestamp
and float value
data, e.g:
"value": 10.04,"time": 1401185375354
[...]
This timestamp (time
) data is converted into a Date()
object before the graph is generated. All is good until I want to add a marker on hover. In order to get the correct y
value, I am resorting to using bisector
and passing the value of the x
at the current hover point. As such I currently have:
var bisect = d3.bisector(function(data) {
return data.time;
}).right;
Then in the hover function:
var timestamp = xScale.invert(mouse[0]),
index = bisect(data, timestamp),
startDatum = data[index - 1],
endDatum = data[index],
interpolate = d3.interpolateNumber(startDatum.value, endDatum.value),
range = endDatum.timestamp - startDatum.timestamp,
valueY = interpolate((timestamp % range) / range);
marker.attr('cy', yScale(valueY));
But the bisector returns invalid values..suggesting it cannot equate the passed argument (date object) against an array item. Any help would be appreciated, full code below:
HTML
<svg id="graph"></svg>
d3
var JSONData = [{
"value": 10.04,
"time": 1401185375354
}, {
"value": 0.02,
"time": 1401185374854
}, {
"value": 1.61,
"time": 1401185373854
}, {
"value": 8.47,
"time": 1401185373353
}, {
"value": 1.65,
"time": 1401185372852
}, {
"value": 0.46,
"time": 1401185371852
}, {
"value": 3.17,
"time": 1401185370888
}]
JSONData.forEach(function (d) {
d.time = new Date(d.time);
});
data = JSONData.slice();
var margin = 45,
width = parseInt(d3.select("#graph").style("width")) - margin * 2,
height = parseInt(d3.select("#graph").style("height")) - margin * 2;
var timeFormat = d3.time.format("%I:%M:%S");
var xMin = d3.min(data, function (d) {
return Math.min(d.time);
});
var xMax = d3.max(data, function (d) {
return Math.max(d.time);
});
var yMin = d3.min(data, function (d) {
return Math.min(d.value);
});
var yMax = d3.max(data, function (d) {
return Math.max(d.value);
});
var xScale = d3.time.scale().domain(d3.extent(data, function (d) {
return d.time;
})).range([0, width]);
var yScale = d3.scale.linear().domain(d3.extent(data, function (d) {
return d.value;
})).range([height, 0]);
var xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickFormat(timeFormat);
var yAxis = d3.svg.axis().scale(yScale).orient("left");
var line = d3.svg.line().x(function (d) {
return xScale(d.time);
}).y(function (d) {
return yScale(d.value);
});
var line2 = d3.svg.line().x(function (d) {
return xScale(d.time);
}).y(function (d) {
return yScale(d.askPrice);
});
var graph = d3.select("#graph").attr("width", width + margin * 2).attr("height", height + margin * 2).append("g").attr("transform", "translate(" + margin + "," + margin + ")");
graph.append("g").attr("class", "x axis").attr("transform", "translate(0," + height + ")").call(xAxis);
graph.append("g").attr("class", "y axis").call(yAxis).append("text").attr("transform", "rotate(-90)").attr("y", 6).attr("dy", ".71em").style("text-anchor", "end");
graph.append("path").datum(data).attr("class", "line").style('pointer-events', 'none').attr("d", line);
graph.append("path").datum(data).attr("class", "line2").style('pointer-events', 'none').attr("d", line2)
var marker = graph.append('circle').attr('r', 7).style('fill', '#FFFFFF').style('pointer-events', 'none').style('stroke', '#FB5050').style('stroke-width', '3px');
graph.append("rect").attr("class", "overlay").attr("width", width).attr("height", height).on("mouseover", function () {
focus.style("display", "block");
}).on("mouseout", function () {
focus.style("display", "none");
}).on("mousemove", update);
var bisect = d3.bisector(function (date) {
return date.time;
}).right;
function update() {
var mouse = d3.mouse(this);
marker.attr('cx', mouse[0]);
/* the issue is with the below */
var timestamp = xScale.invert(mouse[0]),
index = bisect(data, timestamp),
startDatum = data[index - 1],
endDatum = data[index],
interpolate = d3.interpolateNumber(startDatum.value, endDatum.value),
range = endDatum.timestamp - startDatum.timestamp,
valueY = interpolate((timestamp % range) / range);
marker.attr('cy', yScale(valueY));
}
CSS
html, body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
font-family:arial;
font-size:11px;
color:#AAAAAA;
overflow:hidden;
}
.overlay {
fill: none;
pointer-events: all;
}
.axis path, .axis line {
fill: none;
stroke: #555;
shape-rendering: crispEdges;
}
.axis text {
fill: #555;
}
.line {
fill: none;
stroke: red;
stroke-width: 1.5px;
}
Demo jsFiddle
I have a basic d3 line graph, using a simple JSON array of UNIX timestamp
and float value
data, e.g:
"value": 10.04,"time": 1401185375354
[...]
This timestamp (time
) data is converted into a Date()
object before the graph is generated. All is good until I want to add a marker on hover. In order to get the correct y
value, I am resorting to using bisector
and passing the value of the x
at the current hover point. As such I currently have:
var bisect = d3.bisector(function(data) {
return data.time;
}).right;
Then in the hover function:
var timestamp = xScale.invert(mouse[0]),
index = bisect(data, timestamp),
startDatum = data[index - 1],
endDatum = data[index],
interpolate = d3.interpolateNumber(startDatum.value, endDatum.value),
range = endDatum.timestamp - startDatum.timestamp,
valueY = interpolate((timestamp % range) / range);
marker.attr('cy', yScale(valueY));
But the bisector returns invalid values..suggesting it cannot equate the passed argument (date object) against an array item. Any help would be appreciated, full code below:
HTML
<svg id="graph"></svg>
d3
var JSONData = [{
"value": 10.04,
"time": 1401185375354
}, {
"value": 0.02,
"time": 1401185374854
}, {
"value": 1.61,
"time": 1401185373854
}, {
"value": 8.47,
"time": 1401185373353
}, {
"value": 1.65,
"time": 1401185372852
}, {
"value": 0.46,
"time": 1401185371852
}, {
"value": 3.17,
"time": 1401185370888
}]
JSONData.forEach(function (d) {
d.time = new Date(d.time);
});
data = JSONData.slice();
var margin = 45,
width = parseInt(d3.select("#graph").style("width")) - margin * 2,
height = parseInt(d3.select("#graph").style("height")) - margin * 2;
var timeFormat = d3.time.format("%I:%M:%S");
var xMin = d3.min(data, function (d) {
return Math.min(d.time);
});
var xMax = d3.max(data, function (d) {
return Math.max(d.time);
});
var yMin = d3.min(data, function (d) {
return Math.min(d.value);
});
var yMax = d3.max(data, function (d) {
return Math.max(d.value);
});
var xScale = d3.time.scale().domain(d3.extent(data, function (d) {
return d.time;
})).range([0, width]);
var yScale = d3.scale.linear().domain(d3.extent(data, function (d) {
return d.value;
})).range([height, 0]);
var xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickFormat(timeFormat);
var yAxis = d3.svg.axis().scale(yScale).orient("left");
var line = d3.svg.line().x(function (d) {
return xScale(d.time);
}).y(function (d) {
return yScale(d.value);
});
var line2 = d3.svg.line().x(function (d) {
return xScale(d.time);
}).y(function (d) {
return yScale(d.askPrice);
});
var graph = d3.select("#graph").attr("width", width + margin * 2).attr("height", height + margin * 2).append("g").attr("transform", "translate(" + margin + "," + margin + ")");
graph.append("g").attr("class", "x axis").attr("transform", "translate(0," + height + ")").call(xAxis);
graph.append("g").attr("class", "y axis").call(yAxis).append("text").attr("transform", "rotate(-90)").attr("y", 6).attr("dy", ".71em").style("text-anchor", "end");
graph.append("path").datum(data).attr("class", "line").style('pointer-events', 'none').attr("d", line);
graph.append("path").datum(data).attr("class", "line2").style('pointer-events', 'none').attr("d", line2)
var marker = graph.append('circle').attr('r', 7).style('fill', '#FFFFFF').style('pointer-events', 'none').style('stroke', '#FB5050').style('stroke-width', '3px');
graph.append("rect").attr("class", "overlay").attr("width", width).attr("height", height).on("mouseover", function () {
focus.style("display", "block");
}).on("mouseout", function () {
focus.style("display", "none");
}).on("mousemove", update);
var bisect = d3.bisector(function (date) {
return date.time;
}).right;
function update() {
var mouse = d3.mouse(this);
marker.attr('cx', mouse[0]);
/* the issue is with the below */
var timestamp = xScale.invert(mouse[0]),
index = bisect(data, timestamp),
startDatum = data[index - 1],
endDatum = data[index],
interpolate = d3.interpolateNumber(startDatum.value, endDatum.value),
range = endDatum.timestamp - startDatum.timestamp,
valueY = interpolate((timestamp % range) / range);
marker.attr('cy', yScale(valueY));
}
CSS
html, body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
font-family:arial;
font-size:11px;
color:#AAAAAA;
overflow:hidden;
}
.overlay {
fill: none;
pointer-events: all;
}
.axis path, .axis line {
fill: none;
stroke: #555;
shape-rendering: crispEdges;
}
.axis text {
fill: #555;
}
.line {
fill: none;
stroke: red;
stroke-width: 1.5px;
}
Share
asked May 27, 2014 at 13:46
SW4SW4
71.2k20 gold badges136 silver badges139 bronze badges
1 Answer
Reset to default 11There are a few problems with your current code:
d3.bisect
works only on sorted data. Fixed withdata.sort(function(a, b) { return a.time - b.time; });
- In the mouseover function, you're referencing a non-existent
.timestamp
attribute instead of.time
. - The calculation of the interpolation value isn't correct. Should be
interpolate((timestamp - startDatum.time) / range);
Complete demo with fixes here. You may also find this example helpful.
本文标签: javascriptd3bisector using Date() Object does not resolveStack Overflow
版权声明:本文标题:javascript - d3.bisector using Date() Object does not resolve - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741675897a2391881.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论