圆形使用svg代码实现,一个svg背景圆,一个svg进度条圆;进度条使用GSAP的动画操作svg的stroke-dasharray和stroke-dashoffset属性实现,实现思路是一个间隔为一个圆的周长;图片自动轮播切换使用swiper.js插件实现,因为它方法参数多,可以省去不少时间。
实现代码
插件文件:
<link rel="stylesheet" type="text/css" href="js/swiper-bundle.css" media="screen"/> <script src="js/swiper-bundle.min.js"></script> <script src="js/gsap.min.js"></script> <script src="js/ScrollTrigger.min.js"></script>
HTML代码:
<div class="process">
<div class="box">
<div class="circle">
<!--svg圆形,建议使用js插入-->
<div class="process-circle" id="process-circle">
<svg viewBox="0 0 700 700"> <!-- 适配大半径 -->
<!-- 背景圆 -->
<circle class="bg" cx="350" cy="350" r="346"/>
<!-- 进度圆 -->
<circle class="ring" cx="350" cy="350" r="346"/>
</svg>
</div>
</div>
<div class="dots">
<ul class="ul">
<!--圆的六等分点,建议使用js插入-->
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<div class="pic">
<!--swiper轮播图插件html代码-->
<div class="swiper">
<div class="swiper-wrapper">
<figure class="swiper-slide">
<img class="img" src="upload/process_01.jpg" alt="图1"/>
</figure>
<figure class="swiper-slide">
<img class="img" src="upload/process_02.jpg" alt="图2"/>
</figure>
<figure class="swiper-slide">
<img class="img" src="upload/process_03.jpg" alt="图3"/>
</figure>
<figure class="swiper-slide">
<img class="img" src="upload/process_04.jpg" alt="图4"/>
</figure>
<figure class="swiper-slide">
<img class="img" src="upload/process_05.jpg" alt="图5"/>
</figure>
<figure class="swiper-slide">
<img class="img" src="upload/process_06.jpg" alt="图6"/>
</div>
</div>
</div>
</div>
</div>
<div class="text">
<div class="swiper">
<div class="swiper-wrapper">
<div class="swiper-slide item">Step 1</div>
<div class="swiper-slide item">Step 2</div>
<div class="swiper-slide item">Step 3</div>
<div class="swiper-slide item">Step 4</div>
<div class="swiper-slide item">Step 5</div>
<div class="swiper-slide item">Step 6</div>
</div>
</div>
</div>
</div>
CSS代码:
/*oprocess*/
.oprocess {
font-size:0.16rem;
max-width: (700em/16);
width: 85%;
margin:0 auto;
position: relative;
.text {
opacity: 0.2;
.cur {
opacity: 1;
}
}
.box {
position: relative;
}
.pic {
width:(600em/16);
margin:0 auto;
position: absolute;
left:50%;
top:50%;
transform: translate3d(-50%,-50%,0);
.swiper {
border-radius: 50%;
}
img {
display:block;
width:100%;
height:auto;
}
}
/*遮罩镂空*/
.circle {
mask:url(images/circle_mask.png) no-repeat center center;
-webkit-mask:url(images/circle_mask.png) no-repeat center center;
mask-size:100% 100%;
-webkit-mask-size:100% 100%;
.bg {
fill:none;
stroke:#696969;
stroke-width: (4em/16);
}
.ring {
fill:none;
stroke: @color;
stroke-width: (4em/16);
stroke-linecap:round;
stroke-dasharray:2174;
stroke-dashoffset:2174;
}
}
.dots {
li {
position: absolute;
width: 10%;
border-radius: 50%;
border:(4em/16) solid transparent;
z-index: 6;
cursor: pointer;
&:before {
display: block;
content: '';
padding-bottom: 100%;
}
&:after {
.w(62,12);
.pb(62,9);
background: url(images/square_01.svg) no-repeat center center;
background-size: contain;
.after;
left:50%;
top:50%;
transform: translate(-50%,-50%);
}
&:nth-child(1){
right: (140/700*100%);
top:(10/700*100%);
}
&:nth-child(2){
right: (2/700*100%);
transform: translate(50%,-50%);
top:50%;
}
&:nth-child(3){
right: (140/700*100%);
bottom:(15/700*100%);
}
&:nth-child(4){
left: (140/700*100%);
bottom:(15/700*100%);
}
&:nth-child(5){
left: (2/700*100%);
transform: translate(-50%,-50%);
top:50%;
}
&:nth-child(6){
left: (138/700*100%);
top:(10/700*100%);
}
}
.cur {
border-color:@color;
}
}
.process-circle {
transform: rotate(-54.9deg);
padding-bottom: 100%;
position: relative;
svg {
position: absolute;
left:0;
top:0;
width: 100%;
height: 100%;
}
}
}
@media only screen and (min-width:1025px) {
.process {
.text {
.swiper {
position: absolute;
left:0;
top:0;
width: 100%;
height: 100%;
overflow: visible;
}
.swiper-slide {
height: auto;
}
.item {
cursor: pointer;
position: absolute;
top:0;
width: (420em/16)!important;
&:nth-child(-n+3){
left:100%;
.ml(700,40);
}
&:nth-child(1),
&:nth-child(6){
.mt(700,15);
}
&:nth-child(2),
&:nth-child(5){
.mt(700,290);
}
&:nth-child(3),
&:nth-child(4){
.mt(700,540);
}
&:nth-child(n+4){
right:100%;
.mr(700,40);
text-align: right;
}
&:nth-child(3),
&:nth-child(5){
.num,
.title {
color:#fff;
}
}
}
}
}
}
js代码:
function seteq(eq){
$('.process .text .item').eq(eq).addClass('cur').siblings('.item').removeClass('cur');
$('.process .dots li').eq(eq).addClass('cur').siblings('li').removeClass('cur');
$('.process .pic .swiper-slide').eq(eq).stop().fadeIn('fast').siblings().hide();
}
$(function(){
var process = $('.process');
var processCircle = document.getElementById('process-circle');
var progressRing = processCircle.querySelector('.ring');
// 计算周长(2πr)stroke-Dashoffset间隔为一个圆周长
var circumference = 2 * Math.PI * 346 + 1; // ≈ 2174
// 初始化进度圆(完全隐藏)
progressRing.style.strokeDasharray = Math.ceil(circumference);
progressRing.style.strokeDashoffset =Math.ceil(circumference);
var _eq = 0; //记录当前index
var _clickl = gsap.timeline(); //创建点击的动画对象
var processtext = new Swiper('.process .text .swiper',{
slidesPerView:1,
loop:false,
simulateTouch:false,
allowTouchMove:false,
virtualTranslate:true,
speed:1000,
autoplay: {
delay: 1000,
stopOnLastSlide: false,
disableOnInteraction: false,
},
breakpoints: {
0:{
virtualTranslate:false,
},
1025: {
virtualTranslate:true,
}
},
on:{
init:function(){
var _index = this.realIndex;
seteq(_index);
},
transitionStart:function(swiper){
var _index = this.realIndex;
console.log(_index);
var _step = 362*_index - 65;
swiper.autoplay.stop();
if(!_clickl.isActive()){
if(_eq==5 && _index==0){
console.log(_eq);
_clickl.to(progressRing,{
strokeDashoffset:68,
duration:0.2,
onComplete: (self) => {
swiper.slideTo(_index);
seteq(_index);
_clickl.to(progressRing,{
strokeDashoffset:0,
duration:0.2,
onComplete: (self) => {
_clickl.to(progressRing,{
strokeDashoffset:-circumference,
duration:1,
ease: "power3.out",
onComplete: (self) => {
gsap.set(progressRing,{
strokeDashoffset:circumference
});
swiper.update();
swiper.slideTo(1);
swiper.autoplay.start();
_eq=0;
}
});
}
});
}
})
}else{
var _offset = circumference - _step;
_clickl.to(progressRing,{
strokeDashoffset:_offset,
duration:0.2,
ease:'linear',
onComplete: (self) => {
processtext.slideTo(_index);
seteq(_index);
processtext.autoplay.start();
}
});
_eq = _index;
}
}
}
}
});
process.find('.text .item').click(function(){
var _index = $(this).index();
processtext.slideTo(_index);
});
process.find('.dots li').click(function(){
var _index = $(this).index();
processtext.slideTo(_index);
});
});
swiper中文网:https://www.swiper.com.cn/
gsap官网:https://gsap.com/docs/v3/GSAP/
PS:代码很粗糙,但基本实现了预期的动画效果,算是积累思路。
