更新:这是一年前写的练手的前端项目,没想到这么多的评论和私聊,有好多没有写清楚的地方重新再完善一下。目前效果只在h5上进行测试成功,其他地方未测试,请见谅。

可以发现uniapp自带的图片预览不能完全适应淘宝轮播需求

uni.previewImage({current:0,urls:imgsArray
});

新增:模板数据格式(自行修改拓展):需要获取到type类型,详细内容如下

// sort排序方式需要的话就添加上吧,看业务需求和后端返回的数据顺序和格式了
this.list =[
{url:"https://s1.ax1x.com/2022/05/11/OUw2HP.jpg",type:'jpg',sort:1},
{url:"https://cloud.video.taobao.com/play/u/712371218/p/2/e/6/t/1/352489605202.mp4",type:'mp4',sort:2},
{url:"https://s1.ax1x.com/2022/05/11/OUrgxg.jpg",type:'jpg',sort:2},
{url:"https://cloud.video.taobao.com/play/u/712371218/p/2/e/6/t/1/353144490876.mp4",type:'mp4',sort:2},
{url:"https://s1.ax1x.com/2022/05/11/OUrRMQ.png",type:'png',sort:3}
];

实现轮播的需求:
根据插件市场上的插件将图片和视频做一个判断,加入到swiper-item基本可以满足我们的需求
创建一个组件页面,内容基本不用改动。
我这儿就新建一个pages/detail/index.vue页面,将如下内容拷贝到新页面中

