无法计算 D3 v4 中 Y 轴图例上工具提示的垂直坐标
Unable to calculate vertical coordinates for tooltip on Y-axis legend in D3 v4
我创建了一个图表,其中 y 轴上的每个图例项都有一个 mouseover/tooltop。鼠标悬停会创建一个工具提示,它在 y 图例项的高度处跨越图形的宽度。我已经成功定位了工具提示的高度和宽度以及 x 轴位置,但无法想出正确的公式来定位工具提示的顶部。
var countryBox = d3.select("body").append("div")
.attr("class", "countryTip")
.style("opacity", 0);
...
/* Build mouseover infobox for each country in y axis legend in 1800 */
h.selectAll(".axis--y .tick text")
.on("mouseover", function() {
totSpec = 0;
var myElement = d3.select(this);
var countryName = myElement.text();
/* determine absolute coordinates for left edge of SVG */
var matrix = this.getScreenCTM()
.translate(+this.getAttribute("cx"), +this.getAttribute("cy"));
h.selectAll("." + countryName.replace(/\s+/g, '_')).each(function(d) {
totSpec += d.freqEnd;
totSpec -= d.freqStart;
sumSpec = sumSpec + d.freqEnd - d.freqStart;
});
var availPercent = totSpec / availSpec;
countryBox.transition()
.duration(200)
.style("opacity", .9);
var yText = getTranslation(d3.select(this.parentNode).attr("transform"));
countryBox.html(countryName + '</br>' + r(totSpec) + ' MHz assigned out of ' + r(availSpec) + ' MHz available. <br><b>Band occupancy ' + p(availPercent) + '</b>')
.style("left", (window.pageXOffset + matrix.e) + "px")
.style("top", (yText[1] - y.bandwidth()/2 - window.pageYOffset) + "px")
.style("height", y.bandwidth() + "px")
.style("width", width + "px");
console.log("yText[1]: " + yText[1] + " halfBand: " + halfBand + " margin.top: " + margin.top + " window.pageYOffset: " + window.pageYOffset );
})
.on("mouseout", function() {
countryBox.transition()
.duration(500)
.style("opacity", 0);
});
其中
getTranslation
是 到
的函数
function getTranslation(transform) {
var g = document.createElementNS("http://www.w3.org/2000/svg", "g");
g.setAttributeNS(null, "transform", transform);
var matrix = g.transform.baseVal.consolidate().matrix;
return [matrix.e, matrix.f];
}
对于
.style("top", (yText[1] - y.bandwidth()/2 - window.pageYOffset) + "px")
yText[1]
returns 鼠标经过的 y 图例项的 y 坐标,基本上是相关国家/地区波段的垂直中点。
y.bandwidth()/2
表示垂直高度的一半
乐队和
window.pageYOffset
补偿滚动
据我所知,这应该将工具提示的顶部放在相关 x 波段的顶部。显然不是。 bootstrap 是一个因素吗?如果涉及到纯 svg,我发现我可以使用 yText[1]
作为圆的中心点在每个波段上绘制一个完美布局的圆。我是否混淆了 svg 和 html?
CSS
div.countryTip {
position: fixed;
z-index: 99;
text-align: left;
font-family: arial;
font-size: 1em;
line-height: 1.5;
padding: 1.5em;
background: #144667;
border: 0px;
color: white;
border-radius: 3px;
pointer-events: none;
-webkit-transform: translate3d(0, -0.5em, 0);
-moz-transform: translate3d(0, -0.5em, 0);
transform: translate3d(0, -0.5em, 0);
-webkit-transition: opacity 0.1s, -webkit-transform 0.1s;
-moz-transition: opacity 0.1s, -moz-transform 0.1s;
transition: opacity 0.1s, transform 0.1s;
}
更新:添加了 Plunker
向@Gerald Furtado 致敬,他指出我需要为 SVG 元素添加容器 div 的顶部偏移量。
.style("top", (document.getElementById(divID).offsetTop + yText[1] - window.pageYOffset) + "px")
完成了这项工作,尽管我无法解释工具提示上不同选项卡的垂直差异。
终于解决了这个问题。我混淆了 SVG 和 HTML 坐标系。答案是使用由 getScreenCTM()
定义的矩阵坐标的 y 元素
let matrix = this.getScreenCTM()
.translate(+this.getAttribute('cx') +this.getAttribute('cy'))
结果为
.style('top', matrix.f - y.bandwidth() / 2 + 8 + 'px')
SVG 工具提示 understanding SVG coordinates and this practical example 上的 post 帮助我最终实现了目标。
我创建了一个图表,其中 y 轴上的每个图例项都有一个 mouseover/tooltop。鼠标悬停会创建一个工具提示,它在 y 图例项的高度处跨越图形的宽度。我已经成功定位了工具提示的高度和宽度以及 x 轴位置,但无法想出正确的公式来定位工具提示的顶部。
var countryBox = d3.select("body").append("div")
.attr("class", "countryTip")
.style("opacity", 0);
...
/* Build mouseover infobox for each country in y axis legend in 1800 */
h.selectAll(".axis--y .tick text")
.on("mouseover", function() {
totSpec = 0;
var myElement = d3.select(this);
var countryName = myElement.text();
/* determine absolute coordinates for left edge of SVG */
var matrix = this.getScreenCTM()
.translate(+this.getAttribute("cx"), +this.getAttribute("cy"));
h.selectAll("." + countryName.replace(/\s+/g, '_')).each(function(d) {
totSpec += d.freqEnd;
totSpec -= d.freqStart;
sumSpec = sumSpec + d.freqEnd - d.freqStart;
});
var availPercent = totSpec / availSpec;
countryBox.transition()
.duration(200)
.style("opacity", .9);
var yText = getTranslation(d3.select(this.parentNode).attr("transform"));
countryBox.html(countryName + '</br>' + r(totSpec) + ' MHz assigned out of ' + r(availSpec) + ' MHz available. <br><b>Band occupancy ' + p(availPercent) + '</b>')
.style("left", (window.pageXOffset + matrix.e) + "px")
.style("top", (yText[1] - y.bandwidth()/2 - window.pageYOffset) + "px")
.style("height", y.bandwidth() + "px")
.style("width", width + "px");
console.log("yText[1]: " + yText[1] + " halfBand: " + halfBand + " margin.top: " + margin.top + " window.pageYOffset: " + window.pageYOffset );
})
.on("mouseout", function() {
countryBox.transition()
.duration(500)
.style("opacity", 0);
});
其中
getTranslation
是
function getTranslation(transform) {
var g = document.createElementNS("http://www.w3.org/2000/svg", "g");
g.setAttributeNS(null, "transform", transform);
var matrix = g.transform.baseVal.consolidate().matrix;
return [matrix.e, matrix.f];
}
对于
.style("top", (yText[1] - y.bandwidth()/2 - window.pageYOffset) + "px")
yText[1]
returns 鼠标经过的 y 图例项的 y 坐标,基本上是相关国家/地区波段的垂直中点。y.bandwidth()/2
表示垂直高度的一半 乐队和window.pageYOffset
补偿滚动
据我所知,这应该将工具提示的顶部放在相关 x 波段的顶部。显然不是。 bootstrap 是一个因素吗?如果涉及到纯 svg,我发现我可以使用 yText[1]
作为圆的中心点在每个波段上绘制一个完美布局的圆。我是否混淆了 svg 和 html?
CSS
div.countryTip {
position: fixed;
z-index: 99;
text-align: left;
font-family: arial;
font-size: 1em;
line-height: 1.5;
padding: 1.5em;
background: #144667;
border: 0px;
color: white;
border-radius: 3px;
pointer-events: none;
-webkit-transform: translate3d(0, -0.5em, 0);
-moz-transform: translate3d(0, -0.5em, 0);
transform: translate3d(0, -0.5em, 0);
-webkit-transition: opacity 0.1s, -webkit-transform 0.1s;
-moz-transition: opacity 0.1s, -moz-transform 0.1s;
transition: opacity 0.1s, transform 0.1s;
}
更新:添加了 Plunker
向@Gerald Furtado 致敬,他指出我需要为 SVG 元素添加容器 div 的顶部偏移量。
.style("top", (document.getElementById(divID).offsetTop + yText[1] - window.pageYOffset) + "px")
完成了这项工作,尽管我无法解释工具提示上不同选项卡的垂直差异。
终于解决了这个问题。我混淆了 SVG 和 HTML 坐标系。答案是使用由 getScreenCTM()
定义的矩阵坐标的 y 元素let matrix = this.getScreenCTM()
.translate(+this.getAttribute('cx') +this.getAttribute('cy'))
结果为
.style('top', matrix.f - y.bandwidth() / 2 + 8 + 'px')
SVG 工具提示 understanding SVG coordinates and this practical example 上的 post 帮助我最终实现了目标。