无法计算D3 v4中Y轴图例上工具提示的垂直坐标

时间:2017-08-10 18:46:15

标签: javascript css d3.js tooltip

我创建了一个图表,其中y轴包含每个图例项目的鼠标悬停/ tooltop。鼠标悬停创建一个工具提示,该工具提示跨越y图例项目高度处的图形宽度。我已成功定位工具提示的高度和宽度以及x轴位置,但无法找到正确的公式来定位工具提示的顶部。

mouseover with incorrect vertical offset

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);
    });

其中

getTranslationcompensate for the absence of d3.transform in v4

的函数
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] 会返回鼠标经过的y图例项的y坐标,实际上是相关国家/地区范围的垂直中点。
  • y.bandwidth()/2 表示垂直高度的一半 乐队和
  • window.pageYOffset 补偿滚动

据我所见,这应该将工具提示的顶部放在相关x波段的顶部。显然不是。引导是一个因素吗?如果涉及纯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;
}

Working sitefull source

更新:添加了Plunker

2 个答案:

答案 0 :(得分:0)

给@ Gerald Furtado的小费提示,他指出我需要为SVG元素添加容器div的顶部偏移量。

.style("top", (document.getElementById(divID).offsetTop + yText[1] - window.pageYOffset) + "px")

完成了这项工作,虽然我仍然在工具提示的不同标签上得到一点垂直差异,我无法解释。

Plunker updated

答案 1 :(得分:0)

终于解决了这个问题。我混淆了SVG和HTML坐标系。答案是使用getScreenCTM()

定义的矩阵坐标的y元素
let matrix = this.getScreenCTM()
   .translate(+this.getAttribute('cx') +this.getAttribute('cy'))

结果为

.style('top', matrix.f - y.bandwidth() / 2 + 8 + 'px')

这篇关于understanding SVG coordinates的帖子以及关于SVG工具提示的这个practical example帮助我最终实现了目标。