如何使用 JavaScript 将 SVG 数据属性添加到对象而不会变得卡顿



我正在学习使用vanilla JavaScript将SVG数据属性添加到HTML对象以适应设备宽度。我正在寻找一种在移动设备和桌面之间为不同布局加载和切换 SVG 的方法。

我使用 JavaScript setAttribute() 属性构建了一个测试,以将数据属性添加到对象元素并根据客户端浏览器窗口宽度注入外部 SVG 文件。

我从各种资源中拼凑了JavaScript代码。它有效,但结果是卡顿的。JavaScript 包含一个window.onresize函数,该函数会导致 SVG 抖动并重新加载/重新绘制。有没有办法改进此代码以减少 FLOUT?

这是代码:

    <script>
    if (window.matchMedia("(max-width: 760px)").matches) {
      /* the view port is at less than 760 pixels wide */
        document.getElementsByTagName("object")
[0].setAttribute("data", "assets/images/svg/SVG_dynamic-
test_02.svg"); 
    }
        else {
      /* the view port is more than 760 pixels wide */
        document.getElementsByTagName("object")
[0].setAttribute("data", "assets/images/svg/SVG_dynamic-
test_01.svg"); 
        };
    window.onresize=function(){
        if (window.matchMedia("(max-width: 760px)").matches) {
      /* the view port is at less than 600 pixels wide */
        document.getElementsByTagName("object")
[0].setAttribute("data", "assets/images/svg/SVG_dynamic-
test_02.svg"); 
    }
        else {
      /* the view port is more than 760 pixels wide */
        document.getElementsByTagName("object")
[0].setAttribute("data", "assets/images/svg/SVG_dynamic-
test_01.svg"); 
    }
    };
    </script>

以下是实时原型的链接:

http://craigwebbart.com/prototypes/SVG_attribute-test.htmlhttps://codepen.io/cwebba1/pen/GyLVEm

setAttribute调用中的逻辑提取到它自己的函数中,然后在事件处理程序中,将 setAttribute 的调用包装在 setTimeout 调用中(长度可以传入 0(:

function setSvgAttribute(svgName) {
    document.getElementsByTagName("object")[0].setAttribute("data", svgName);
}
...
if (window.matchMedia("(max-width: 760px)").matches) {
  /* the view port is at less than 760 pixels wide */
    setTimeout(function() { 
        setSvgAttribute("assets/images/svg/SVG_dynamic-test_02.svg");}, 0);
}...

通过调用 setTimeout ,您将暂时将执行权返回给浏览器,浏览器将利用该机会重新绘制和更新 DOM 元素的位置等。您的 SVG 闪烁是因为您通过改变 DOM 来强制浏览器传递额外的布局。

我接受了乔希的指导,并为他的建议增加了限制。最终代码如下所示:

<script>
  var delay = 150, // delay between calls, was 250
    throttled = false; // are we currently throttled?
  function setSvgAttribute(svgName) {
    document.getElementsByTagName("object")[0].setAttribute("data", svgName);
}
if (!throttled) {
  if (window.matchMedia("(max-width: 760px)").matches) {
    /* the view port is at less than 760 pixels wide */
      setTimeout(function() { 
          setSvgAttribute("assets/images/svg/SVG_dynamic-test_02.svg");}, 0);
    }
  else {
  /* the view port is more than 760 pixels wide */
    setTimeout(function() { 
        setSvgAttribute("assets/images/svg/SVG_dynamic-test_01.svg");}, 0);
  }
    throttled = true;
};
if (!throttled) {
  window.onresize=function(){
    if (window.matchMedia("(max-width: 760px)").matches) {
    /* the view port is at less than 600 pixels wide */
      setTimeout(function() { 
          setSvgAttribute("assets/images/svg/SVG_dynamic-test_02.svg");}, 0);
    }
    else {
    /* the view port is more than 760 pixels wide */
      setTimeout(function() { 
          setSvgAttribute("assets/images/svg/SVG_dynamic-test_01.svg");}, 0);
    }
  }
};
</script>

最新更新