我为我的数据改编了这个例子: D3js Graph with X and Y crosshairs, and a threshold line
我认为该域存在问题,但我无法弄明白。这是我的剧本:
更新:问题是由我定位文字的方式引起的。任何想法如何以另一种方式定位文本?
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);
}
});
答案 0 :(得分:1)
问题是整个焦点变量的转换。我将圆圈和文本分开放置,现在可以正常工作:
// 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))
}
答案 1 :(得分:0)
在创建焦点线的代码中,您使用当前数据点(鼠标位置)来开始您的线。
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);
希望有所帮助