RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1272099
Accepted
Sevastopol'
Sevastopol'
Asked:2022-04-19 22:16:02 +0000 UTC2022-04-19 22:16:02 +0000 UTC 2022-04-19 22:16:02 +0000 UTC

如何为 SVG 元素绘制动画和页面滚动动画设置相同的时间?

  • 772

我有一个 SVG 元素。我通过指向页面滚动的链接开始绘制边框的动画。以下是此类动画的示例:

const htmlElem = document.querySelector("html");
const pathElem = document.querySelector(".path");
const dashOffset = parseInt(getComputedStyle(pathElem).strokeDashoffset);
document.addEventListener("scroll", () => {
  const percentageComplete =
    (window.pageYOffset / (htmlElem.offsetHeight - window.innerHeight)) * 100;
  const offsetUnit = (percentageComplete * dashOffset) / 100;
  pathElem.style.strokeDashoffset = dashOffset - offsetUnit;
});

//прогресс
let x = $('.progress');
$(window).on('scroll',function(){
  let st = $(window).scrollTop();
  let sa = $(document).height();
  let sb = $(window).height();
  let dd = Math.ceil(100 * (st / (sa - sb)));
  x.css({width : dd + '%'})
})
body {margin: 0; height: 3000px;}

.progress {position: fixed; top: 0; left: 0; width: 0%; height: 5px; background-color: red;}
.progress::after {content: "Крутим вниз"; white-space: nowrap; position: absolute; top: 15px; left: 15px;}

#svg {
  position: fixed;
  top: 0;
  left: -200px;
}

