【问题标题】:Issue with SVG path not animating as expectedSVG 路径未按预期设置动画的问题
【发布时间】:2021-07-21 04:43:37
【问题描述】:

我正在使用this 关于内联 SVG 的视频教程作为参考。我正在尝试复制使 SVG 线看起来从中点向外绘制的效果。视频中的方法和我的方法之间的唯一区别是,在视频中,SVG 线具有预定义的长度,而我的方法是可变长度的。

该方法背后的想法非常简单。您制作一条任意大小的 SVG 线,然后将其 stroke-dasharray 属性设置为 '0, length/2' 并将其 stroke-dashoffset 属性设置为 '-length/2',这样就根本不会绘制该线首先,它的“起点”设置在它的中间点。然后,当相关输入字段被聚焦时,将 dasharray 属性更改为“length, 0”,将 dashoffset 属性更改为 0。这使得破折号等于线的长度。这应该使线看起来从中间点拉入,如果你从一开始就知道线的长度,确实会发生这种情况。但是,当我尝试使用没有预定长度的行来实现这种方法时,情况并非如此。我的线似乎是从线的最开头而不是从中间点开始画的。我很困惑为什么会这样。我正在使用 JavaScript 来计算行的长度。下面是我的代码的 sn-p。

function animateLine() {

  const input = document.querySelector('.input');
  const line = document.querySelector('.focus');
  
  const length = line.getTotalLength();
  
  line.style.strokeDasharray = `0, ${length/2}`;
  line.style.strokeDashoffset = `-${length/2}`;
  
  input.addEventListener('focus', function() {
    line.style.strokeDasharray = `${length}, 0`;
    line.style.strokeDashoffset = `0`;
  });
};


animateLine();
/* Input module */

.input {
  background: none;
  border: none;
  width: 100 %;
  padding: 0.5em;
  padding-left: 0;
  color: white;
  font-family: inherit;
  font-size: 0.85em;
}

.input:focus {
  outline: none;
}

.line {
  width: 100%;
  height: 2px;
  padding: 0;
  stroke: grey;
}

.focus {
  stroke: black;
  transition: all 5s;
  stroke-dasharray: 0, 10000;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <input class="input" type="text" name="review[body]" placeholder="Leave a review..." required>
  <svg xmlns="http://www.w3.org/2000/svg" class="line" viewBox="0 0 40 2" preserveAspectRatio="none">
                        <path d="M0 1 L40 1"></path>
                        <path d="M0 1 L40 1" class="focus"></path>
</svg>
</body>

</html>

我尝试使用不同的百分比,只使用值“20”作为我的半长,因为我的视口长度为“40”,但这些都不起作用。有谁知道这可能是什么问题?

【问题讨论】:

    标签: javascript html css svg stroke-dasharray


    【解决方案1】:

    我发现了问题所在。这是一个令人尴尬的错误,但我会把它留在这里,以防万一有人也遇到这个问题。

    当我为 SVG 线设置动画时,我使用“transition: all 5s”来更好地查看中间点的位置。问题是在开始时,我将 stroke-dasharray 设置为“0, 10000”使线不可见,并且我没有设置 stroke-dashoffset 属性,因为我认为我需要先弄清楚中间点是什么。然后我将这两个属性设置为它们应该使用 JavaScript 的值。这触发了启动转换,这需要 5 秒。所以当我专注于相关的输入元素时,我并没有像我想要的那样从中间点开始动画;当我加载到页面时,我没有等待 5 秒,这没有给初始动画足够的时间来完成到达该行的中间点。

    这一切都是因为我的一个误会。我的理解是 SVG 线的长度与包含它的 div 的大小成正比(因为我将“线”类的宽度设置为 100%)。但是,SVG 大小实际上是使用视口单位计算的,而不是像素或其他绝对单位。知道了这一点,我意识到我可以使用一种更简单的方法来实现我正在寻找的效果,而无需涉及 JavaScript。我们可以简单地忽略 SVG 的实际显示尺寸,而只关注我们最初设置的视口单位。浏览器实际上会使这个视口单位与默认情况下 SVG 可用的任何空间成比例。因此,我们可以简单地使用 20 个视口单位的宽度作为 SVG 线的中点,而不是计算 SVG 路径的长度,因为我们知道这些视口单位将与 SVG 可用的空间成正比.我想强调的是,只要您使用 40 的视口,这将适用于任何线长。

    /* Input module */
    
    .input {
      background: none;
      border: none;
      width: 100%;
      padding: 0.5em;
      padding-left: 0;
      color: black;
      font-family: inherit;
      font-size: 0.85em;
    }
    
    .input:focus {
      outline: none;
    }
    
    
    /* SVGs */
    
    .line {
      width: 100%;
      height: 2px;
      padding: 0;
      stroke: grey;
    }
    
    .focus {
      stroke: black;
      transition: all 2s;
      stroke-dasharray: 0, 20;
      stroke-dashoffset: -20;
    }
    
    .input:focus~.line .focus {
      stroke-dasharray: 40;
      stroke-dashoffset: 0;
    }
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    
    <body>
      <input class="input" type="text" name="review[body]" placeholder="Leave a review..." required>
      <svg xmlns="http://www.w3.org/2000/svg" class="line" viewBox="0 0 40 2" preserveAspectRatio="none">
                            <path d="M0 1 L40 1"></path>
                            <path d="M0 1 L40 1" class="focus">
                            </path>
                        </svg>
    </body>
    
    </html>

    差不多就是这样。真的是我的基本错误。

    【讨论】:

      猜你喜欢
      • 2021-10-16
      • 1970-01-01
      • 2018-07-25
      • 1970-01-01
      • 2020-07-17
      • 2015-07-31
      • 2020-01-29
      • 2018-10-31
      • 1970-01-01
      相关资源
      最近更新 更多