基于微博语法,
这里是组件使用代码
引入组件,组件的使用及属性方法在组件内部也进行了注释originalData 数据
autoPlay 是否自动播放
interval 自动播放间隔时间
indicatorDots 是否显示指示点
indicatorColor 指示点颜色
indicatorActiveColor 当前选中的指示点颜色
current 当前的滑块是第几个 用法 :current.sync='current',外部数据跟组件内部是同步的
vertical 滑动方向是否为纵向
@currentChange 轮播图改变时会触发 currentChange 事件,返回当前滑块为第几个
@moveTouchStart 滑动开始触发的方法
@moveTouchEnd 滑动结束触发的方法
@slideToNumber(index,isAnimation) 调取这个方法可以直接跳转到某一个滑块 index为要跳转的第几个滑块, isAnimation为是否需要动画
javascript
<template>
<wbx-view class="" style="width: 100vw;height: 100vh;">
<wbx-view style="margin-top: 100px; margin-left: 30px;margin-bottom: 20px;">
<WBXswiper
:current.sync="current"
:vertical="true"
:indicatorDots="true"
ref="seiperDom"
:autoPlay="true"
indicatorActiveColor="#fff"
indicatorColor="#c0c0c0"
:originalData="items"
@moveTouchEnd="end"
@moveTouchStart="start"
@currentChange="gaibian"
style="width: 300px;height: 300px;border-radius: 20px;">
<template slot="swiperItem" slot-scope="scope">
<wbx-image :src="scope.item.src" mode="scaleToFill" style="width:300px; height: 300px;" />
</template>
</WBXswiper>
<wbx-view @click="add(99,true)" style="width: 30px;height:30px;background-color: red;">
<wbx-text style="color:#000">99</wbx-text>
</wbx-view>
<wbx-view @click="add(1,true)" style="width: 70px;height:30px;background-color:rebeccapurple;">
<wbx-text style="color:#000">1有效果</wbx-text>
</wbx-view>
<wbx-view @click="add(4,false)" style="width: 70px;height:30px;background-color: gold;">
<wbx-text style="color:#000">4没效果</wbx-text>
</wbx-view>
<wbx-text style="width: 100px;height: 50px;color: red;border: 1px solid #000;">
总数:{{items.length}}
</wbx-text>
</wbx-view>
</wbx-view>
</template>
<script>
/**
* @type WBXAppOption
*/
import WBXswiper from "../../commpents/WBXswiper/index.vue";
const pageOptions = {
data() {
return {
items: [
{
src: 'res/001.jpg',
txt:222222
},{
src: 'res/1.jpg',
txt:222222
},
{
src: 'res/2.jpg',
txt:333333
},
{
src: 'res/login.png',
txt:4444
},
{
src: 'res/5.jpg',
txt:333333
},
{
src: 'res/6.jpg',
txt:333333
},{
src: 'res/7.jpg',
txt:333333
},{
src: 'res/8.jpg',
txt:333333
},
{
src: 'res/100.jpg',
txt:333333
},
],
current:3,
}
},
computed:{
},
methods: {
gaibian(e){
console.log(e,"传出来的值")
},
add(index,isAnimation){
this.$refs.seiperDom.slideToNumber(index,isAnimation)
},
start(){
console.log('开始了')
},
end(){
console.log('结束了')
}
},
components: {
WBXswiper,
},
wbox: {
onLoad() { },
onShow() {
// 页面显示/切入前台时触发
},
onHide() {
// 页面隐藏时触发
},
onUnload() {
// 页面退出时触发
},
},
mounted() { },
};
export default pageOptions;
</script>
<style></style>
这里是组件内部,
javascript
<template>
<wbx-view
ref="objStyle"
:style="wrapperStyle"
>
<wbx-view
@touchstart~stop="onTouchStart"
@touchmove~stop="onTouchMove"
@touchend~stop="onTouchEnd"
class="carousel-wrapper"
:style="carouselStyle"
@transitionend~stop="onTransitionEnd"
ref="carouselWrapper"
>
<wbx-view :style="itemStyle">
<slot name="swiperItem" :item="originalData[originalData.length - 1]"></slot>
</wbx-view>
<wbx-view v-for="(item, index) in originalData" :key="index" :style="itemStyle">
<slot name="swiperItem" :item="item"></slot>
</wbx-view>
<wbx-view :style="itemStyle">
<slot name="swiperItem" :item="originalData[0]"></slot>
</wbx-view>
</wbx-view>
<wbx-view v-if="indicatorDots" :style="{ width: containerWidth + 'px' }" style="position: absolute; bottom: 10px; display: flex; flex-direction: row; justify-content: center;">
<wbx-view
v-for="(item, index) in originalData"
:key="index"
:style="{ backgroundColor: index == realIndex ? indicatorActiveColor : indicatorColor }"
style="width: 20px; height: 20px; margin: 0 5px; cursor: pointer; border-radius: 10px;"
@click~stop="setCurrentIndex(index+1)"
></wbx-view>
</wbx-view>
</wbx-view>
</template>
<script>
/*
originalData 数据
autoPlay 是否自动播放
interval 自动播放间隔时间
indicatorDots 是否显示指示点
indicatorColor 指示点颜色
indicatorActiveColor 当前选中的指示点颜色
current 当前的滑块是第几个 用法 :current.sync='current',外部数据跟组件内部是同步的
vertical 滑动方向是否为纵向
@currentChange 轮播图改变时会触发 currentChange 事件,返回当前滑块为第几个
@moveTouchStart 滑动开始触发的方法
@moveTouchEnd 滑动结束触发的方法
@slideToNumber(index,isAnimation) 调取这个方法可以直接跳转到某一个滑块 index为要跳转的第几个滑块, isAnimation为是否需要动画
*/
export default {
props: {
originalData: {
type: Array,
required: true
},
autoPlay: {
type: Boolean,
default: false
},
interval: {
type: Number,
default: 3000
},
indicatorDots: {
type: Boolean,
default: false
},
indicatorColor: {
type: String,
default: '#c0c0c0'
},
indicatorActiveColor: {
type: String,
default: '#fff'
},
current: {
type: String,
default: ''
},
vertical: {
type: Boolean,
default: false
},
modelValue: {
type: Number,
required: true,
},
},
data() {
return {
currentIndex: 1,
startIndex:'',
timer: null,
startX: 0,
startY: 0,
offset: 0,
isTransitioning: false,
containerWidth: 0,
containerHeight: 0,
userCurrent:false,
userCurrentStare:false,
};
},
watch: {
current: {
handler(newVal) {
this.userCurrent=true
this.setCurrentIndexDom(newVal);
},
immediate: true
},
},
computed: {
wrapperStyle() {
return {
position: "relative",
width: `${this.wrapperWidth}px`,
height: `${this.wrapperHeight}px`,
};
},
carouselStyle() {
const baseTranslateValue = -this.currentIndex * (this.vertical ? this.containerHeight : this.containerWidth);
const translateValue = baseTranslateValue + this.offset;
return {
display: 'flex',
flexDirection: this.vertical ? 'column' : 'row',
transform: this.vertical ? `translateY(${translateValue}px)` : `translateX(${translateValue}px)`,
transition: this.isTransitioning ? 'transform 0.3s ease-out' : 'none',
width: !this.vertical ? `${this.wrapperWidth}px` : `${this.containerWidth}px`,
height: this.vertical ? `${this.wrapperHeight}px` : `${this.containerWidth}px`
};
},
wrapperWidth() {
return this.containerWidth * (this.originalData.length + 2);
},
wrapperHeight() {
return this.containerHeight * (this.originalData.length + 2);
},
itemStyle() {
return {
width: !this.vertical ? `${this.containerWidth}px` : `${this.containerWidth}px`,
height: this.vertical ? `${this.containerHeight}px` : `${this.containerWidth}px`,
flexShrink: 0
};
},
realIndex() {
return (this.currentIndex - 1 + this.originalData.length) % this.originalData.length;
}
},
mounted() {
this.updateDimensions();
this.$nextTick(() => {
if (this.autoPlay) {
this.startAutoPlay();
}
});
},
beforeDestroy() {
this.stopAutoPlay();
},
methods: {
updateDimensions() {
if (this.$refs.objStyle) {
const objStyle = this.$refs.objStyle.styleObject
this.containerWidth = parseFloat(objStyle.width);
this.containerHeight = parseFloat(objStyle.height);
}
},
startAutoPlay() {
this.timer = setInterval(() => {
this.next();
}, this.interval);
},
stopAutoPlay() {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
},
next() {
this.offset = 0;
this.isTransitioning = true;
this.currentIndex=this.currentIndex + 1;
this.changeNumFn()
},
prev() {
this.offset = 0;
this.isTransitioning = true;
this.currentIndex=this.currentIndex-1;
this.changeNumFn()
},
changeNumFn(){
let num =''
if(this.currentIndex>this.originalData.length){
num=1
}else if(this.currentIndex<1){
num=this.originalData.length
}else{
num=this.currentIndex
}
this.$emit('update:current',num)
this.$emit('currentChange', { current: num });
},
slideToNumber(index,isAnimation){
if(index>0 && index<this.originalData.length){
this.startIndex=index
}else{
return
}
this.stopAutoPlay();
this.isTransitioning = isAnimation;
this.currentIndex = index;
this.changeNumFn()
if (this.autoPlay) {
this.startAutoPlay();
}
},
setCurrentIndexDom(index){
if(index==1||index==this.originalData.length||this.startIndex==index){
return
}
if(this.current!==''){
if(this.userCurrentStare==false){
this.isTransitioning=false
this.userCurrentStare=true
}else{
this.isTransitioning=true
}
}else{
if(index==''){
this.isTransitioning = false;
}else{
this.isTransitioning = true;
}
}
this.currentIndex = index==''?1:index;
},
setCurrentIndex(index) {
this.stopAutoPlay();
this.currentIndex = index==''?1:index;
if (this.autoPlay) {
this.startAutoPlay();
}
this.changeNumFn()
},
onTouchStart(e) {
this.startX = e.touches[0].clientX;
this.startY = e.touches[0].clientY;
this.offset = 0;
this.stopAutoPlay();
this.$emit('moveTouchStart',)
},
onTouchMove(e) {
const moveX = e.touches[0].clientX;
const moveY = e.touches[0].clientY;
if(this.vertical){
if(moveY - this.startY>=this.containerHeight){
this.offset=this.containerHeight
}else if(moveY - this.startY<= -this.containerHeight){
this.offset=-this.containerHeight
}else{
this.offset= moveY - this.startY;
}
}else{
if(moveX - this.startX>=this.containerWidth){
this.offset=this.containerWidth
}else if(moveX - this.startX<= -this.containerWidth){
this.offset=-this.containerWidth
}else{
this.offset= moveX - this.startX;
}
}
},
onTouchEnd() {
this.isTransitioning = true;
this.$emit('moveTouchEnd')
if (Math.abs(this.offset) > (this.vertical ? this.containerHeight : this.containerWidth) /6) {
if (this.offset > 0) {
this.prev();
} else {
this.next(111);
}
} else {
this.offset = 0;
}
if (this.autoPlay) {
this.startAutoPlay();
}
},
onTransitionEnd() {
this.isTransitioning = false;
this.offset = 0;
if (this.currentIndex === this.originalData.length + 1) {
this.currentIndex = 1;
}
if (this.currentIndex === 0) {
this.currentIndex = this.originalData.length;
}
}
}
};
</script>
<style>
</style>