【问题标题】:SVG - Draw scrolling issue with multiple instancesSVG - 绘制多个实例的滚动问题
【发布时间】:2023-01-27 02:48:13
【问题描述】:

我正在尝试创建一个页面(在 Wordpress 中),它本质上是一个时间轴。当用户滚动到下一部分时,我有一条垂直线“连接”到下一个内容部分。经过大量的反复试验,我能够创建一条在滚动时“绘制”自身的线,并在向上滚动时反转。我的问题是,当我尝试在同一页面中再次使用该代码时,它已经被绘制了——换句话说,我认为代码存在一个问题,不知道它不应该被触发。我对此知之甚少,不知道为什么它不起作用。理想情况下,我希望每一行都在查看视图框/浏览器窗口时开始绘制。

我已经尝试创建唯一 ID、唯一 div 和 ID 等。我最初认为这可能是需要唯一容器/ID 的问题。现在,我*认为这可能是因为我不知道如何告诉“线”在被拉入视野之前不可见。

这是我的笔:

// Get the id of the <path> element and the length of <path>
var triangle = document.getElementById("triangle");
var length = triangle.getTotalLength();

// The start position of the drawing
triangle.style.strokeDasharray = length;

// Hide the triangle by offsetting dash. Remove this line to show the triangle before scroll draw
triangle.style.strokeDashoffset = length;

// Find scroll percentage on scroll (using cross-browser properties), and offset dash same amount as percentage scrolled
window.addEventListener("scroll", myFunction);

function myFunction() {
  var scrollpercent = (document.body.scrollTop + document.documentElement.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight);

  var draw = length * scrollpercent;

  // Reverse the drawing (when scrolling upwards)
  triangle.style.strokeDashoffset = length - draw;
}
body {
  height: 200vh;
}

#mySVG {
  position: relative;
  top: 15%;
  left: 50%;
  width: 50px;
  height: 710px;
}
<svg id="mySVG" preserveAspectRatio="none" viewBox="0 0 4 100">
  <path fill="none" stroke="#000000" stroke-width="1"
    id="triangle" d="M 0 0 V 100 0"/>
</svg>

【问题讨论】:

    标签: svg draw scrolltrigger


    【解决方案1】:

    每当你需要操作多个元素时,你需要查询这些元素得到一个数组/列表,然后循环遍历这个数组中的所有节点。

    通常使用类名来避免像这样的非唯一 ID 是更好的方法

    let triangles = document.querySelectorAll(".triangle");
        triangles.forEach( (triangle) => {
        // do something
    });
    

    因此,将类名(或仅替换 id 属性)添加到您的 &lt;path&gt; 元素并添加滚动 EventListener

    let triangles = document.querySelectorAll(".triangle");
    
    // calculate path length and init
    triangles.forEach((triangle) => {
      let pathLength = triangle.getTotalLength();
      triangle.setAttribute("stroke-dasharray", `0 ${pathLength}`);
    });
    
    // Find scroll percentage on scroll 
    window.addEventListener("scroll", (e) => {
      drawLines(triangles);
    });
    
    function drawLines(triangle, pathLength) {
      var scrollpercent =
        (document.body.scrollTop + document.documentElement.scrollTop) /
        (document.documentElement.scrollHeight -
          document.documentElement.clientHeight);
      triangles.forEach((triangle) => {
        let pathLength = triangle.getAttribute("stroke-dasharray").split(" ")[1];
        var dashLength = pathLength * scrollpercent;
        triangle.setAttribute("stroke-dasharray", `${dashLength} ${pathLength}`);
      });
    }
    body {
      padding:0 5em;
      height: 200vh;
      margin:0;
    
    }
    
    svg {
      position: relative;
      top: 15%;
      left: 50%;
      width: 50px;
      height: 710px;
    
    }
    
    path{
      transition:0.4s 0.4s;
    }
    <svg  preserveAspectRatio="none" viewBox="0 0 4 100">
      <path fill="none" stroke="#000000" stroke-width="1" class="triangle" d="M 0 0 V 100 0" />
    </svg>
    
    <svg  preserveAspectRatio="none" viewBox="0 0 4 100">
      <path fill="none" stroke="#000000" stroke-width="1" class="triangle" d="M 0 0 V 100 0"/>
    </svg>

    您还可以使用指定 2 个参数的 stroke-dasharray 属性来简化笔画动画:

    1. 破折号
    2. 破折号差距
      stroke-dasharray="50 100"

      您甚至可以通过应用这些固定的初始属性pathLength="100"和stroke-dasharray="0 100"来跳过长度计算getTotalLength()。
      这样您就可以使用百分比,而无需计算元素的确切长度。

      let triangles = document.querySelectorAll(".triangle");
      
      // Find scroll percentage on scroll 
      window.addEventListener("scroll", (e) => {
        drawLines(triangles);
      });
      
      function drawLines(triangle, pathLength) {
        var scrollpercent =
          (document.body.scrollTop + document.documentElement.scrollTop) /
          (document.documentElement.scrollHeight -
            document.documentElement.clientHeight);
        triangles.forEach((triangle) => {
          var dashLength = 100 * scrollpercent;
          triangle.setAttribute("stroke-dasharray", `${dashLength} 100`);
        });
      }
      body {
        padding:0 5em;
        height: 200vh;
        margin:0;
      }
      
      svg {
        position: relative;
        top: 15%;
        left: 50%;
        width: 50px;
        height: 710px;
      }
      
      path{
        transition:0.4s 0.4s;
      }
      <svg  preserveAspectRatio="none" viewBox="0 0 4 100">
        <path fill="none" stroke="#000000" stroke-width="1" class="triangle" d="M 0 0 V 100 0" pathLength="100" stroke-dasharray="0 100"/>
      </svg>
      
      <svg  preserveAspectRatio="none" viewBox="0 0 4 100">
        <path fill="none" stroke="#000000" stroke-width="1" class="triangle" d="M 0 0 V 100 0" pathLength="100" stroke-dasharray="0 100"/>
      </svg>

    【讨论】:

    • 我无语。几个小时后我会回到这个问题,我可以使用这个新代码更新你吗?我无法告诉你我有多感激。相信我,我在伸出手之前尝试了一切。我相信你很忙,而且显然非常熟练。所以,只是想提前谢谢你。我会尽快更新你。对此深表感谢!
    猜你喜欢
    • 1970-01-01
    • 2022-09-28
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-23
    • 2021-07-08
    相关资源
    最近更新 更多