【问题标题】:How is it possible to implement the drawing of the SVG circle when scrolling horizontally水平滚动时如何实现SVG圆的绘制
【发布时间】:2021-08-26 22:07:50
【问题描述】:

我有宽度为 1000px、水平滚动和 SVG 图像的 div。

我在 SVG 图像中有 5 个圆圈。如何实现每 20% 的滚动绘制每个圆圈。我的意思是每个可滚动的 div -> 在里面画圈。

喜欢加载器动画:

JSFiddle

代码:

.svg-circles-progress {
    position: relative;
    top: 0;
    left: 0;
    height: 200px;
}

.svg-circles-progress svg {
    max-width: 200px;
    position: fixed;
    top: 0;
    height: 250px;
}
.horizontal-scroll {
  margin-top: 50px;
  width: 1000px;
  overflow-x: scroll;
  overflow-y: hidden;
  height: 200px;
  border: 1px solid black;
  display: flex;
  justify-content: space-between;
}

.horizontal-scroll .box {
  margin: 20px; 
  padding: 10px;
  background: blue;
  max-width: 100px;
}
<div class="draw-svg-widget">
  <div class="svg-circles-progress">
  <svg width="421" height="408" viewBox="0 0 421 408" fill="none" xmlns="http://www.w3.org/2000/svg">
  <ellipse cx="209" cy="207" rx="29" ry="29" transform="rotate(-180 209 207)" stroke="#BDBDBD" stroke-dasharray="4 4"/>
  <ellipse cx="209" cy="207" rx="74" ry="74" transform="rotate(-180 209 207)" stroke="#BDBDBD" stroke-dasharray="4 4"/>
  <ellipse cx="209" cy="207" rx="118" ry="118" transform="rotate(-180 209 207)" stroke="#BDBDBD" stroke-dasharray="4 4"/>
  <ellipse cx="209" cy="207" rx="162" ry="162" transform="rotate(-180 209 207)" stroke="#BDBDBD" stroke-dasharray="4 4"/>
  <ellipse cx="209" cy="207" rx="200" ry="200" transform="rotate(-180 209 207)" stroke="#BDBDBD" stroke-dasharray="4 4"/>
  <path d="M2.49982 207L2.49982 213.5L15.4998 213.5L15.4998 207L2.49982 207ZM358.637 84.3176C360.913 87.0937 365.009 87.4991 367.785 85.2231C370.561 82.947 370.966 78.8515 368.69 76.0754L358.637 84.3176ZM15.4998 207C15.4998 167.102 27.8331 128.179 50.8107 95.5619L40.183 88.0751C15.6617 122.884 2.49982 164.421 2.49982 207L15.4998 207ZM50.8107 95.5619C73.7883 62.9446 106.287 38.2275 143.856 24.7954L139.479 12.5543C99.3862 26.8888 64.7044 53.2664 40.183 88.0751L50.8107 95.5619ZM143.856 24.7954C181.425 11.3633 222.228 9.87282 260.677 20.5282L264.149 8.00034C223.116 -3.37086 179.572 -1.78029 139.479 12.5543L143.856 24.7954ZM260.677 20.5282C299.126 31.1835 333.341 53.4637 358.637 84.3176L368.69 76.0754C341.695 43.1485 305.181 19.3716 264.149 8.00034L260.677 20.5282Z" fill="url(#paint0_linear)"/>
  <defs>
  <linearGradient id="paint0_linear" x1="424.5" y1="229" x2="-211.5" y2="231" gradientUnits="userSpaceOnUse">
  <stop stop-color="#CE008E"/>
  <stop offset="0.512051" stop-color="#3913BA"/>
  <stop offset="0.869792" stop-color="#3913BA" stop-opacity="0"/>
  </linearGradient>
  </defs>
  </svg>
</div>

  <div class="horizontal-scroll">
    <div class="box one"> Draw Circle 1 </div>
    <div class="box two"> Draw Circle 2 </div>
    <div class="box three"> Draw Circle 3 </div>
    <div class="box four"> Draw Circle 4 </div>
    <div class="box five"> Draw Circle 5 </div>
  </div>
</div>

【问题讨论】:

  • 你的意思是从没有圈子开始?然后第一个循环将完成 0 到 20% 之间,第二个循环在 20% 到 40% 之间,第三个循环 40% 到 60%,第四个循环 60% 到 80%,第五个循环将在 100% 结束。不是吗?您希望在用户滚动页面时绘制圆圈还是只显示圆圈?
  • @SIMBIOSIS 所以,我的意思是,我有滚动(1000 像素),如果我向右滚动 200 像素 -> 绘制 1 个圆圈,向右滚动 400 像素 -> 绘制 2 个圆圈,向右滚动 600 像素 -> 绘制 3圆圈,向右滚动 800 像素 -> 绘制 4 个圆圈并向右滚动 1000 像素 -> 绘制 5 个圆圈。
  • 但是,你说的draw是什么意思?一次渲染整个圆圈还是在滚动前进时绘制路径?
  • @SIMBIOSIS 是的,随着滚动前进而绘制

