利用swiper写展示页面底部缩略图、滑块分页(可拖动选择页码)、放大查看功能

2,248 阅读3分钟

前几天做了个类似的项目,效果是和链接里差不多的参考链接
第一次做笔记,有错误或者不足之处望指出,虚心学习,一起进步!

先理一下步骤

  1. 实现样式
  2. 将缩略图与展示的大图关联
  3. 实现点击按钮,跳转到swiper跳转到指定页的功能
  4. 滑块页码功能
  5. 放大镜功能
  6. 补充缩略图搜索功能
  7. 取消放大镜、重置缩略图搜索

1.实现样式

因为有缩略图功能,就要用到swiper互相控制的方法
且缩略图和展示大图应该在一个页面
这里我是这样做的,展示大图class为read,缩略图为book-detail,缩略图用z-index来控制显示与隐藏

这里注意缩略图如果用display来控制显隐的话,swiper会报错 图片.png
参考Swiper缩略图控制 / Swiper互相控制

因为缩略图如下图所示,所以不能用普通swiper
swiper官网有个多行多列swiper的例子,参考多行Slides 分布
图片.png
但是按照例子复制过来,发现slides是纵向排列的,如下图,需要加上slidesPerColumnFill : 'row'
图片.png

缩略图完整代码

var lines = Math.ceil($(".gallery-thumbs").find(".swiper-slide").length/3);//缩略图行数
var galleryThumbs = new Swiper('.gallery-thumbs', {
    slidesPerView: 3,
    slidesPerColumn : lines,
    slidesPerColumnFill : 'row',//使swiper横向排列
    freeMode: true,
    watchSlidesVisibility: true,
    watchSlidesProgress: true,
    observer:true,//修改swiper自己或子元素时,自动初始化swiper
    observeParents:true,//修改swiper的父元素时,自动初始化swiper
});

2.将缩略图与展示的大图关联

参考上面Swiper缩略图控制 / Swiper互相控制例子

var galleryTop = new Swiper('.book-swiper', {
    observer:true,//修改swiper自己或子元素时,自动初始化swiper
    observeParents:true,//修改swiper的父元素时,自动初始化swiper
    thumbs: {
        swiper: galleryThumbs//将大图与缩略图关联起来
    },
    //上一页与下一页按钮
    navigation: {
        nextEl: '.next',
        prevEl: '.prev',
    },
    //页码展示
    pagination: {
        el: '.pagination',
        type: 'fraction',
    },
});

3.实现点击按钮,跳转到swiper跳转到指定页的功能

// 跳转到第一页
$(".read-page").find(".first").click(function () {
    galleryTop.slideTo(0,500,false);//第一个参数是要跳转到的swiper-slide索引,第二个是动画时间
})

跳转到指定页数同理,只需改变第一个参数就可以

4.滑块页码功能

先要实现滑块根据当前显示页码,改变长度。需要监听swiper状态改变
图片.png
html结构:

<div class="progress">
   <div class="swiper-progress">
       <span><a ondragstart="return false;" href="javascript:"></a></span>
   </div>
</div>

样式代码(SCSS):

.progress {
    width: 100%;
    height: rem(8);
    padding: 0 rem(35);
    margin-top: rem(35);
    .swiper-progress {
        position: relative;
        border-radius: rem(4);
        background-color: rgba(204,204,204,.5);
        height: 100%;
        span {
            height: rem(8);
            border-radius: rem(4);
            width: 0;
            max-width: 100%;
            background-color: #ccc;
            position: absolute;
            left: 0;
            a {
                width: rem(40);
                height: rem(40);
                border-radius: 50%;
                background-color: #434343;
                border: rem(8) solid #ccc;
                box-sizing: border-box;
                position: absolute;
                right: 0;
                top: 50%;
                transform: translate(50%,-50%);
            }
        }
    }
}

js代码:

//加到两个swiper任一一个里,因为是相互关联的,无论监听哪个swiper都能实现监听
on:{
    slideChange: function(){
        // 滑动条显示效果
        //当前页数除以总页数得出滑块宽度百分比
        var spanWidth = (this.activeIndex + 1) / bookLength * 100+"%";
        $(".swiper-progress span").css("width", spanWidth);
    },
},

到这里已经实现了页码改变,滑块也会对应改变的功能,那么触摸滑动改变页码呢?
需要用到移动端的触摸监听事件,touchstart,touchmove和touchend
先定义几个对象

var circular = document.querySelector('.swiper-progress a');//滑块
var startX = 0;//触屏开始坐标
var x = 0;
var divWidth = $(".swiper-progress span").width();//元素原始宽度

接下来是监听事件

