uniapp異型無縫輪播圖實(shí)現(xiàn)完整示例
上截圖

支持 web ios android
上代碼
<template>
<view class="joy-swiper" @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd"
@touchcancel="handleTouchEnd">
<!-- 實(shí)際數(shù)據(jù)+填充數(shù)據(jù)實(shí)現(xiàn)無縫循環(huán) -->
<view class="swiper-warap" :style="{
transform: `translate3d(${offsetX}px, 0, 0)`,
transition: transitionStyle
}">
<view v-for="(item, index) in local_list" :key="index" :id="`item-${index}`" class="swiper-item"
:class="{active: currentIndex == index}" @click.stop="itemClick(item)">
<image class="image" :style="{
transition: transitionWidth,
backgroundColor: item.filePath
}" :src="item.filePath" mode="aspectFill" />
</view>
</view>
</view>
</template>
<script>
export default {
props: {
list: {
type: Array,
default: () => {
return []
}
},
autoplay: {
type: Boolean,
default: false
},
duration: {
type: Number,
default: 3000
}
},
watch: {
list: {
immediate: true,
handler(list) {
this.leng = list.length
if (1 < this.leng) {
// 復(fù)制數(shù)組 數(shù)組1 數(shù)組2 數(shù)組3
this.local_list = [...list, ...list, ...list]
this.currentIndex = list.length
clearTimeout(this.timeout2)
this.timeout2 = setTimeout(() => {
this.getItemDom().then((res) => {
this.itemWidth = res.width
this.offsetX = -this.currentIndex * this.itemWidth
clearTimeout(this.timeout3)
this.timeout3 = setTimeout(() => {
this.transitionStyle = "transform 0.2s ease-out"
this.transitionWidth = "all ease 0.2s"
clearTimeout(this.timeout2)
clearTimeout(this.timeout3)
}, 50)
})
}, 0)
} else {
this.local_list = list
this.currentIndex = 0
this.offsetX = 0
}
}
},
autoplay: {
immediate: true,
handler(val) {
this.local_autoplay = val
}
},
local_autoplay: {
handler(val) {
if (val) {
this.autoplayHandler()
} else {
this.interval && clearInterval(this.interval)
}
},
immediate: true,
}
},
data() {
return {
itemWidth: 0, // 單項(xiàng)寬度
isDragging: false, // 防止斷觸
startX: 0,
startY: 0,
distance: 0,
miniDistance: 25, // 最小距離
offsetX: 0,
damping: 0.38, // 阻尼系數(shù)
transitionStyle: "none",
transitionWidth: "all ease 0.2s",
leng: 0, // 原始數(shù)組length
currentIndex: 0, // 當(dāng)前選中項(xiàng)索引
local_list: [], // 新的數(shù)組數(shù)據(jù)
local_autoplay: false,
interval: null,
timeout1: null,
timeout2: null,
timeout3: null,
};
},
methods: {
handleTouchStart(e) {
this.distance = 0;
this.local_autoplay = false;
if (this.leng == 1) return;
this.startX = e.touches[0].pageX;
this.startY = e.touches[0].pageY;
this.isDragging = true;
// 拖拽時(shí)禁用過渡
this.transitionStyle = "none";
this.transitionWidth = "none";
},
handleTouchMove(e) {
this.local_autoplay = false;
if (this.leng == 1) return;
if (!this.isDragging) return;
// 阻止事件冒泡,上調(diào)允許上下滾動(dòng)的閾值
if (Math.abs(e.touches[0].pageY - this.startY) < 50) {
e.stopPropagation()
}
// 手姿移動(dòng)的距離
this.distance = e.touches[0].pageX - this.startX;
// 盒子實(shí)際移動(dòng)的距離 = 手勢(shì)距離 * 阻尼系數(shù)
const domDistance = this.distance * this.damping
// X軸方向位移距離,判斷允許左右滾動(dòng)的閾值
if (this.miniDistance < Math.abs(this.distance)) {
this.offsetX = -this.currentIndex * this.itemWidth + domDistance;
}
},
handleTouchEnd() {
this.local_autoplay = this.autoplay;
if (this.leng == 1) return;
if (Math.abs(this.distance) <= this.miniDistance) return;
this.changeHandler()
},
changeHandler(eventType) {
// 開啟過渡
this.transitionStyle = "transform 0.2s cubic-bezier(0.2, 0.7, 0.3, 1)";
this.transitionWidth = "all ease 0.2s";
if (eventType === 'autoplayHandler') {
this.currentIndex++;
} else {
// 計(jì)算是否超過一個(gè)item的寬度,超過則移動(dòng)一個(gè)item寬度的距離
const delta = Math.round(this.distance * this.damping / this.itemWidth);
if (1 <= Math.abs(delta)) {
// 根據(jù) distance 正負(fù)判斷滑動(dòng)的方向
if (0 < this.distance) {
this.currentIndex--;
} else {
this.currentIndex++;
}
}
}
// X軸方向位移距離
this.offsetX = -this.currentIndex * (this.itemWidth)
// 過渡動(dòng)畫結(jié)束時(shí)重置索引,實(shí)現(xiàn)無縫滑動(dòng)效果
this.timeout1 && clearTimeout(this.timeout1)
this.timeout1 = setTimeout(() => {
// 修改數(shù)據(jù)時(shí)禁用過渡動(dòng)畫以實(shí)現(xiàn)視覺欺騙,否則盒子和元素會(huì)出現(xiàn)跳動(dòng)
this.transitionStyle = "none";
this.transitionWidth = "none";
// 向右滑到 0 時(shí),截取數(shù)組3放在最前面
if (this.currentIndex === 0) {
const temp = this.local_list.splice(this.leng * 2, this.leng)
this.local_list = [...temp, ...this.local_list]
}
// 向右滑到 this.list.length * 2 時(shí),截取數(shù)組1放在最后面
if (this.currentIndex === this.leng * 2) {
const temp = this.local_list.splice(0, this.leng)
this.local_list = [...this.local_list, ...temp]
}
// 重置索引為 this.list.length
if (this.currentIndex === 0 || this.currentIndex === this.leng * 2) {
this.currentIndex = this.leng
this.offsetX = -this.currentIndex * this.itemWidth
}
// 恢復(fù)
this.isDragging = false;
}, 220)
},
autoplayHandler() {
this.interval && clearInterval(this.interval)
this.interval = setInterval(() => {
this.changeHandler('autoplayHandler')
}, this.duration);
},
getItemDom() {
return new Promise((resolve, reject) => {
let selectorQuery = uni.createSelectorQuery().in(this);
// #ifdef MP-ALIPAY
selectorQuery = uni.createSelectorQuery();
// #endif
selectorQuery
.select("#item-1")
.boundingClientRect()
.exec((res) => {
resolve(res[0])
})
})
},
itemClick(item) {
this.$emit('click', JSON.parse(JSON.stringify(item)))
}
},
destroyed() {
clearTimeout(this.timeout1)
clearTimeout(this.timeout2)
clearTimeout(this.timeout3)
clearInterval(this.interval)
},
};
</script>
<style lang="scss">
.joy-swiper {
padding-top: 100px;
width: 100vw;
overflow: hidden;
position: relative;
.swiper-warap {
display: flex;
flex-wrap: nowrap;
padding: 0 4px;
.swiper-item {
display: flex;
position: relative;
flex-shrink: 0;
padding: 0 4px;
.image {
display: block;
width: 73px;
height: 150px;
border-radius: 5px;
}
&.active .image {
width: calc(100vw - 175px);
border-radius: 5px;
}
}
}
}
</style>使用姿勢(shì)
<template>
<view>
<joy-swiper :list="swiper" @click="clickItem" />
</view>
</template>
<script>
export default {
data() {
return {
// 建議數(shù)組長(zhǎng)度在3個(gè)以上
// 假數(shù)據(jù)是用背景色代替圖片路徑,引入插件后在插件內(nèi)刪除image的backgroundColor屬性即可
swiper: [
{
filePath: '#815c94'
},
{
filePath: '#2E5A6F'
},
{
filePath: '#ed5126'
},
{
filePath: '#B6D7A8'
},
{
filePath: '#2A52BE'
},
{
filePath: '#96c24e'
},
]
}
},
methods: {
clickItem(item) {
console.log(item)
}
}
}
</script>
<style>
</style>總結(jié)
到此這篇關(guān)于uniapp異型無縫輪播圖實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)uniapp異型無縫輪播圖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript頁面跳轉(zhuǎn)常見實(shí)現(xiàn)方式匯總
這篇文章主要介紹了Javascript頁面跳轉(zhuǎn)常見實(shí)現(xiàn)方式,結(jié)合實(shí)例匯總分析了JavaScript常用的七種頁面跳轉(zhuǎn)實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
Web開發(fā)中客戶端的跳轉(zhuǎn)與服務(wù)器端的跳轉(zhuǎn)的區(qū)別
這篇文章主要介紹了Web開發(fā)中客戶端的跳轉(zhuǎn)與服務(wù)器端的跳轉(zhuǎn)的區(qū)別 ,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-03-03
JavaScript中的null和undefined用法解析
這篇文章主要介紹了JavaScript中的null和undefined用法解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
JavaScript中Obfuscator的實(shí)際操作指南
javascript-obfuscator以其強(qiáng)大的功能和豐富的配置選項(xiàng),成為了許多開發(fā)者保護(hù)代碼的得力助手,本文將帶你走進(jìn)?javascript-obfuscator的實(shí)際操作世界,從零開始,一步步學(xué)會(huì)如何使用它來提升你的JavaScript代碼安全性,需要的朋友可以參考下2025-06-06
小程序hover-class點(diǎn)擊態(tài)效果實(shí)現(xiàn)
這篇文章主要介紹了小程序hover-class點(diǎn)擊態(tài)效果實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-02-02
JavaScript判斷一個(gè)變量是否是數(shù)組的五種方式總結(jié)
在 JavaScript 編程中,我們經(jīng)常需要對(duì)不同類型的變量進(jìn)行判斷和處理,其中,判斷一個(gè)變量是否是數(shù)組是一項(xiàng)基本且常見的任務(wù),在本篇博客中,我們將介紹幾種常用的方式來判斷一個(gè)變量是否是數(shù)組,并探討它們的優(yōu)缺點(diǎn)以及適用場(chǎng)景,需要的朋友可以參考下2023-11-11
js方法數(shù)據(jù)驗(yàn)證的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)硪黄猨s方法數(shù)據(jù)驗(yàn)證的簡(jiǎn)單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-09-09

