ger*_*nte 15 svg position tooltip d3.js
我有一个带有SVG的网页.在某些形状上,我需要显示工具提示.但是,我无法将工具提示显示在它应该的位置,只是距离形状本身一些像素.
它出现在屏幕的右侧,可能距离大约300px.我用来获取坐标的代码如下:
d3.select("body")
.select("svg")
.select("g")
.selectAll("circle")
.on("mouseover", function(){return tooltip.style("visibility", "visible");})
.on("mousemove", function(){
var svgPos = $('svg').offset(),
/*** Tooltip ***/
//This should be the correct one, but is displaying at all working at all.
/*x = svgPos.left + d3.event.target.cx.animVal.value,
y = svgPos.top + d3.event.target.cy.animVal.value;*/
//This displays a tool tip but way much to the left of the screen.
x = svgPos.left + d3.event.target.cx.animVal.value,
y = svgPos.top + d3.event.target.cy.animVal.value;
Tooltip
window.alert("svgPos: "+svgPos+" top: "+y+"px left: "+x+"px "+d3.event.target.cx.animVal.value);
return tooltip.style("top", x+"px").style("left",y+"px");
})
.on("mouseout", function(){return tooltip.style("visibility", "hidden");});
Run Code Online (Sandbox Code Playgroud)
我在这篇SO帖子之后得到了这段代码.
我更改了$(ev.target).attr(cx),因为它没有在我的机器上返回值; d3.event.target.cx是,尽管它似乎并没有影响最终结果.
我究竟做错了什么?有人可以帮帮我吗?非常感谢你的时间.
Ame*_*aBR 31
如果您的工具提示是HTML元素,那么您希望将其相对于页面整体定位,而不是内部SVG坐标,因此访问cx/cy值只会使事情变得复杂.我不能说肯定不看你的代码,但如果你对你的任何变换<svg>或<g>元素,那么这可能是什么你扔了.
但是,有一个更容易的解决方案.只需访问鼠标事件的默认.pageX和.pageY属性,它们给出鼠标相对于HTML主体的位置,并使用这些坐标来定位工具提示div.
示例:http://fiddle.jshell.net/tPv46/1/
关键代码:
.on("mousemove", function () {
//console.log(d3.event);
return tooltip
.style("top", (d3.event.pageY + 16) + "px")
.style("left", (d3.event.pageX + 16) + "px");
})
Run Code Online (Sandbox Code Playgroud)
即使在SVG圆圈上进行旋转变换,鼠标也会知道它在页面上的位置,并且工具提示也相应地定位.
还有其他方法可以做到这一点,包括让工具提示显示在相对于圆圈的固定位置而不是跟随鼠标,但我刚检查了我正在处理的示例并意识到它们不是跨浏览器兼容的,所以我必须将它们标准化并回复你.与此同时,我希望这能让您重回项目.
为了比较,这里是使用HTML工具提示(<div>元素)和SVG工具提示(<g>元素)实现的相同示例.
http://fiddle.jshell.net/tPv46/4/
默认鼠标事件坐标可能非常适合定位直接子元素的HTML元素<body>,但它们对于定位SVG元素不太有用.d3.mouse()在应用了所有变换后,该函数计算当前事件相对于指定SVG元素坐标系的鼠标坐标.因此,它可用于以我们需要定位SVG工具提示的形式获取鼠标坐标.
关键代码:
.on("mousemove", function () {
var mouseCoords = d3.mouse(
SVGtooltip[0][0].parentNode);
//the d3.mouse() function calculates the mouse
//position relative to an SVG Element, in that
//element's coordinate system
//(after transform or viewBox attributes).
//Because we're using the coordinates to position
//the SVG tooltip, we want the coordinates to be
//with respect to that element's parent.
//SVGtooltip[0][0] accesses the (first and only)
//selected element from the saved d3 selection object.
SVGtooltip
.attr("transform", "translate(" + (mouseCoords[0]-30)
+ "," + (mouseCoords[1]-30) + ")");
HTMLtooltip
.style("top", (d3.event.pageY + 16) + "px")
.style("left", (d3.event.pageX + 16) + "px");
})
Run Code Online (Sandbox Code Playgroud)
请注意,即使我使用viewBox属性缩放SVG 并将工具提示放在<g>带有transform属性的a中,它仍然有效.
经过测试并适用于Chrome,Firefox和Opera(合理的最新版本) - 尽管SVG工具提示中的文本可能会超出其矩形,具体取决于您的字体设置.使用HTML工具提示的一个原因!另一个原因是它不会被SVG的边缘切断.
如果您在Safari或IE9/10/11中有任何错误,请发表评论.(IE8及以下版本都运气不好,因为他们不做SVG).
那么你最初的想法是什么,将工具提示定位在圆圈本身上?能够准确定位笔尖有一定的好处:更好的布局控制,文本不会随着鼠标摆动.最重要的是,您可以在mouseover事件中定位一次,而不是对每个mousemove事件做出反应.
但要做到这一点,你不能再只使用鼠标位置来确定放置工具提示的位置 - 你需要弄清楚元素的位置,这意味着你必须处理转换.SVG规范引入了一组接口,用于相对于DOM的其他部分定位SVG元素.
用于在您使用的两个SVG转换系统之间进行转换SVGElement.getTransformToElement(SVGElement); 用于在SVG坐标系和屏幕之间进行转换SVGElement.getScreenCTM().结果是转换矩阵,您可以从中提取净水平和垂直平移.
SVG工具提示的关键代码是
var tooltipParent = SVGtooltip[0][0].parentNode;
var matrix =
this.getTransformToElement(tooltipParent)
.translate(+this.getAttribute("cx"),
+this.getAttribute("cy"));
SVGtooltip
.attr("transform", "translate(" + (matrix.e)
+ "," + (matrix.f - 30) + ")");
Run Code Online (Sandbox Code Playgroud)
HTML工具提示的关键代码是
var matrix = this.getScreenCTM()
.translate(+this.getAttribute("cx"),
+this.getAttribute("cy"));
absoluteHTMLtooltip
.style("left",
(window.pageXOffset + matrix.e) + "px")
.style("top",
(window.pageYOffset + matrix.f + 30) + "px");
Run Code Online (Sandbox Code Playgroud)
实例:http://fiddle.jshell.net/tPv46/89/
我再次感谢任何可以在Safari或IE或任何移动浏览器中测试此内容的人的确认评论.我很确定我已经为所有东西使用了标准API,但仅仅因为API是标准的并不意味着它是普遍实现的!