// 获取到当前触屏所在初始的位置 和 元素 div 的初始位置
circular.addEventListener('touchstart', (e) => {
    startX = e.targetTouches[0].pageX;
    x = circular.offsetLeft;
})
// 获取到当前触摸的位置 计算出鼠标初始位置到当前位置移动的坐标
circular.addEventListener('touchmove', (e) => {
    var moveX = e.targetTouches[0].pageX - startX;
    // 改变盒子宽度
    $(".swiper-progress span").css("width", divWidth+moveX+x);
    // 禁用默认的屏幕滚动事件,一般移动端拖动都需要加上这句
    e.preventDefault();
})
circular.addEventListener('touchend', (e) => {
    // 获取最新滑块宽度除以进度条总宽度乘以总页数,就会得到现在宽度对应的页数
    // 这里我担心最后得出数字会有小数点,所以四舍五入到最近的页数
    var newIndex = Math.round($(".swiper-progress span").width() / $(".swiper-progress").width() * bookLength);
    galleryTop.slideTo(newIndex - 1,500,false);
})

5.放大镜功能

点击按钮,放大图片,并锁定swiper的默认滑动事件。再次点击,复原图片大小和位置,恢复swiper默认滑动切换事件

$(".magnifier").click(function() {
    $(this).toggleClass("focus");
    $(".book-swiper").toggleClass('swiper-no-swiping');
    if($(this).hasClass("focus")) {
      $(".book-swiper .swiper-slide-active").find("img").css('transform', 'translate(-50%, -50%) scale(1.5)');
    }else {
      $(".book-swiper .swiper-slide-active").find("img").css({'transform':'translate(-50%, -50%) scale(1)','left':'50%','top':'50%'});
    }
});

拖动图片也是监听手指在屏幕上的触摸事件,可以参考滑块页码功能

// 定义需要拖动的图片
var magnifierDiv = document.querySelector('.book-swiper .swiper-slide-active img');
// 获取手指点击屏幕的坐标
magnifierDiv.addEventListener('touchstart', (e) => {
    startX = e.targetTouches[0].pageX;
    startY = e.targetTouches[0].pageY;
    x = magnifierDiv.offsetLeft;
    y = magnifierDiv.offsetTop;
})
// 监听手指移动,重新定义图片坐标
magnifierDiv.addEventListener('touchmove', (e) => {
    // 注意这里的条件,当图片放大时移动图片。否则取消放大时划动屏幕,图片也会被拖动
    if($(".magnifier").hasClass("focus")) {
        let moveX = e.targetTouches[0].pageX - startX;
        let moveY = e.targetTouches[0].pageY - startY;
        // 移动盒子
        magnifierDiv.style.left = x + moveX + 'px';
        magnifierDiv.style.top = y + moveY + 'px';
        // 禁用默认的屏幕滚动事件
        e.preventDefault();
    }
})

6.补充缩略图搜索功能

参考页面上,点开缩略图页面还有搜索框,功能是输入数字,只显示搜索的数字页码。
这里我遍历了缩略图中所有swiper-slide,筛选出搜索的页码,并把其余兄弟元素隐藏,就实现了这个搜索功能

// 缩略图搜索
$(".search .submit").click(function() {
    var searchVal = $(".search input").val();// 获取输入框中的值
    $(this).toggleClass("focus");// 搜索和取消搜索互相切换
    if ($(this).hasClass("focus")) {
        $(".swiper-box .swiper-slide").each(function(index){
            if (searchVal == index + 1) {
                console.log($(this).find("p").text());
                $(this).siblings().hide();
            }
        });
    } else {
        cancelSearch();//取消搜索
    }
})

7.取消放大镜、重置缩略图搜索

因为取消放大镜和取消搜索会在多处用到,所以我封装成了几个方法

// 取消搜索
function cancelSearch() {  
    $(".search input").val("");// 清空输入框中的值
    $(".swiper-box .swiper-slide").show();// 显示所有元素
    $(".search .submit").removeClass("focus");
}
// 取消放大镜
function cancelMagnifier() {
    $(".book-swiper .swiper-slide-active").find("img").css({'transform':'translate(-50%, -50%) scale(1)','left':'50%','top':'50%'});
    $(".book-swiper").removeClass("swiper-no-swiping");// 恢复swiper默认滑动切换事件
    (".magnifier").removeClass("focus");
    $(".swiper-box .swiper-slide").show();
    // 更新swiper,这句不加的话缩略图样式有可能会出现问题
    galleryThumbs.update();
    cancelSearch();
};

补充点击滑块任意位置翻页

原理和上面滑块一样,获取滑块距离最左边的位置和点击屏幕的坐标位置,与总长相除乘以总页数获得当前应该跳转的页数,直接上代码。

var lines = document.querySelector('.progress');//滑块的div
var startX = 0;var linesOffsetX = 0;
// 点击滑块翻页
lines.addEventListener('touchstart', (e) => {
    startX = e.targetTouches[0].pageX;
    linesOffsetX = lines.offsetLeft;
    var newIndex = Math.round((startX - linesOffsetX ) / $(".swiper-progress").width() * bookLength);
    galleryTop.slideTo(newIndex - 1,500,false);// 翻页
});

最后

真机测试的时候发现缩略图隐藏其他相邻元素后会出现样式错乱,pc端的手机调试并不会
最后我找了网页版的真机调试 找出了问题所在
图片.png
错乱样式

图片.png 问题所在,在样式中加个width:100% !important;就可以了

参考

swiper演示
swiper中文API
云真机