<template><view class="previewImage"  @touchmove.stop.prevent><swiper class="swiper" :current="index" @change="swiperChange" :disable-touch="swiper" :circular="false"><swiper-item v-for="(img, i) in imgs"  :key="'swiper-item-'+i" :id="'swiper-item-'+i"><view class="marea"><view:id="'movable-view-'+i":key="'movable-view-'+i"class="mview"@change="movableChange"><image@tap.stop="previewImages(index)"v-if="img.type == 'png' || img.type == 'jpg'|| img.type == 'svg' || img.type == 'jpeg'":id="'image-'+i":key="'movable-view'+i"class="image":src="":data-index="i":data-src=""mode="aspectFit"/><video @tap.stopv-else:id="'video-'+i":key="'movable-view'+i"class="image":data-index="i":enable-progress-gesture="false":src="":data-src=""show-progressobjectFit="cover"></video></view></view></swiper-item></swiper><view class="page" v-if="imgs.length > 0"><text class="text">{{ index + 1 }} / {{ imgs.length }}</text></view></view>
</template><script>
export default {name: 'my-swiper', //插件名称props: {imgs: {//图片列表type: Array,required: true,default: () => {return [];}},},data() {return {swiper:false,//是否禁用index: 0, //当前页time: 0, //定时器scale: 1 //缩放比例};},methods: {// 父子组件中传值,实现轮播和预览轮播previewImages(index){this.$emit("previewImages",index)},//图片改变swiperChange(e) {let myVideo = document.getElementById("video-"+this.index);if(myVideo !== null){let videoCtx = uni.createVideoContext("video-"+this.index)videoCtx.pause();}this.index = e.target.current; //更新当前图片index//this.swiper=true;},//移动变化movableChange(e) {/* if(this.old.scale <= 1){this.swiper=false;}else if(e.detail.x===0){this.swiper=false;} */},}
};
</script><!--使用scss,只在本组件生效-->
<style lang="scss" scoped>
.previewImage {top: 0;left: 0;width: 100%;height: 466rpx;user-select: none;background-color: #000000;.swiper {width: 100%;height: 100%;.marea {height: 100%;width: 100%;position: fixed;overflow: hidden;.mview {z-index: 9;display: flex;align-items: center;justify-content: center;width: 100%;height: 100%;.image {width: 100%;height: 100%;}}}}.page {z-index: 2;position: absolute;width: 100%;bottom: 60rpx;text-align: center;.text {position: relative;top: 40rpx;color: #fff;font-size: 26rpx;padding: 3rpx 16rpx;user-select: none;}}}
</style>

页面中如何去使用该页面组件?

<template><view class="screen-swiper detail-boby"><mySwiper v-show="previeShow" :imgs="list" ref="myswiper" @previewImages="previewImages"></mySwiper></view>
</template>
<script>import mySwiper from '@/components/my-swiper/my-swiper.vue';
export default{components: {mySwiper}, //注册插件data() {return{list: [],}},onLoad: function () {//为了演示方便,这儿直接写死的图床中的数据,正常应该是请求后端传递过来的this.list = [{url:"https://s1.ax1x.com/2022/05/11/OUw2HP.jpg",type:'jpg',sort:1},{url:"https://cloud.video.taobao.com/play/u/712371218/p/2/e/6/t/1/352489605202.mp4",type:'mp4',sort:2},{url:"https://s1.ax1x.com/2022/05/11/OUrgxg.jpg",type:'jpg',sort:2},{url:"https://cloud.video.taobao.com/play/u/712371218/p/2/e/6/t/1/353144490876.mp4",type:'mp4',sort:2},{url:"https://s1.ax1x.com/2022/05/11/OUrRMQ.png",type:'png',sort:3}];},methods: {// 预览轮播previewImages(index){if (this.list[index].type !== "mp4") {// this.previeShow = false;var stateObj = {};let that = this;let onjs = JSON.stringify(this.list)uni.navigateTo({url: '/components/kxj-previewImage/kxj-previewImage?onjs='+onjs+'&index='+index+'&id='+this.id,events: {// 监听子组件传过来的值changePreviewIndex(index){that.$refs.myswiper.index = index;},}});}},}
}</script>

以上代码只是实现了轮播图的效果,但是需求还需要点击预览,所以接下来请看
为了实现返回可以取消预览而不是突兀的返回到上一级,这儿新定义一个路由页面,图片地址连接使用json路由参数的方式进行传参

// 图片点击预览轮播
previewImages(index){// 当为音频形式的时,点击进行音频播放,不处理if (this.list[index].type !== "mp4") {// this.previeShow = false;var stateObj = {};let that = this;let onjs = JSON.stringify(this.list)uni.navigateTo({url: '/components/kxj-previewImage/kxj-previewImage?onjs='+onjs+'&index='+index+'&id='+this.id,events: {// 监听子组件传过来的值,这儿为了实现联动效果,// 即:预览翻到某一图片/视频,轮播图同样滚动到相关的地方changePreviewIndex(index){that.$refs.myswiper.index = index;},}});}
},

kxj-previewImage组件内容主要是在插件市场中安装的,找了一下没有找到,现在应该有更优雅的组件了,先把我使用的代码和位置沾出来吧:components/kxj-previewImage/kxj-previewImage.vue,同样的看需求来改,数据格式一样的话可以不用修改里面的代码

<template><view class="previewImage" :style="{ 'background-color': 'rgba(0,0,0,' + opacity + ')' }" v-if="show" @tap="close" @touchmove.stop.prevent><text @tap.stop="close" class="lg text-gray cuIcon-close close"></text><swiper class="swiper" :current="index" @change="swiperChange" :disable-touch="swiper" :circular="circular"><swiper-item v-for="(img, i) in imgs" :key="'swiper-item-'+i" :id="'swiper-item-'+i"><movable-area class="marea" scale-area><movable-view:id="'movable-view-'+i":key="'movable-view-'+i"class="mview"direction="all":out-of-bounds="false":inertia="true"damping="90"friction="2"scale="true"scale-min="1"scale-max="4":scale-value="scale"@scale="onScale"@change="movableChange"><image@tap.stopv-if="img.type == 'png' || img.type == 'jpg'|| img.type == 'svg' || img.type == 'jpeg'":id="'image-'+i":key="'movable-view'+i"class="image":src="img.url":style="{ transform: 'rotateZ(' + deg + 'deg)' }":data-index="i":data-src="img.url"mode="widthFix"@touchmove="handletouchmove"@touchstart="handletouchstart"@touchend="handletouchend"/><video @tap.stopv-else:id="'video-'+i":key="'movable-view'+i"class="image":style="{ transform: 'rotateZ(' + deg + 'deg)' }":data-index="i"@touchmove="handletouchmove"@touchstart="handletouchstart"@touchend="handletouchend":enable-progress-gesture="false":src="img.url":data-src="img.url"show-progressobjectFit="cover"></video></movable-view></movable-area></swiper-item></swiper><view class="page" v-if="imgs.length > 0"><text class="text">{{ index + 1 }} / {{ imgs.length }}</text></view><!-- <view class="save" v-if="saveBtn" @click.stop.prevent="save"><text class="text">保存</text></view> --><!-- <view class="rotate" v-if="rotateBtn" @click.stop.prevent="rotate"><text class="text">旋转</text></view> --><view class="desc" v-if="descs.length > 0 && descs.length == imgs.length && descs[index].length > 0">{{ descs[index] }}</view></view>
</template><script>import baseUrl from '@/utils/config.js';
export default {name: 'ksj-previewImage', //插件名称props: {// imgs: {//   //图片列表//     type: Array,//   required: true,//    default: () => {//        return [];//     }// },descs: {//描述列表type: Array,required: false,default: () => {return [];}},//透明度,0到1之间。opacity: {type: Number,default: 0.8},//保存按键saveBtn: {type: Boolean,default: true},//旋转按键rotateBtn: {type: Boolean,default: true},//循环预览circular:{type: Boolean,default: false}},onLoad(option) {// this.eventChannel = this.getOpenerEventChannel()let json = JSON.parse(option.onjs);// console.log(json);this.imgs = json;this.id = parseInt(option.id)// console.log(option.index)this.open(parseInt(option.index))},data() {return {imgs: [],swiper:false,//是否禁用show: true, //显示状态index: 0, //当前页deg: 0, //旋转角度time: 0, //定时器interval: 1000, //长按事件scale: 1 ,//缩放比例,id:0,};},computed: {baseUrl() {return baseUrl}},methods: {//比例变化onScale(e) {},substringShow (param) {if(param !== undefined){return param.substring(param.lastIndexOf('images/') + 7)}},//长按事件相关内容---------开始-------------------//接触开始handletouchstart(e) {var tchs = e.touches.length;if (tchs != 1) {return false;}this.time = setTimeout(() => {this.onLongPress(e);}, this.interval);return false;},//清除定时器handletouchend() {clearTimeout(this.time);if (this.time != 0) {//处理点击时间}return false;},//清除定时器handletouchmove() {clearTimeout(this.time);this.time = 0;},// 处理长按事件onLongPress(e) {var src = e.currentTarget.dataset.src;var index = e.currentTarget.dataset.index;var data = { src: src, index: index };this.$emit('longPress', data);},//长按事件相关内容---------结束-------------------//图片改变swiperChange(e) {let myVideo = document.getElementById("video-"+this.index);if(myVideo !== null){let videoCtx = uni.createVideoContext("video-"+this.index)videoCtx.pause();}this.index = e.target.current; //更新当前图片indexthis.$nextTick(function() {this.scale = 1;})this.getOpenerEventChannel().emit("changePreviewIndex",this.index);//this.deg = 0; //旋转角度//this.swiper=true;},//移动变化movableChange(e) {/* if(this.old.scale <= 1){this.swiper=false;}else if(e.detail.x===0){this.swiper=false;} */},//保存save(e) {var _this = this;var src = this.imgs[this.index];//#ifdef MP-WEIXIN//提前向用户发起授权请求uni.authorize({scope: 'scope.writePhotosAlbum',success() {console.log('kxj-previewImage:允许储存');_this.downloadImg(src);}});//#endif//#ifdef APP-PLUSthis.downloadImg(src);//#endif//#ifdef H5//非同源图片将直接打开var abtn = document.createElement('a');abtn.href = src;abtn.download = '';abtn.target = '_blank';abtn.click();//#endif},//下载并保存文件downloadImg(src) {//下载图片文件uni.showLoading({title: '大图提取中'});uni.downloadFile({url: src,success: function(res) {console.log('kxj-previewImage:下载成功');uni.hideLoading();uni.saveImageToPhotosAlbum({filePath: res.tempFilePath,success: () => {uni.showToast({title: '已保存至相册',duration: 1000});}});},fail: function() {uni.hideLoading();uni.showToast({title: '图片下载失败',icon: 'none',duration: 1000});}});},//旋转rotate(e) {this.deg = this.deg == 270 ? 0 : this.deg + 90;},//打开open(e) {if (e === null || e === '') {console.log('kxj-previewImage:打开参数无效');return;}if (!isNaN(e)) {if(e>=this.imgs.length){console.log('kxj-previewImage:打开参数无效');}else{this.index = e;}} else {var index = this.imgs.indexOf(e);if(index===-1){this.imgs = [e];this.index = 0;console.log('kxj-previewImage:未在图片地址数组中找到传入的图片,已为你自动打开单张预览模式')}else{this.index = this.imgs.indexOf(e);}}// console.log('kxj-previewImage:当前预览图片序号'+this.index);this.show = true;},//关闭close(e) {// this.show = false;// this.index = 0; //当前页this.deg = 0; //旋转角度this.time = 0; //定时器this.interval = 1000; //长按事件this.scale = 1; //缩放比例// this.$emit("colseToShow");let canNavBack = getCurrentPages();if(canNavBack && canNavBack.length>1) {  uni.navigateBack({  delta: 1  });  } else {  uni.redirectTo({url:'/pages/detail/index?id='+ this.id});}}}
};</script><!--使用scss,只在本组件生效-->
<style lang="scss" scoped>.previewImage {z-index: 9999;position: fixed;top: 0;left: 0;width: 100%;height: 100%;background-color: #000000;user-select: none;.swiper {width: 100%;height: 100%;z-index: 9999;.marea {z-index: 9999;height: 100%;width: 100%;position: fixed;overflow: hidden;.mview {display: flex;align-items: center;justify-content: center;width: 100%;height: auto;min-height: 100%;.image {width: 100%;max-height: 70vh;}}}}.close{position: absolute;z-index: 20;top: 20px;left: 20px;font-size: 30px;}.page {position: absolute;width: 100%;bottom: 20rpx;text-align: center;.text {color: #fff;font-size: 26rpx;background-color: rgba(0, 0, 0, 0.5);padding: 3rpx 16rpx;border-radius: 20rpx;user-select: none;}}.save {position: absolute;left: 10rpx;width: 120rpx;height: 56rpx;bottom: 10rpx;text-align: center;padding: 10rpx;.text {background-color: rgba(0, 0, 0, 0.5);color: #fff;font-size: 30rpx;border-radius: 20rpx;border: 1rpx solid #f1f1f1;padding: 6rpx 22rpx;user-select: none;}.text:active {background-color: rgba(100, 100, 100, 0.5);}}.rotate {position: absolute;right: 10rpx;width: 120rpx;height: 56rpx;bottom: 10rpx;text-align: center;padding: 10rpx;.text {background-color: rgba(0, 0, 0, 0.5);color: #fff;font-size: 30rpx;border-radius: 20rpx;border: 1rpx solid #f1f1f1;padding: 6rpx 22rpx;user-select: none;}.text:active {background-color: rgba(100, 100, 100, 0.5);}}.desc {position: absolute;top: 0;width: 100%;padding: 5rpx 10rpx;text-align: center;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;background-color: rgba(0, 0, 0, 0.5);color: #fff;font-size: 28rpx;letter-spacing: 3rpx;user-select: none;}
}</style>

预览效果:

注意:
使用colorui框架的时候,需要注释colorui/mian.css约在2589行

.swiper-item video {width: 100%;display: block;height: 100%;margin: 0;// 当时好像是因为视频选择问题。/* pointer-events: none; */
}

uniapp实现类似淘宝(京东)视频图片轮播和预览,并实现联动的效果(更新)相关推荐

  1. Android 仿淘宝详情视频图片混合轮播

    implementation 'com.github.bumptech.glide:glide:4.11.0' implementation 'androidx.recyclerview:recycl ...

  2. Android 视频图片 轮播,详解android 视频图片混合轮播实现

    循环添加视频view  图片view for (int i = 0 ;i if (beansarraylist.get(i).gettype()==1){ videoplayer = new nice ...

  3. 仿淘宝、头条上下轮播广告

    仿淘宝.头条上下滚动自动轮播广告效果 前言:想必大家工作久了,都会接触横向走马灯.纵向走马灯的效果.在这里介绍系统自带的控件来实现纵向走马灯(上下滚动)效果. 布局: <ViewFlippera ...

  4. 利用html5中canvas实现类似淘宝的放大图片效果

    <!DOCTYPE html> <html> <head> </head> <body> <!-- 这里定义原始图片,设置鼠标移动到图 ...

  5. javascript 图片轮播效果

    类似于淘宝首页广告图片轮播图效果,同时,点击左右箭头及下方数字键可进行切换图片 1.HTML <!DOCTYPE html> <html>     <head>   ...

  6. Android仿淘宝京东商品规格参数颜色筛选

    Android 选择商品属性sku 最近项目中使用SKU属性查询,类似淘宝京东商品的选择,在网上查询了弄了几个源码看看,发现还是实现不了多属性选择问题,再原基础上改动相当费事,所以想干脆自己处理这个问 ...

  7. 屏蔽去除CSDN上图片轮播形式的百度推广广告-20190104更新

    旧方法 之前采用的是在hosts文件中添加网址映射,从而使请求无效,添加的部分如下: 127.0.0.1 cpro.baidu.com 127.0.0.1 cpro.baidustatic.com 1 ...

  8. uniapp、uniCloud实现微信公众号自动查询淘宝京东优惠券制作过程

    uniapp.uniCloud实现微信公众号自动查询淘宝京东优惠券制作过程 微信公众号自动查询淘宝京东优惠券机器人制作教程.服务器通过uniapp提供的uniCloud云服务搭建,建议使用阿里云,不要 ...

  9. 短视频直播源码,显示和隐藏 类似淘宝加载

    短视频直播源码,显示和隐藏 类似淘宝加载的相关代码 1:当点击HomeActity中的Tab时,首先 case 1:case 2:if ( fg2== null) {fg2 = new Fragmen ...

最新文章

  1. zabbix监控之nginx状态监控(一)
  2. [FlareOn5]Ultimate Minesweeper(dnSpy新玩法)
  3. 面试时被问到「有没有职业规划时」,要怎么回答?
  4. es dsl多条件组合查询(转)
  5. C语言 嵌入式 面试小知识点(一)
  6. pyqt5让主窗口居中显示(显示在显示器的中间位置)
  7. mysql 1045错误ODBC_MySQL ERROR 1045 (28000) 错误的解决办法
  8. 单片机sleep函数的头文件_单片机空项目代码解析
  9. RTT时钟管理篇——RTT定时器超时判断理解
  10. android自定义键盘遮挡,Android软键盘遮挡的四种完美解决方案
  11. 撞击测试软件,碰撞检测用什么软件?你会用Navisworks做碰撞检测吗?
  12. 2021年中国国内生产总值(GDP)、GDP结构及人均国内生产总值分析[图]
  13. 一份完整的数据分析师成长书单
  14. 【OCR 文字识别】Python中一个不错的OCR库-EasyOCR
  15. iOS URL Scheme
  16. Promethues (普罗米修斯)详细介绍
  17. 写作历时一个月,长达8000字的年终总结——[2022年终总结]不要怕,请勇敢的向前走
  18. 计算机中的right函数,right函数用法实例
  19. python微信公众号翻译功能_10分钟教你用Python实现微信翻译机器人
  20. MVC中利用ViewBag传递Json数据时的前端处理方法

热门文章

  1. 19【C趣味算法 却是用Python解决】国王的失算(数量级太大Dev-C++中无法得出结果),考虑用Python实现
  2. java实习面试题_实习生java面试题集及详细答案
  3. 计算机表格模拟考试,计算机职称考试电子表格模拟题
  4. “麒麟”助力“鸿”鹄之志 |鸿合科技与麒麟软件开启战略合作
  5. 直方图、曲线与色彩平衡
  6. 大数据分析利器之Power BI,你是否已经掌握?
  7. Python_机器学习_算法_第1章_K-近邻算法
  8. 20210417 simulink导入CSV
  9. 华为鸿蒙os系统手表,对标Apple Watch!魅族推首款智能手表,官宣接入华为鸿蒙系统...
  10. 暴力破解(Burte Force)