当鼠标进入条形图时,我正在处理一个带有基本缩放和工具提示显示的简单条形图。 我在d3代码的不同层上触发的两个事件之间存在冲突。我有一个svg:rect,其目的是捕获d3缩放事件,我有一个兄弟节点,一个名为layer1的svg,其中包含条形图的条形图。这些条中的每一个都是简单的svg:rect,它们是我的layer1 svg的子节点。我在每个栏上附加了mouseover和mouseout事件以显示工具提示(我使用https://github.com/Caged/d3-tip/)。
我的问题如下:
如果我尝试使用鼠标滚轮进行缩放,当鼠标位于绘图上但位于条形图外时,它可以正常工作。但是,当鼠标在条形图上时,显示d3-tip但我不能再放大/缩小,鼠标滚轮只会使整个页面向上或向下滚动。
我已经尝试过以下链接中描述的方法但没有成功:
Handling Mouse Events in Overlapping SVG Layers
我还希望通过将它附加到我的主svg后附加layer1来直接处理evt_catcher层的鼠标悬停和鼠标输出,但问题是函数tip.show和tip.hide实际上计算了工具提示的位置event.target/d3.event.target,这里将与evt_catcher层相关联,而不再与bar相关联。
所以为了使这个方法成功,我需要从鼠标的坐标获得与一个条相关联的svg节点,我不知道该怎么做。 Document.elementFromPoint()似乎很有希望,但只提供最顶层的元素,这将再次出现在evt_catcher中......
以下是一些相关代码:
// appending evt_catcher layer
this.evt_catcher = this.svg.append('rect')
.attr('class', 'overlay')
.attr('width', this.width)
.attr('height', this.height);
// appending layer1 layer (will contain the bars)
this.layer1 = this.svg.append('svg')
.attr('height', this.height)
.attr('width', this.width);
// creating the d3-tip
this.tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return d[1].toFixed(2);
});
// attaching the d3-tip to the main svg
this.svg.call(this.tip);
// defining the d3.behavior.zoom function
this.zoom = d3.behavior.zoom()
.x(this.x)
.scaleExtent([1, 32])
.on('zoom', function() {
d3.event.sourceEvent.stopPropagation();
d3.event.sourceEvent.preventDefault();
/* my zoom code */
});
});
// creating the bars representing the data
var bars = this.layer1.selectAll('.bar').data(data.series.values);
bars.transition()
.attr('x', function(d) {return that.x(d[0]);})
.attr('width', that.range_band * that.zoom.scale())
.attr('y', function(d) { return d[1] < 0 ? that.y(0): that.y(d[1]); })
.attr('height', function(d) {
return Math.abs(that.y(d[1]) - that.y(0));
});
bars.enter().append('rect')
.attr('class', 'bar')
.attr('x', function(d) {return that.x(d[0]);})
.attr('fill', 'steelblue')
.attr('width', that.range_band * that.zoom.scale())
.attr('y', function(d) { return d[1] < 0 ? that.y(0): that.y(d[1]); })
.attr('height', 0)
.on('mouseover', that.tip.show) // attaching mouseover event to trigger the display of the tooltip
.on('mouseout', that.tip.hide) //attaching mouseout event to hide the the tooltip
.transition()
.attr('height', function(d) {
return Math.abs(that.y(d[1]) - that.y(0));
});
bars.exit().transition()
.attr('height', 0)
.remove();
// attaching the zoom event to the evt_catcher layer
this.evt_catcher.call(this.zoom);
有什么想法吗?