标签: css animation svg scroll


【解决方案1】:

你需要使用javascript来实现你想要的。

以下是如何执行此操作的示例。我已经对代码进行了注释,因此希望您能跟随它在做什么。

// The div that scrolls
var scroller = document.querySelector(".horizontal-scroll-container");
// The five progress circles
var progressCircles = document.querySelectorAll(".progress-circles circle");

scroller.addEventListener("scroll", function(evt) {
  // Calculate the percentage that the user has scrolled. The result is a value between 0 and 1.
  //   scrollLeft is the scroll offset of the contents of .horizontal-scroll-container
  //   scrollWidth is the width of the contents of .horizontal-scroll-container
  //   offsetWidth is the width that is visible in the scroll region 
  let scrollFraction = evt.target.scrollLeft / (evt.target.scrollWidth - evt.target.offsetWidth);
  // For each of the progress circles, draw the fraction of the circumference based
  // on how far through the scroll we are.
  let rangeForEachCircle = 1 / progressCircles.length;
  progressCircles.forEach(function(ellipseElem, index) {
    let circleStart = index * rangeForEachCircle;
    setDashArray(ellipseElem, circleStart, rangeForEachCircle, scrollFraction);
  });
});

function setDashArray(circleElem, fractionStart, fractionRange, scrollFraction)
{
  let circleRadius = circleElem.r.baseVal.value;
  let circleCircumference = Math.PI * 2 * circleRadius;
  let dashFraction = (scrollFraction - fractionStart) / fractionRange;
  // If dashFraction is less than 0, then scroll hasn't reached this circle yet.
  // Clamp dash length to 0 (no dash shown).
  dashFraction = Math.max(dashFraction, 0);
  // If dashFraction is greater than 1, then we have passed this circle.
  // Clamp dash length to 1 (full circle shown).
  dashFraction = Math.min(dashFraction, 1)
  // Calculate and set the circle's dash pattern
  let dashLength = dashFraction * circleCircumference;
  circleElem.setAttribute("stroke-dasharray", dashLength + " " + circleCircumference);
}
.svg-circles-progress {
    position: relative;
    top: 0;
    left: 0;
    height: 200px;
}

.svg-circles-progress svg {
    max-width: 200px;
    position: fixed;
    top: 0;
    height: 250px;
}

.horizontal-scroll-container {
  overflow-x: scroll;
  overflow-y: hidden;
}

.horizontal-scroll {
  margin-top: 50px;
  width: 1000px;
  height: 200px;
  border: 1px solid black;
  display: flex;
  justify-content: space-between;
}

.horizontal-scroll .box {
  margin: 20px; 
  padding: 10px;
  background: blue;
  max-width: 100px;
}
<div class="draw-svg-widget">
  <div class="svg-circles-progress">
  <svg width="421" height="408" viewBox="0 0 421 408" fill="none">
    <defs>
      <linearGradient id="paint0_linear" x1="424.5" y1="229" x2="-211.5" y2="231" gradientUnits="userSpaceOnUse">
        <stop stop-color="#CE008E"/>
        <stop offset="0.512051" stop-color="#3913BA"/>
        <stop offset="0.869792" stop-color="#3913BA" stop-opacity="0"/>
      </linearGradient>
    </defs>

    <!-- grey circles -->
    <g stroke="#BDBDBD">
      <ellipse cx="209" cy="207" rx="29" ry="29"/>
      <ellipse cx="209" cy="207" rx="74" ry="74"/>
      <ellipse cx="209" cy="207" rx="118" ry="118"/>
      <ellipse cx="209" cy="207" rx="162" ry="162"/>
      <ellipse cx="209" cy="207" rx="200" ry="200"/>
    </g>
    <!-- coloured circles -->
    <g class="progress-circles" transform="rotate(-180 209 207)"
      stroke="url(#paint0_linear)" stroke-width="16" stroke-dasharray="0, 1000">
      <circle cx="209" cy="207" r="200"/>
      <circle cx="209" cy="207" r="162"/>
      <circle cx="209" cy="207" r="118"/>
      <circle cx="209" cy="207" r="74"/>
      <circle cx="209" cy="207" r="29"/>
    </g>
  </svg>
</div>

<div class="horizontal-scroll-container">
  <div class="horizontal-scroll">
    <div class="box one"> Draw Circle 1 </div>
    <div class="box two"> Draw Circle 2 </div>
    <div class="box three"> Draw Circle 3 </div>
    <div class="box four"> Draw Circle 4 </div>
    <div class="box five"> Draw Circle 5 </div>
  </div>
</div>

【讨论】:

  • 非常感谢,这是一个了不起的解决方案!
猜你喜欢
  • 1970-01-01
  • 2022-08-24
  • 2012-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-04
  • 2016-03-27
  • 1970-01-01
相关资源
最近更新 更多