【问题标题】:How do I use JavaScript to add SVG Data Attributes to Objects without being Janky?如何使用 JavaScript 将 SVG 数据属性添加到对象而不是 Janky?
【发布时间】:2018-01-24 19:25:09
【问题描述】:

我正在学习使用 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.html https://codepen.io/cwebba1/pen/GyLVEm

【问题讨论】:

    标签: javascript html svg


    【解决方案1】:

    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 来强制浏览器进行额外的布局传递。

    【讨论】:

    • 太棒了!感谢您建议 setTimeout() 我制作了一个新原型并在这里进行了测试:link 它有帮助。还是有些抖动。我查找了 setTimeout 教程,发现:优化 window.onresize link 这是关于节流和去抖动的。我盲目地刺伤并添加了节流。适用于这个用例。示例:link 再次感谢您的帮助!我永远不会得到它!
    • 天哪 - 油门示例的链接不正确,stackoverflow 不允许我编辑它。这是 setTimeout/throttle 示例的正确链接:link
    【解决方案2】:

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

    <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>
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-15
    • 2021-03-15
    • 1970-01-01
    • 1970-01-01
    • 2016-06-12
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    相关资源
    最近更新 更多