path {
  stroke-dashoffset: 2000;
  stroke-dasharray: 2000;
  fill: none;
  stroke: darkorange;
  stroke-width: 6px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="progress"></div><!--прогресс-->

<svg id="svg" width="640" height="480">
<g>

<circle fill="orange" stroke="orangered" stroke-width="6px" r="13.53787" cy="287.50003" cx="279.99998"/>

<path class="path" d="m396.35663,311.25821c-13.41742,-10.47318 -28.76758,-3.96683 -43.5509,-4.75632c-12.93182,-11.07962 -28.66629,2.3475 -40.85934,-8.33789c-15.77493,-14.05475 11.56558,-22.86807 5.7373,-39.56415c-0.65771,-24.0419 -10.94836,-45.81717 -21.77539,-66.02428c-7.65988,-16.06839 -4.94803,-34.53508 -7.41699,-51.7166c-8.85388,-12.34473 -17.69766,-27.62405 -7.16412,-42.87289c11.90973,-12.87106 6.30396,-29.77943 1.62924,-44.65391c12.03101,3.54156 25.85321,19.66071 41.68884,16.43285c10.75632,-6.93137 17.29297,-0.08103 19.09409,12.61797c5.64624,16.29109 8.93484,38.5827 26.75375,43.83432c18.70941,5.34254 39.6553,6.52644 54.44867,22.20027c27.06769,25.3474 39.60474,65.31624 38.552,103.83789c2.43921,18.01105 25.04413,8.44919 36.23547,11.10004c18.74976,-0.82904 36.76111,5.06967 54.91443,9.1069c16.20013,4.31042 29.92078,-9.31888 45.14905,-10.9483c2.57037,15.745 -17.41418,22.30164 -28.33221,27.15833c-12.95184,5.51471 -26.98676,5.64691 -40.29266,1.6095c-28.78772,-7.18442 -59.29565,-5.29221 -86.63629,7.31573c-14.76294,5.44357 -29.09103,15.73447 -45.14957,14.43954l-3.02536,-0.77902l0,0l0,0z" />

</g>
</svg>

如示例所示,动画在页面完成滚动之前结束。

问题:如何将在页面滚动上绘制 SVG 元素边框的动画与页面滚动时间计时,以便动画在页面滚动结束时准确结束?

javascript
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Alexander Lonberg
    2022-04-22T22:07:18Z2022-04-22T22:07:18Z

    为什么不使用默认的pathLength?

    毕竟,如果对指定的值没有特别的偏好dashoffset/dasharray =2000,pathLength可以解决所有问题。

    安装 ...

    // HTML
    <path pathLength="100" ...
    
    // CSS
    stroke-dashoffset: 100
    stroke-dasharray: 100
    

    ...并以相对百分比计算所有内容,就像进度一样。

    下面是一个例子:

    const htmlElem = document.querySelector("html")
    const progress = document.querySelector(".progress")
    const pathElem = document.querySelector(".path")
    
    // Дабавлю относительный калькулятор
    function rangeCalculator(begin, end, beginRange = 0, endRange = 100) {
      const inputRange = end - begin
      const outRange = endRange - beginRange
      return /*calculate*/(current) => (
        beginRange + (outRange / (inputRange / (current - begin)))
      )
    }
    
    // Сразу создадим функцию расчета относительно scroll
    // Есть один момент:
    //   Если пользователь изменит размер окна - калькулятор собъется,
    //   а значит нужно его перерасчитать
    const calculate = (() => {
      let calc
      const remake = () => calc = rangeCalculator(0, htmlElem.scrollHeight - htmlElem.clientHeight)
      window.addEventListener('resize', remake)
      remake()
      // На выходе получим значение в диапазоне 0 - 100
      return (v) => calc(v)
    })()
    
    document.addEventListener("scroll", () => {
      const percent = calculate(htmlElem.scrollTop)
      // Собственно передаем всем подряд наши проценты
      progress.style.width = `${percent}%`
      pathElem.style.strokeDashoffset = 100 - percent
    })
    body {
      margin: 0;
      height: 3000px;
    }
    
    .progress {
      position: fixed;
      top: 0;
      left: 0;
      width: 0%;
      height: 5px;
      background-color: red;
    }
    
    .progress::after {
      content: "Крутим вниз";
      white-space: nowrap;
      position: absolute;
      top: 15px;
      left: 15px;
    }
    
    #svg {
      position: fixed;
      top: 0;
      left: -200px;
    }
    
    path {
      stroke-dashoffset: 100;
      stroke-dasharray: 100;
      fill: none;
      stroke: darkorange;
      stroke-width: 6px;
    }
    <div class="progress"></div>
    
    <svg id="svg" width="640" height="480">
        <g>
          <circle fill="orange" stroke="orangered" stroke-width="6px" r="13.53787" cy="287.50003" cx="279.99998" />
          <path class="path" pathLength="100"
            d="m396.35663,311.25821c-13.41742,-10.47318 -28.76758,-3.96683 -43.5509,-4.75632c-12.93182,-11.07962 -28.66629,2.3475 -40.85934,-8.33789c-15.77493,-14.05475 11.56558,-22.86807 5.7373,-39.56415c-0.65771,-24.0419 -10.94836,-45.81717 -21.77539,-66.02428c-7.65988,-16.06839 -4.94803,-34.53508 -7.41699,-51.7166c-8.85388,-12.34473 -17.69766,-27.62405 -7.16412,-42.87289c11.90973,-12.87106 6.30396,-29.77943 1.62924,-44.65391c12.03101,3.54156 25.85321,19.66071 41.68884,16.43285c10.75632,-6.93137 17.29297,-0.08103 19.09409,12.61797c5.64624,16.29109 8.93484,38.5827 26.75375,43.83432c18.70941,5.34254 39.6553,6.52644 54.44867,22.20027c27.06769,25.3474 39.60474,65.31624 38.552,103.83789c2.43921,18.01105 25.04413,8.44919 36.23547,11.10004c18.74976,-0.82904 36.76111,5.06967 54.91443,9.1069c16.20013,4.31042 29.92078,-9.31888 45.14905,-10.9483c2.57037,15.745 -17.41418,22.30164 -28.33221,27.15833c-12.95184,5.51471 -26.98676,5.64691 -40.29266,1.6095c-28.78772,-7.18442 -59.29565,-5.29221 -86.63629,7.31573c-14.76294,5.44357 -29.09103,15.73447 -45.14957,14.43954l-3.02536,-0.77902l0,0l0,0z" />
        </g>
      </svg>

    • 1
  2. Максим Воробьев
    2022-04-20T00:58:30Z2022-04-20T00:58:30Z

    向 JS 字符串添加系数 - 1.95

    (window.pageYOffset / (htmlElem.offsetHeight - window.innerHeight) / 1.95) * 100;

    const htmlElem = document.querySelector("html");
    const pathElem = document.querySelector(".path");
    const dashOffset = parseInt(getComputedStyle(pathElem).strokeDashoffset);
    document.addEventListener("scroll", () => {
      const percentageComplete =
        (window.pageYOffset / (htmlElem.offsetHeight - window.innerHeight) / 1.95) * 100;
      const offsetUnit = (percentageComplete * dashOffset) / 100;
      pathElem.style.strokeDashoffset = dashOffset - offsetUnit;
    });
    
    //прогресс
    let x = $('.progress');
    $(window).on('scroll',function(){
      let st = $(window).scrollTop();
      let sa = $(document).height();
      let sb = $(window).height();
      let dd = Math.ceil(100 * (st / (sa - sb)));
      x.css({width : dd + '%'})
    })
    body {margin: 0; height: 3000px;}
    
    .progress {position: fixed; top: 0; left: 0; width: 0%; height: 5px; background-color: red;}
    .progress::after {content: "Крутим вниз"; white-space: nowrap; position: absolute; top: 15px; left: 15px;}
    
    #svg {
      position: fixed;
      top: 0;
      left: -200px;
    }
    
    path {
      stroke-dashoffset: 2000;
      stroke-dasharray: 2000;
      fill: none;
      stroke: darkorange;
      stroke-width: 6px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div class="progress"></div><!--прогресс-->
    
    <svg id="svg" width="640" height="480">
    <g>
    
    <circle fill="orange" stroke="orangered" stroke-width="6px" r="13.53787" cy="287.50003" cx="279.99998"/>
    
    <path class="path" d="m396.35663,311.25821c-13.41742,-10.47318 -28.76758,-3.96683 -43.5509,-4.75632c-12.93182,-11.07962 -28.66629,2.3475 -40.85934,-8.33789c-15.77493,-14.05475 11.56558,-22.86807 5.7373,-39.56415c-0.65771,-24.0419 -10.94836,-45.81717 -21.77539,-66.02428c-7.65988,-16.06839 -4.94803,-34.53508 -7.41699,-51.7166c-8.85388,-12.34473 -17.69766,-27.62405 -7.16412,-42.87289c11.90973,-12.87106 6.30396,-29.77943 1.62924,-44.65391c12.03101,3.54156 25.85321,19.66071 41.68884,16.43285c10.75632,-6.93137 17.29297,-0.08103 19.09409,12.61797c5.64624,16.29109 8.93484,38.5827 26.75375,43.83432c18.70941,5.34254 39.6553,6.52644 54.44867,22.20027c27.06769,25.3474 39.60474,65.31624 38.552,103.83789c2.43921,18.01105 25.04413,8.44919 36.23547,11.10004c18.74976,-0.82904 36.76111,5.06967 54.91443,9.1069c16.20013,4.31042 29.92078,-9.31888 45.14905,-10.9483c2.57037,15.745 -17.41418,22.30164 -28.33221,27.15833c-12.95184,5.51471 -26.98676,5.64691 -40.29266,1.6095c-28.78772,-7.18442 -59.29565,-5.29221 -86.63629,7.31573c-14.76294,5.44357 -29.09103,15.73447 -45.14957,14.43954l-3.02536,-0.77902l0,0l0,0z" />
    
    </g>
    </svg>

    • 0

相关问题

  • 第二个 Instagram 按钮的 CSS 属性

  • 由于模糊,内容不可见

  • 弹出队列。消息显示不正确

  • 是否可以在 for 循环中插入提示?

  • 如何将 JSON 请求中的信息输出到数据表 Vuetify vue.js?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    表格填充不起作用

    • 2 个回答
  • Marko Smith

    提示 50/50,有两个,其中一个是正确的

    • 1 个回答
  • Marko Smith

    在 PyQt5 中停止进程

    • 1 个回答
  • Marko Smith

    我的脚本不工作

    • 1 个回答
  • Marko Smith

    在文本文件中写入和读取列表

    • 2 个回答
  • Marko Smith

    如何像屏幕截图中那样并排排列这些块?

    • 1 个回答
  • Marko Smith

    确定文本文件中每一行的字符数

    • 2 个回答
  • Marko Smith

    将接口对象传递给 JAVA 构造函数

    • 1 个回答
  • Marko Smith

    正确更新数据库中的数据

    • 1 个回答
  • Marko Smith

    Python解析不是css

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5