GSAP+Swiper+Svg实现六等分平面圆形进度条关联文本图片手动自动切换的效果

圆形使用svg代码实现,一个svg背景圆,一个svg进度条圆;进度条使用GSAP的动画操作svg的stroke-dasharray和stroke-dashoffset属性实现,实现思路是一个间隔为一个圆的周长;图片自动轮播切换使用swiper.js插件实现,因为它方法参数多,可以省去不少时间。

gsap-swiper-svg-process-circle.jpg

实现代码

插件文件:
<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:代码很粗糙,但基本实现了预期的动画效果,算是积累思路。