[英]D3.js: Wrong position of horizontal and vertical focus lines (crosshairs) in line chart
我為數據修改了該示例: 具有X和Y十字准線以及閾值線的D3js圖 。
我認為該域存在問題,但我無法弄清楚。 這是我的腳本:
更新:問題是由我放置文本的方式引起的。 任何想法如何以其他方式放置文本?
var svg = d3.select("svg"),
margin = {top: 20, right: 50, bottom: 30, left: 50},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var parseTime = d3.utcParse("%Y-%m-%dT%H:%M:%S.%LZ");
var bisectDate = d3.bisector(function(d) { return d.timestamp; }).left;
var formatValue = d3.format(",.2f");
d3.json("data.json", function(error, json) {
if (error) throw error;
var data = json[0].tideData;
data.forEach(function(d) {
d.timestamp = parseTime(d.timestamp);
});
var xDomain = d3.extent(data, function(d) { return d.timestamp; });
var yDomain = d3.extent(data, function(d) { return d.tide; });
var xScale = d3.scaleTime().rangeRound([0, width]).domain(xDomain);
var yScale = d3.scaleLinear().rangeRound([height, 0]).domain(yDomain);
var line = d3.line()
.defined(function(d) { return d.tide!=null; })
.x(function(d) { return xScale(d.timestamp); })
.y(function(d) { return yScale(d.tide); });
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(yScale))
.append("text")
.attr("fill", "#000")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.style("text-anchor", "end")
.text("Sea Level");
g.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
var focus = g.append("g")
.attr("class", "focus")
.style("display", "none");
focus.append("circle")
.attr("r", 4.5);
focus.append("text")
.attr("x", 9)
.attr("dy", ".35em");
focus.append('line')
.attr('id', 'focusLineX')
.attr('class', 'focusLine');
focus.append('line')
.attr('id', 'focusLineY')
.attr('class', 'focusLine');
g.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.on("mouseover", function() { focus.style("display", null); })
.on("mouseout", function() { focus.style("display", "none"); })
.on("mousemove", mousemove);
function mousemove() {
var mouse = d3.mouse(this);
var mouseDate = xScale.invert(mouse[0]);
var i = bisectDate(data, mouseDate); // returns the index to the current data item
var d0 = data[i - 1];
var d1 = data[i];
// work out which date value is closest to the mouse
var d = mouseDate - d0[0] > d1[0] - mouseDate ? d1 : d0;
var x = xScale(d.timestamp);
var y = yScale(d.tide);
focus.attr("transform", "translate(" + x + "," + y + ")");
focus.select("text").text(formatValue(d.tide));
focus.select('#focusLineX')
.attr('x1', x).attr('y1', yScale(yDomain[0]))
.attr('x2', x).attr('y2', yScale(yDomain[1]));
focus.select('#focusLineY')
.attr('x1', xScale(xDomain[0])).attr('y1', y)
.attr('x2', xScale(xDomain[1])).attr('y2', y);
}
});
問題是整個焦點變量的轉換。 我將圓和文本分別定位,現在可以使用:
// focus tracking
var focus = g.append('g').style('display', 'none')
focus.append('circle')
.attr('id', 'focusCircle')
.attr('r', 4.5)
.attr('class', 'circle focusCircle')
focus.append("text")
.attr("x", 9)
.attr("dy", ".35em")
focus.append('line')
.attr('id', 'focusLineX')
.attr('class', 'focusLine')
focus.append('line')
.attr('id', 'focusLineY')
.attr('class', 'focusLine')
g.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.on("mouseover", function() { focus.style("display", null) })
.on("mouseout", function() { focus.style("display", "none") })
.on("mousemove", mousemove)
function mousemove() {
var mouse = d3.mouse(this)
var mouseDate = xScale.invert(mouse[0])
var i = bisectDate(data, mouseDate) // returns the index to the current data item
var d0 = data[i - 1]
var d1 = data[i]
// work out which date value is closest to the mouse
var d = mouseDate - d0[0] > d1[0] - mouseDate ? d1 : d0
var x = xScale(d.date)
var y = yScale(d.tide)
focus.select("text")
.attr("transform", "translate(" + x + "," + y + ")")
.text(formatValue(d.tide))
focus.select('#focusCircle')
.attr('cx', x)
.attr('cy', y)
focus.select('#focusLineX')
.attr('x1', xScale(d.date)).attr('y1', yScale(yDomain[0]))
.attr('x2', xScale(d.date)).attr('y2', yScale(yDomain[1]))
focus.select('#focusLineY')
.attr('x1', xScale(xDomain[0])).attr('y1', yScale(d.tide))
.attr('x2', xScale(xDomain[1])).attr('y2', yScale(d.tide))
}
在創建焦點線的代碼中,您正在使用當前數據點(鼠標位置)開始行。
focus.select('#focusLineX')
.attr('x1', x).attr('y1', yScale(yDomain[0]))
.attr('x2', x).attr('y2', yScale(yDomain[1]));
focus.select('#focusLineY')
.attr('x1', xScale(xDomain[0])).attr('y1', y)
.attr('x2', xScale(xDomain[1])).attr('y2', y);
您的水平線應從y軸開始,並跨越點高處的寬度。 同樣,垂直線應從圖形的頂部開始,一直到底部(x軸)。
試試這個變化
focus.select('#focusLineX')
.attr('x1', x).attr('y1', 0)
.attr('x2', x).attr('y2', heightOfChart);
focus.select('#focusLineY')
.attr('x1', 0).attr('y1', y)
.attr('x2', widthOfChart).attr('y2', y);
希望能幫助到你
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.