d3.js - mouseover事件在svg组上无法正常工作 [英] d3.js - mouseover event not working properly on svg group
问题描述
我有一个图形,我需要一个参考线,鼠标光标在这个图形内。此参考线将跟随图形内的鼠标移动。
I have a graph for which I need a reference line everywhere the mouse-cursor is inside this graph. And this reference line will follow the mouse movements inside the graph.
但这似乎不工作。它只适用于轴的轴和刻度(轴线)。
But this doesn't seems to work fine. It works only on the axis and the ticks (.axis lines) of the axis. On debugging, I found that mouse event works fine when applied over SVG but not on the group, why so ?
这是我的代码:
<html>
<head>
<script src="jquery.js">
</script>
<script src="d3.v2.js">
</script>
<script src="retest.js">
</script>
<style type="text/css">
.g_main {
cursor:pointer;
}
.axis path, .axis line {
stroke: #DBDBDB;
/*shape-rendering: crispEdges;
*/
}
.y g:first-child text {
display:none;
}
.y g:first-child line {
stroke: #989898 ;
stroke-width: 2.5px;
}
/*.x g:first-child line {
stroke: black ;
stroke-width: 2.5px;
}
*/
.y path {
stroke: #989898 ;
stroke-width: 2.5px;
}
</style>
</head>
<body>
<center>
<button id="reload" onclick="loadViz();">
load Graph
</button>
<div id="viz" class="viz">
</div>
</center>
<script>
loadViz();
</script>
</body>
</html>
retest.js
retest.js
var series,
classifications,
minVal,
maxVal,
svgW = 600,
svgH = 600,
//w = 1200,
//h = 1200,
vizPadding = {
top: 120,
right: 30,
bottom: 120,
left: 50
},
yAxMin_PA = 0,
yAxMax_PA = 50,
xAxMin_PA = 2002,
xAxMax_PA = 2008,
areaStrokeColors = ['#FF6600', '#3366FF', '#B8860B', '#458B00', 'white'];
var loadViz = function () {
color = d3.scale.category10();
data = {
"lines": [{
"line": [{
"X": 2002,
"Y": 42
}, {
"X": 2003,
"Y": 45
},
{
"X": 2005,
"Y": 47
},
{
"X": 2007,
"Y": 41
}
]
}, {
"line": [{
"X": 2003,
"Y": 33
}, {
"X": 2005,
"Y": 38
}, {
"Y": 36,
"X": 2008
}
]
}, {
"line": [{
"X": 2004,
"Y": 13
}, {
"X": 2005,
"Y": 19
}, {
"X": 2008,
"Y": 21
}
]
}, {
"line": [{
"X": 2003,
"Y": 20
}, {
"X": 2005,
"Y": 27
}, {
"X": 2008,
"Y": 29
}
]
}
]
};
$("#viz").html("");
buildBase();
//setScales();
};
var buildBase = function () {
margin = {
top: 80,
right: 120,
bottom: 40,
left: 40
},
width = 960 - margin.left - margin.right,
height = 550 - margin.top - margin.bottom;
t2 = height + margin.top + margin.bottom;
x = d3.scale.linear()
.domain([xAxMin_PA, xAxMax_PA])
.range([0, width]);
y = d3.scale.linear()
.domain([yAxMin_PA, yAxMax_PA])
.range([height, 0]);
tickSizeToApplyX = 5;
tickSizeToApplyY = 10;
// Function to draw X-axis
xAxis = d3.svg.axis()
.scale(x)
.ticks(tickSizeToApplyX)
.tickSize(-height, 0, 0)
//.tickSize(10)
.orient("bottom")
.tickPadding(5);
// Function to draw Y-axis
yAxis = d3.svg.axis()
.scale(y)
.ticks(tickSizeToApplyY)
.tickSize(-width, 0, 0)
//.tickSize(0)
.orient("left")
.tickPadding(5);
// Define the line
var valueline = d3.svg.line()
.x(function (d) { /*console.log(d.X);*/
return x(d.X);
})
.y(function (d) { /*console.log(d.Y);*/
return y(d.Y);
});
// Define the line
var referline = d3.svg.line()
.x(function (dx) { /*console.log(d.X);*/
return dx;
})
.y(function (dy) { /*console.log(d.Y);*/
return dy;
});
// Append SVG into the html
var viz = d3.select("#viz")
.append("svg")
.attr("width", width + margin.left + margin.right + 10)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("class", "g_main")
.attr("transform", "translate(" + margin.left + "," + ((margin.top) - 30) + ")");
viz.on("mousemove", function () {
cx = d3.mouse(this)[0];
cy = d3.mouse(this)[1];
console.log("xx=>" + cx + "yy=>" + cy);
redrawline(cx, cy);
})
.on("mouseover", function () {
d3.selectAll('.line_over').style("display", "block");
})
.on("mouseout", function () {
d3.selectAll('.line_over').style("display", "none");
});
//console.log(this);
viz.append("line")
//d3.select("svg").append("line")
.attr("class", 'line_over')
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", x(xAxMax_PA))
.attr("y2", 0)
.style("stroke", "gray")
.attr("stroke-dasharray", ("5,5"))
.style("stroke-width", "1.5")
.style("display", "none");
// Draw X-axis
viz.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Draw Y-axis
viz.append("g")
.attr("class", function (d, i) {
return "y axis"
})
.call(yAxis);
function redrawline(cx, cy) {
d3.selectAll('.line_over')
.attr("x1", 0)
.attr("y1", cy)
.attr("x2", x(xAxMax_PA))
.attr("y2", cy)
.style("display", "block");
}
};
推荐答案
g
元素只是一个空容器,无法捕获点击事件(请参阅文档 pointer-events
属性)。
The g
element is just an empty container which cannot capture click events (see documentation for pointer-events
property for details).
但是,鼠标事件会冒泡。因此,您可以通过首先确保 g
接收所有指针事件来实现您的期望效果:
However, mouse events do bubble up to it. Hence, the effect you desire can be achieved by first making sure that the g
receives all pointer events:
.g_main {
// ..
pointer-events: all;
}
然后将一个不可见的矩形添加到它作为一个地方悬停: / p>
And then appending an invisible rectangle to it as a place to hover over:
viz.on("mousemove", function () {
cx = d3.mouse(this)[0];
cy = d3.mouse(this)[1];
redrawline(cx, cy);
})
.on("mouseover", function () {
d3.selectAll('.line_over').style("display", "block");
})
.on("mouseout", function () {
d3.selectAll('.line_over').style("display", "none");
})
.append('rect')
.attr('class', 'click-capture')
.style('visibility', 'hidden')
.attr('x', 0)
.attr('y', 0)
.attr('width', width)
.attr('height', height);
工作示例: http://jsfiddle.net/H3W3k/
至于为什么应用于 svg
元素(从文档):
As for why they work when applied to the svg
element (from the docs):
请注意,'svg'元素不是图形元素,在一个符合SVG的独立文件中,最顶端的'svg'元素永远不会是指针事件的目标,虽然事件可以冒泡到这个元素。如果指针事件不导致对图形元素的肯定的命中测试,则它应当引起任何用户代理特定的窗口行为,诸如呈现上下文菜单或控件以允许SVG文档片段的缩放和平移。
Note that the ‘svg’ element is not a graphics element, and in a Conforming SVG Stand-Alone File a rootmost ‘svg’ element will never be the target of pointer events, though events can bubble to this element. If a pointer event does not result in a positive hit-test on a graphics element, then it should evoke any user-agent-specific window behavior, such as a presenting a context menu or controls to allow zooming and panning of an SVG document fragment.
这篇关于d3.js - mouseover事件在svg组上无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!