水平滚动时如何实现SVG圆的绘制
How is it possible to implement the drawing of the SVG circle when scrolling horizontally
我有 div 宽度为 1000 像素、水平滚动和 SVG 图像。
我在 SVG 图像中有 5 个圆圈。如何每滚动 20% 就绘制每个圆圈。我的意思是每个可滚动 div -> 在里面画圆圈。
喜欢加载动画:
代码:
.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>
你需要使用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>
我有 div 宽度为 1000 像素、水平滚动和 SVG 图像。
我在 SVG 图像中有 5 个圆圈。如何每滚动 20% 就绘制每个圆圈。我的意思是每个可滚动 div -> 在里面画圆圈。
喜欢加载动画:
代码:
.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>
你需要使用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>