我在D3中有一个多线图,每一行代表一个"样本"。
图表中有很大一部分是重叠的,但有些部分是分开的。我想要做的是当鼠标在线上移动时,获取该重叠部分中每个样本的ID。
目前我只能获得最顶行的ID。有没有办法将'mouseenter'
事件传播到该点的所有行并获取每个事件的ID?
这是一个最小的工作示例。在线条重叠的部分中,我基本上需要[line1, line2, line3]
或类似的东西。
<!DOCTYPE html>
<head>
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script>
var myData = "x line1 line2 line3\n\
1 63.4 62.7 72.2\n\
2 58.0 59.9 67.7\n\
3 53.3 59.1 69.4\n\
4 55.7 55.7 55.7\n\
5 58.7 58.7 58.7\n\
6 77.0 77.0 77.0\n\
7 57.9 56.7 82.3\n\
8 61.8 56.8 78.9\n\
9 69.3 56.7 68.8\n\
10 71.2 60.1 68.7\n";
var data = d3.tsvParse(myData);
var margin = {
top: 20,
right: 20,
bottom: 40,
left: 50
};
var height = 500 - margin.bottom - margin.top,
width = 960 - margin.left - margin.right;
var line = d3.line()
.x(function(d) {
return X(d.x);
})
.y(function(d) {
return Y(d.y);
});
var X = d3.scaleLinear().range([0, width]);
var Y = d3.scaleLinear().range([height, 0]);
var colour = d3.scaleOrdinal(d3.schemeCategory10);
colour.domain(d3.keys(data[0]).filter(function(key) {
return key !== "x";
}));
var lines = colour.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
x: +d.x,
y: +d[name]
};
})
};
});
var svg = d3.select('body').append('svg')
.attr('height', height + margin.top + margin.bottom)
.attr('width', width + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
X.domain(d3.extent(data, function(d) {
return d.x;
}));
Y.domain([
d3.min(lines, function(c) {
return d3.min(c.values, function(v) {
return v.y;
});
}),
d3.max(lines, function(c) {
return d3.max(c.values, function(v) {
return v.y;
});
})
]);
svg.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(X));
svg.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(Y));
var gLines = svg.selectAll('.lines')
.data(lines)
.enter().append('g')
.attr('class', 'lines');
gLines.append('path')
.attr('d', function(d) {
return line(d.values);
})
.style('stroke', function(d) {
return colour(d.name)
})
.style('fill', 'none')
.on('mouseenter', function(d) {
console.log(d.name);
});
</script>
</body>
</html>
&#13;
答案 0 :(得分:1)
您可以使用Document.elementsFromPoint()
。虽然这种方法仍被认为是实验性的,但所有主流浏览器都是implemented。
该方法将返回指定坐标下的所有元素,包括您感兴趣的路径的所有祖先。要获得您的路径,您必须应用额外的过滤:
d3.selectAll(document.elementsFromPoint(d3.event.x, d3.event.y)).filter("path");
因为访问DOM树的Stack Snippets以某种方式倾向于冻结浏览器,所以这里有JSFiddle证明了这一点。
如果将来修复这个缺点,这是工作演示:
var myData = "x line1 line2 line3\n\
1 63.4 62.7 72.2\n\
2 58.0 59.9 67.7\n\
3 53.3 59.1 69.4\n\
4 55.7 55.7 55.7\n\
5 58.7 58.7 58.7\n\
6 77.0 77.0 77.0\n\
7 57.9 56.7 82.3\n\
8 61.8 56.8 78.9\n\
9 69.3 56.7 68.8\n\
10 71.2 60.1 68.7\n";
var data = d3.tsvParse(myData);
var margin = {
top: 20,
right: 20,
bottom: 40,
left: 50
};
var height = 500 - margin.bottom - margin.top,
width = 960 - margin.left - margin.right;
var line = d3.line()
.x(function(d) {
return X(d.x);
})
.y(function(d) {
return Y(d.y);
});
var X = d3.scaleLinear().range([0, width]);
var Y = d3.scaleLinear().range([height, 0]);
var colour = d3.scaleOrdinal(d3.schemeCategory10);
colour.domain(d3.keys(data[0]).filter(function(key) {
return key !== "x";
}));
var lines = colour.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
x: +d.x,
y: +d[name]
};
})
};
});
var svg = d3.select('body').append('svg')
.attr('height', height + margin.top + margin.bottom)
.attr('width', width + margin.left + margin.right)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
X.domain(d3.extent(data, function(d) {
return d.x;
}));
Y.domain([
d3.min(lines, function(c) {
return d3.min(c.values, function(v) {
return v.y;
});
}),
d3.max(lines, function(c) {
return d3.max(c.values, function(v) {
return v.y;
});
})
]);
svg.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(X));
svg.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(Y));
var gLines = svg.selectAll('.lines')
.data(lines)
.enter().append('g')
.attr('class', 'lines');
gLines.append('path')
.attr('d', function(d) {
return line(d.values);
})
.style('stroke', function(d) {
return colour(d.name)
})
.style('fill', 'none')
.on('mouseenter', function(d) {
console.dir(d3.selectAll(document.elementsFromPoint(d3.event.x, d3.event.y)).filter("path"));
});
<script src="https://d3js.org/d3.v4.min.js"></script>