垂直滚动时修复SVG元素,Firefox问题

时间:2018-07-02 16:18:42

标签: javascript d3.js svg browser scroll

当尝试在可滚动div内垂直固定SVG项目时,请将其y坐标设置为scrollTop属性,如以下示例所示:

var container = document.getElementById('container');
var fixedText = document.getElementById('fixed-text');
fixedText.setAttribute('y', container.scrollTop + 50);
 container.addEventListener('scroll', function() {
   fixedText.setAttribute('y', container.scrollTop + 50);
 });
    div {
      border: 1px solid black;
      width: 300px;
      height: 300px;
      margin: auto;
      overflow: auto;
    }
    svg {
      width: 400px; 
      height: 2000px;
    }
    text {
      text-anchor: middle;
    }
  <div id="container">
    <svg>
      <text id="fixed-text" x="200" y="50">Fixed text vertically, but not horizontally</text>
    </svg>
  </div>

JSFiddle:https://jsfiddle.net/fr4top2g/10/

SVG项目已在Chrome中正确修复,但我在Firefox中遇到问题,该项目似乎在div内的视图框更新之前已定位,从而导致其在屏幕上振荡,而不是被固定为预期。 (在使用鼠标滚轮滚动时尤其明显。)

您是否有解决此问题的简单方法的线索,可能是Chrome和Firefox中的滚动处理方式不同?

注1:由于该项目可能太宽而无法容纳div,因此它也必须是水平可滚动的,这意味着如果解决方案不涉及将SVG项从其容器可滚动div中放出,则将更加简单

注2:请注意,如果我们在Firefox中打开Web控制台,单击SVG项目,然后用鼠标滚轮垂直滚动,则该问题似乎由于某种原因而得到解决。

注3:我已经在该项目中使用了D3.js,因此任何涉及它的解决方案都不会困扰我。我目前不使用JQuery,即使有可能的话也可以。

注释4:为此主题提供的解决方案中出现了相同的问题:Fixing an element on Y axis, but scrolling with page on x axis?

在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

Firefox滚动管理与DOM元素更新异步完成,如本页中所述:https://developer.mozilla.org/en-US/docs/Mozilla/Performance/Scroll-linked_effects

我最终设法不使用Java脚本,而是使用一些CSS以及SVG异物来修复SVG项目:

    #container {
      border: 1px solid black;
      width: 300px;
      height: 300px;
      margin: auto;
      overflow: auto;
    }
    svg#outer-svg {
      width: 400px;
      height: 2000px;
    }
    text {
      text-anchor: middle;
    }
    #inner-svg {
      position: sticky;
      top: 70px;
      width: 400px;
      height: 50px;
    }
    <div id="container">
      <svg id="outer-svg">
        <foreignObject id="foreign-object" width="100%" height="100%">
          <body xmlns="http://www.w3.org/1999/xhtml">
            <svg id="inner-svg">
              <text x="200" y="30">Fixed text vertically, but not horizontally</text>
            </svg>
          </body>
        </foreignObject>
      </svg>
    </div>