优化阅读页面
This commit is contained in:
parent
2c18c9ec0d
commit
184e85da84
@ -12,33 +12,29 @@
|
||||
:line-height="defaultCharactersLineHeight" :color="novelContentColor" :bg-color="bodyReadingBg"
|
||||
:slide="20" :enablePreload="false" @loadmore="loadmoreContent" @preload="preloadContent"
|
||||
@change="currentChange" @setCatalog="setCatalog" @clickme="clickme" @clickher="clickher"
|
||||
@clickTo="handelShowStepUp" :clickOption="{width:200,height: 400,left:'auto',top:'auto'}">
|
||||
@clickTo="handelShowStepUp" :clickOption="{width:200,height: 400,left:'auto',top:'auto'}"
|
||||
@handelPurchaseFull="handelPurchaseFull">
|
||||
<template #test>
|
||||
<view class="balance_con">
|
||||
<rich-text class="balance_con_rich_text"
|
||||
:style="`color:${novelContentColor};font-size:${newCharactersSize}px;`"
|
||||
:nodes="readChapterInfoObj.content"></rich-text>
|
||||
<view class="balance_recharge_option"></view>
|
||||
<view class="balance_recharge" :style="`background:${bodyReadingBg}`">
|
||||
<view class="balance_tips" :style="`color:${novelContentColor}`">
|
||||
付费章节,需要购买。{{readChapterInfoObj.price}}书币</view>
|
||||
<view class="balance_btn_all">
|
||||
<view v-if="!token" class="purchaseFull_popup_btn" @click="toPathLogin">新用户登录</view>
|
||||
<view v-else class="purchaseFull_popup_btn" @click="handelPurchaseFull">需要全本购买
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</yingbing-ReadPage>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u_popup_all">
|
||||
<u-popup :show="tabBarPopupShow" mode="bottom" :overlay="false" zIndex="6" :bgColor="bodyReadingBg">
|
||||
<view class="my_tabBar_Reading" :style="`background:${bodyReadingBg}`">
|
||||
<view class="tabBar_Reading_item">
|
||||
<view class="reading_item_icon" @tap="handelDirectoryPopup">
|
||||
<image class="is_images" :src="barPopupIcon[novelMainTypeColor].directory_icon"></image>
|
||||
</view>
|
||||
<view class="reading_item_name" :style="`color:${tabBarTextColor}`">目录</view>
|
||||
</view>
|
||||
<view class="tabBar_Reading_item">
|
||||
<view class="reading_item_icon" @tap="toBookshelf">
|
||||
<image class="is_images" :src="barPopupIcon[novelMainTypeColor].bookshelf_icon"></image>
|
||||
</view>
|
||||
<view class="reading_item_name" :style="`color:${tabBarTextColor}`">书城</view>
|
||||
</view>
|
||||
<view class="tabBar_Reading_item" @tap="handelSteUpPopup">
|
||||
<view class="reading_item_icon">
|
||||
<image class="is_images" :src="barPopupIcon[novelMainTypeColor].step_up_icon"></image>
|
||||
</view>
|
||||
<view class="reading_item_name" :style="`color:${tabBarTextColor}`">设置</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
<u-popup :show="readingPopupshow" mode="bottom" :overlay="false" zIndex="4" bgColor="transparent">
|
||||
<view class="reading_schedule_box" :style="`background:${bodyReadingBg}`">
|
||||
<view class="reading_schedule_body">
|
||||
@ -52,7 +48,26 @@
|
||||
@tap="nextChapter">下一章
|
||||
</view>
|
||||
</view>
|
||||
<view style="height: 140rpx" />
|
||||
<view class="my_tabBar_Reading" :style="`background:${bodyReadingBg}`">
|
||||
<view class="tabBar_Reading_item">
|
||||
<view class="reading_item_icon" @tap="handelDirectoryPopup">
|
||||
<image class="is_images" :src="barPopupIcon[novelMainTypeColor].directory_icon"></image>
|
||||
</view>
|
||||
<view class="reading_item_name" :style="`color:${tabBarTextColor}`">目录</view>
|
||||
</view>
|
||||
<view class="tabBar_Reading_item">
|
||||
<view class="reading_item_icon" @tap="toBookshelf">
|
||||
<image class="is_images" :src="barPopupIcon[novelMainTypeColor].bookshelf_icon"></image>
|
||||
</view>
|
||||
<view class="reading_item_name" :style="`color:${tabBarTextColor}`">书城</view>
|
||||
</view>
|
||||
<view class="tabBar_Reading_item" @tap="handelSteUpPopup">
|
||||
<view class="reading_item_icon">
|
||||
<image class="is_images" :src="barPopupIcon[novelMainTypeColor].step_up_icon"></image>
|
||||
</view>
|
||||
<view class="reading_item_name" :style="`color:${tabBarTextColor}`">设置</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
<u-popup :show="stepUpPopupShow" mode="bottom" :overlay="false" bgColor="transparent" zIndex="5">
|
||||
@ -103,7 +118,7 @@
|
||||
</scroll-view>
|
||||
</view>
|
||||
</u-popup>
|
||||
<u-popup :show="purchaseFullShow" @close="purchaseFullClose" mode="bottom" overlayStyle="top:44px">
|
||||
<!-- <u-popup :show="purchaseFullShow" @close="purchaseFullClose" mode="bottom" overlayStyle="top:44px">
|
||||
<view class="purchaseFull_popup_box" :style="`background:${bodyReadingBg}`">
|
||||
<view>
|
||||
<CommBookLeftRigth :bookTips="bookInfo.category_name" :bookName="bookInfo.title"
|
||||
@ -113,9 +128,9 @@
|
||||
<view class="purchaseFull_popup_btn" @tap="handelPurchaseFull">需要全本购买</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
<u-modal :show="balanceShow" :title="balanceTitle" content='余额不足,请充值...'
|
||||
:showCancelButton="!readChapterFlag" @confirm="balanceConfirm" @cancel="balanceCancel" />
|
||||
</u-popup> -->
|
||||
<!-- <u-modal :show="balanceShow" :title="balanceTitle" content='余额不足,请充值...'
|
||||
:showCancelButton="!readChapterFlag" @confirm="balanceConfirm" @cancel="balanceCancel" /> -->
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@ -149,6 +164,7 @@
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
token: '',
|
||||
navbarTitle: '小说阅读页面',
|
||||
novelMainTypeColor: '',
|
||||
setUpColorAll: {},
|
||||
@ -165,7 +181,6 @@
|
||||
bodyReadingBg: '',
|
||||
// 底部安全区
|
||||
// bottomSecureHeight: 0,
|
||||
tabBarPopupShow: false,
|
||||
readingPopupshow: false,
|
||||
stepUpPopupShow: false,
|
||||
purchaseFullShow: false,
|
||||
@ -189,7 +204,7 @@
|
||||
directoryPopupShow: false,
|
||||
// 小说信息
|
||||
novelReadingContentText: [],
|
||||
charactersPageType: 'real',
|
||||
charactersPageType: 'reals',
|
||||
defaultCharactersSize: 28,
|
||||
newCharactersSize: 28,
|
||||
defaultCharactersLineHeight: 20,
|
||||
@ -211,23 +226,25 @@
|
||||
this.readChapterid = options.id;
|
||||
},
|
||||
onShow() {
|
||||
const token = myGetStorage('token');
|
||||
this.token = token;
|
||||
const bookSid = this.booksDirectorySid;
|
||||
const data = {
|
||||
sid: bookSid,
|
||||
}
|
||||
uni.$u.http.post('/bookdetails', data).then((res) => {
|
||||
uni.hideLoading();
|
||||
if (res.status == 1) {
|
||||
const info = res.data.info;
|
||||
const cover = info.cover.includes('http') ? info.cover : `${config.baseUrl}${info.cover}`;
|
||||
this.bookInfo = {
|
||||
...info,
|
||||
cover
|
||||
};
|
||||
}
|
||||
}).catch((err) => {
|
||||
uni.hideLoading();
|
||||
})
|
||||
// const data = {
|
||||
// sid: bookSid,
|
||||
// }
|
||||
// uni.$u.http.post('/bookdetails', data).then((res) => {
|
||||
// uni.hideLoading();
|
||||
// if (res.status == 1) {
|
||||
// const info = res.data.info;
|
||||
// const cover = info.cover.includes('http') ? info.cover : `${config.baseUrl}${info.cover}`;
|
||||
// this.bookInfo = {
|
||||
// ...info,
|
||||
// cover
|
||||
// };
|
||||
// }
|
||||
// }).catch((err) => {
|
||||
// uni.hideLoading();
|
||||
// })
|
||||
this.isGetUserRead();
|
||||
},
|
||||
methods: {
|
||||
@ -277,23 +294,23 @@
|
||||
title: resData.chaptername,
|
||||
isTtitle: resData.title
|
||||
// richTextNodes: `<h3>${res.data.chaptername}</h3></br>${res.data.novel_content}`
|
||||
// richTextNodes: `<h3>${res.data.chaptername}</h3></br>${res.data.novel_content}`
|
||||
};
|
||||
this.readChapterInfoObj = readChapterInfoObj;
|
||||
if (readChapterInfoObj.chackpay == 1) {
|
||||
resolve(readChapterInfoObj);
|
||||
} else if (readChapterInfoObj.chackpay == 2) {
|
||||
this.balanceShow = true;
|
||||
this.balanceTitle = '下一章,付费章节';
|
||||
if (isShowLoading) {
|
||||
this.readChapterFlag = true;
|
||||
}
|
||||
} else if (readChapterInfoObj.chackpay == 3) {
|
||||
this.purchaseFullShow = true;
|
||||
if (isShowLoading) {
|
||||
this.readChapterFlag = true;
|
||||
}
|
||||
}
|
||||
resolve(readChapterInfoObj);
|
||||
// if (readChapterInfoObj.chackpay == 1) {
|
||||
|
||||
// } else if (readChapterInfoObj.chackpay == 2) {
|
||||
// this.balanceShow = true;
|
||||
// this.balanceTitle = '下一章,付费章节';
|
||||
// if (isShowLoading) {
|
||||
// this.readChapterFlag = true;
|
||||
// }
|
||||
// } else if (readChapterInfoObj.chackpay == 3) {
|
||||
// this.purchaseFullShow = true;
|
||||
// if (isShowLoading) {
|
||||
// this.readChapterFlag = true;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}).catch((err) => {
|
||||
uni.hideLoading();
|
||||
@ -303,34 +320,64 @@
|
||||
|
||||
},
|
||||
async loadmoreContent(chapter, callback) {
|
||||
console.log(chapter, "*****************")
|
||||
const newReadDirectoryActive = this.readDirectoryActive;
|
||||
const newReadChapterLastid = this.readChapterLastid;
|
||||
const newNovelReadingContentText = this.novelReadingContentText;
|
||||
const newReadChapterNextid = this.readChapterNextid;
|
||||
console.log(newNovelReadingContentText,"newNovelReadingContentText")
|
||||
// const itemTemp = newNovelReadingContentText.filter((m) => m.chapter == parseInt(chapter + 1));
|
||||
// console.log(itemTemp,itemTemp[0].lastid, "itemTempitemTempitemTemp")
|
||||
if (newReadDirectoryActive != 1) {
|
||||
console.log(chapter, newReadDirectoryActive, "loadmoreContent")
|
||||
if (chapter != 1) {
|
||||
if (chapter < newReadDirectoryActive) {
|
||||
// const readChapterInfoObj = await this.isGetBookInfo(itemTemp[0].lastid);
|
||||
const readChapterInfoObj = await this.isGetBookInfo(newReadChapterLastid);
|
||||
console.log(readChapterInfoObj, "上一章")
|
||||
this.novelReadingContentText = [...newNovelReadingContentText, readChapterInfoObj];
|
||||
this.readDirectoryActive = chapter;
|
||||
// this.readChapterLastid = readChapterInfoObj.lastid;
|
||||
// this.readChapterNextid = readChapterInfoObj.nextid;
|
||||
callback('success', readChapterInfoObj)
|
||||
if (readChapterInfoObj.chackpay == 1) {
|
||||
callback('success', readChapterInfoObj)
|
||||
}
|
||||
const obj = {
|
||||
...readChapterInfoObj,
|
||||
custom,
|
||||
content: ''
|
||||
}
|
||||
console.log(obj, "objobj")
|
||||
callback('success', obj)
|
||||
}
|
||||
if (chapter > newReadDirectoryActive) {
|
||||
// const readChapterInfoObj = await this.isGetBookInfo(itemTemp[0].nextid);
|
||||
const readChapterInfoObj = await this.isGetBookInfo(newReadChapterNextid);
|
||||
console.log(readChapterInfoObj, "下一章")
|
||||
this.novelReadingContentText = [readChapterInfoObj, ...newNovelReadingContentText];
|
||||
this.readDirectoryActive = chapter;
|
||||
// this.readChapterLastid = readChapterInfoObj.lastid;
|
||||
// this.readChapterNextid = readChapterInfoObj.nextid;
|
||||
callback('success', readChapterInfoObj)
|
||||
if (readChapterInfoObj.chackpay == 1) {
|
||||
callback('success', readChapterInfoObj)
|
||||
}
|
||||
if (readChapterInfoObj.chackpay == 2) {
|
||||
const novelContentColor = this.novelContentColor;
|
||||
const newCharactersSize = this.newCharactersSize;
|
||||
const bodyReadingBg = this.bodyReadingBg;
|
||||
//
|
||||
const custom = [`slot:test`]
|
||||
// const custom = [
|
||||
// `<div class="balance_con">
|
||||
// <div class="balance_con_rich_text"
|
||||
// style="color:${novelContentColor};font-size:${newCharactersSize}px;"
|
||||
// >${readChapterInfoObj.content}</div>
|
||||
// <div class="balance_recharge_option"></div>
|
||||
// <div class="balance_recharge" style="background:${bodyReadingBg}">
|
||||
// <div class="balance_tips" style="color:${novelContentColor}">
|
||||
// 付费章节,需要购买。${readChapterInfoObj.price}书币</div>
|
||||
// <div class="balance_btn_all">
|
||||
// <div class="purchaseFull_popup_btn" onclick="handelPurchaseFull">需要全本购买</div>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>`
|
||||
// ]
|
||||
const obj = {
|
||||
...readChapterInfoObj,
|
||||
custom,
|
||||
content: ''
|
||||
}
|
||||
console.log(obj, "objobj")
|
||||
callback('success', obj)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -341,19 +388,30 @@
|
||||
this.readChapterLastid = itemTemp[0].lastid;
|
||||
this.readChapterNextid = itemTemp[0].nextid;
|
||||
},
|
||||
previousChapter() {
|
||||
const readChapterLastid = this.readChapterLastid
|
||||
if (!readChapterLastid) {
|
||||
async previousChapter() {
|
||||
const newReadDirectoryActive = this.readDirectoryActive;
|
||||
const newReadChapterLastid = this.readChapterLastid;
|
||||
const newNovelReadingContentText = this.novelReadingContentText;
|
||||
if (!newReadChapterLastid) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
title: "已经是第一章了"
|
||||
})
|
||||
return
|
||||
}
|
||||
this.isGetBookInfo(readChapterLastid, 'previousChapter');
|
||||
const readChapterInfoObj = await this.isGetBookInfo(newReadChapterLastid);
|
||||
this.novelReadingContentText = [readChapterInfoObj];
|
||||
this.$refs.yingbingReadPage.init({
|
||||
contents: [readChapterInfoObj],
|
||||
start: 0,
|
||||
currentChapter: newReadDirectoryActive - 1
|
||||
})
|
||||
this.readDirectoryActive = newReadDirectoryActive - 1;
|
||||
},
|
||||
nextChapter() {
|
||||
async nextChapter() {
|
||||
const newReadDirectoryActive = this.readDirectoryActive;
|
||||
const readChapterNextid = this.readChapterNextid;
|
||||
const newNovelReadingContentText = this.novelReadingContentText;
|
||||
if (!readChapterNextid) {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
@ -361,11 +419,17 @@
|
||||
})
|
||||
return
|
||||
}
|
||||
this.isGetBookInfo(readChapterNextid, 'nextChapter');
|
||||
const readChapterInfoObj = await this.isGetBookInfo(readChapterNextid);
|
||||
this.novelReadingContentText = [readChapterInfoObj];
|
||||
this.$refs.yingbingReadPage.init({
|
||||
contents: [readChapterInfoObj],
|
||||
start: 0,
|
||||
currentChapter: newReadDirectoryActive + 1
|
||||
})
|
||||
this.readDirectoryActive = newReadDirectoryActive + 1;
|
||||
},
|
||||
handelDirectoryItem(row) {},
|
||||
handelShowStepUp() {
|
||||
this.tabBarPopupShow = !this.tabBarPopupShow;
|
||||
this.readingPopupshow = !this.readingPopupshow;
|
||||
this.stepUpPopupShow = false;
|
||||
},
|
||||
@ -377,6 +441,13 @@
|
||||
url: `/pages/bookRecommendList/bookRecommendList?sid=${readChapterInfoObj.sid}&t=${readChapterInfoObj.title}&c=${readDirectoryActive}`
|
||||
})
|
||||
},
|
||||
toPathLogin() {
|
||||
const readChapterInfoObj = this.readChapterInfoObj;
|
||||
const readDirectoryActive = this.readDirectoryActive;
|
||||
uni.navigateTo({
|
||||
url: `/pages/login/login?sid=${readChapterInfoObj.sid}&t=${readChapterInfoObj.title}&c=${readDirectoryActive}`
|
||||
})
|
||||
},
|
||||
directoryPopupClose() {
|
||||
// this.directoryPopupShow = false;
|
||||
// const readChapterInfoObj = this.readChapterInfoObj;
|
||||
@ -545,30 +616,6 @@
|
||||
})
|
||||
}
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
// const isReadDirectoryActive = this.readDirectoryActive;
|
||||
// if(isReadDirectoryActive == 0) {
|
||||
// uni.showToast({
|
||||
// icon:'none',
|
||||
// title:"已经是第一章了"
|
||||
// })
|
||||
// uni.stopPullDownRefresh()
|
||||
// return
|
||||
// }
|
||||
// const readDirectoryActive = isReadDirectoryActive- 1;
|
||||
// const novelReadingContentText = this.myData[readDirectoryActive];
|
||||
// this.novelReadingContentText = [novelReadingContentText, ...this.novelReadingContentText];
|
||||
// // setTimeout(() => {
|
||||
// this.computeRichText = this.myData[readDirectoryActive].content;
|
||||
// // this.readDirectoryActive = readDirectoryActive;
|
||||
// const query = uni.createSelectorQuery().in(this);
|
||||
// this.$nextTick(() => {
|
||||
// query.select(`#compute_rich_text`).boundingClientRect((data) => {
|
||||
// this.isScrollTop = parseInt(data.height) - 30;
|
||||
// }).exec();
|
||||
// });
|
||||
// uni.stopPullDownRefresh()
|
||||
},
|
||||
created() {
|
||||
const novelMainObj = myGetStorage('novelMainObj') || '{}';
|
||||
const novelMainTypeColor = JSON.parse(novelMainObj).novelMainTypeColor || 'F3EFE9';
|
||||
@ -581,17 +628,6 @@
|
||||
this.novelMainTypeColor = novelMainTypeColor;
|
||||
this.newCharactersSize = JSON.parse(novelMainObj).charactersSize || 28;
|
||||
this.bodyReadingHeight = screenHeight - statusBarHeight - devicePixelRatio * 22;
|
||||
// 不需要
|
||||
// this.scrollReadingHeight = screenHeight - statusBarHeight - devicePixelRatio * 38;
|
||||
// this.scrollReadingHeight = windowHeight - (screenWidth / 375) * 54;
|
||||
// // #ifdef APP-PLUS
|
||||
// this.directoryPopupHeight = screenHeight - statusBarHeight;
|
||||
// // #endif
|
||||
// // #ifdef H5 || MP-WEIXIN
|
||||
// this.directoryPopupHeight = screenHeight - statusBarHeight - devicePixelRatio * 22;
|
||||
// // #endif
|
||||
|
||||
// this.bottomSecureHeight = screenHeight - windowHeight;
|
||||
this.setUpColorAll = setUpReadingColorAll;
|
||||
this.barPopupIcon = {
|
||||
'F3EFE9': {
|
||||
@ -631,6 +667,96 @@
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
|
||||
|
||||
/deep/.balance_con {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
|
||||
.balance_con_rich_text {
|
||||
width: 100%;
|
||||
height: 80%;
|
||||
line-height: 2;
|
||||
overflow: hidden;
|
||||
// text-overflow: ellipsis;
|
||||
// display: -webkit-box;
|
||||
// -webkit-line-clamp: 10;
|
||||
// -webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.balance_recharge_option {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 414px;
|
||||
height: 560rpx;
|
||||
// box-shadow: 0 0 8rpx rgba(0, 0, 0, 0.2);
|
||||
background: rgba(243, 239, 233, 0.7);
|
||||
filter: blur(10px);
|
||||
// user-select: none;
|
||||
// opacity: 0.6;
|
||||
// background: #fff;
|
||||
// background-image: linear-gradient(-180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.6) 80%);
|
||||
}
|
||||
|
||||
// .balance_recharge_option::after {
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
// content: '';
|
||||
// display: block;
|
||||
|
||||
// }
|
||||
|
||||
.balance_recharge {
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
position: fixed;
|
||||
bottom: 0rpx;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
box-shadow: 0 0 8rpx rgba(0, 0, 0, 0.2);
|
||||
height: 360rpx;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
padding: 32rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
// background-image: linear-gradient(-180deg, rgba(255, 255, 255, 0) 0%, rgb(255, 255, 255) 80%);
|
||||
// background: rgba(255, 255, 255, 0.2);
|
||||
// filter: blur(5px);
|
||||
// user-select: none;
|
||||
// box-shadow: 0 -20rpx 20rpx rgba(0, 0, 0, 0.2);
|
||||
.balance_tips {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.balance_btn_all {
|
||||
// display: flex;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
margin-top: 32rpx;
|
||||
|
||||
.purchaseFull_popup_btn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 84rpx;
|
||||
font-size: 30rpx;
|
||||
color: #fff;
|
||||
background: linear-gradient(to top, #FBA676, #E95E32);
|
||||
border-radius: 24rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.novelReading_content::v-deep.u-navbar__content__title {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
@ -1,3 +1,43 @@
|
||||
## 1.5.9(2023-09-01)
|
||||
* 修复滚动模式下计算滚动位置异常的问题
|
||||
## 1.5.8(2023-08-23)
|
||||
* 修复APP-VUE翻页翻往下一章时可能会出现的undefined
|
||||
## 1.5.7(2023-08-21)
|
||||
* 增加split属性,用于分隔字符串排版,适用于英文小说
|
||||
* measureSize属性中将英文字母大小拆分成小写英文字母和大写英文字母大小
|
||||
## 1.5.6(2023-07-24)
|
||||
* 解决bgColor属性无效的问题
|
||||
## 1.5.5(2023-07-22)
|
||||
* 请注意此次更新将翻页功能抽出来,插件本身只有滚动阅读功能,如果需要翻页功能请下载新插件好用翻页组件配合使用,下载地址看使用介绍
|
||||
* 此次更新未更新新功能,不想多下载插件的朋友可以不更新
|
||||
## 1.5.4(2023-07-10)
|
||||
* 增加firstTipUnable、lastTipUnable属性控制第一页提示页和最后一页提示页的显示
|
||||
## 1.5.3(2023-07-08)
|
||||
* 自定义插槽添加作用域插槽,可以获取当前页信息,用于动态绑定内容(不支持微信小程序)
|
||||
## 1.5.2(2023-07-07)
|
||||
* 增加firstTip,lastTip属性自定义第一页和最后一页提示文字
|
||||
* 增加top、bottom插槽,自定义第一页和最后一页的页面
|
||||
## 1.5.1(2023-07-07)
|
||||
* 新增unableClickPage属性控制点击左右2侧翻页
|
||||
## 1.5.0(2023-06-20)
|
||||
* 修复微信小程序报错的问题
|
||||
## 1.4.9(2023-06-14)
|
||||
* 修复向前翻页页面抖动的问题
|
||||
* 优化loadmore事件返回回调为fail或者timeout时的显示
|
||||
* 优化change事件,不再强制传contents
|
||||
## 1.4.8(2023-06-12)
|
||||
* 修复h5,APP-VUE自定义页面添加点击事件无法点击的问题
|
||||
## 1.4.7(2023-06-07)
|
||||
* 优化h5电量显示,避免报错
|
||||
## 1.4.6(2023-06-07)
|
||||
* 新增自动翻页功能
|
||||
* 优化页面刷新逻辑,减少报错
|
||||
## 1.4.5(2023-05-27)
|
||||
* 添加字符宽度自动测量功能,减少排版错误
|
||||
* 新增measureSize属性,用于自定义字符宽度
|
||||
## 1.4.4(2023-05-26)
|
||||
* 翻页模式添加touchcancel事件
|
||||
* 为兼容IOS空格计算宽度增加1px
|
||||
## 1.4.3(2023-05-25)
|
||||
* 新增fontFamily属性设置字体名称
|
||||
* 新增fontFace属性添加自定义字体
|
||||
|
@ -34,13 +34,14 @@
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
mounted () {
|
||||
created () {
|
||||
this.getBattery()
|
||||
},
|
||||
methods: {
|
||||
getBattery () {
|
||||
// #ifdef H5
|
||||
window.navigator.getBattery().then((res) => {
|
||||
//window.navigator.getBattery只能在安全环境下(比如:https file:///url)使用,判断一下避免报错
|
||||
window.navigator.getBattery && window.navigator.getBattery().then((res) => {
|
||||
// 电池电量在0到1之间,因此我们将其乘以100得出百分比
|
||||
this.value = res.level * 54
|
||||
});
|
||||
|
@ -0,0 +1,14 @@
|
||||
.computed {
|
||||
position: fixed;
|
||||
top: -1000rpx;
|
||||
left: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.computed-text {
|
||||
font-size: 20px;
|
||||
flex-shrink: 0;
|
||||
}
|
@ -1,8 +1,22 @@
|
||||
import Util from '../../../js_sdk/util.js'
|
||||
export default {
|
||||
props: {
|
||||
measureSize: {
|
||||
type: Object,
|
||||
default () {
|
||||
return new Object
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
computedResolve: null
|
||||
computedResolve: null,
|
||||
chineseSize: 0,
|
||||
spaceSize: 0,
|
||||
lowerSize: 0,
|
||||
upperSize: 0,
|
||||
numberSize: 0,
|
||||
specialSize: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -49,29 +63,62 @@ export default {
|
||||
text = new String(text);
|
||||
text = text.split('');
|
||||
let width = 0;
|
||||
text.forEach(function(item) {
|
||||
if (/[a-zA-Z]/.test(item)) {
|
||||
width += 7;
|
||||
} else if (/[0-9]/.test(item)) {
|
||||
width += 5.5;
|
||||
} else if (/\./.test(item)) {
|
||||
width += 2.7;
|
||||
} else if (/-/.test(item)) {
|
||||
width += 3.25;
|
||||
text.forEach((item) => {
|
||||
if (/[a-z]/.test(item)) {
|
||||
width += this.measureSize.lower || this.lowerSize || 7
|
||||
} else if ( /[A-Z]/.test(item) ) {
|
||||
width += this.measureSize.upper || this.upperSize || 7
|
||||
} else if (/[0-9]/.test(item)) {
|
||||
width += this.measureSize.number || this.numberSize || 5.5
|
||||
} else if (/[\u4e00-\u9fa5]/.test(item)) { //中文匹配
|
||||
width += 10;
|
||||
} else if (/\(|\)/.test(item)) {
|
||||
width += 3.73;
|
||||
width += this.measureSize.chinese || this.chineseSize || 10
|
||||
} else if (/\s/.test(item)) {
|
||||
width += 2.5;
|
||||
width += this.measureSize.space || this.spaceSize || 3.5
|
||||
} else if (/[`!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?~]/.test(item)) {
|
||||
width += 8;
|
||||
width += this.measureSize.special || this.specialSize || 8
|
||||
} else {
|
||||
width += 10;
|
||||
width += this.measureSize.other || this.chineseSize || 10
|
||||
}
|
||||
});
|
||||
return width * fontSize / 10;
|
||||
},
|
||||
getComputedTextSize (selector, el) {
|
||||
let arr = []
|
||||
arr.push(Util.getRect('.computed-text-chinese', this.$refs.computedTextChinese, this))
|
||||
arr.push(Util.getRect('.computed-text-space', this.$refs.computedTextSpace, this))
|
||||
arr.push(Util.getRect('.computed-text-lower', this.$refs.computedTextLower, this))
|
||||
arr.push(Util.getRect('.computed-text-upper', this.$refs.computedTextUpper, this))
|
||||
arr.push(Util.getRect('.computed-text-number', this.$refs.computedTextNumber, this))
|
||||
arr.push(Util.getRect('.computed-text-special', this.$refs.computedTextSpecial, this))
|
||||
Promise.all(arr).then(ress => {
|
||||
ress.forEach((res, key) => {
|
||||
if ( key == 0 ) {
|
||||
this.chineseSize = res.width * (10 / 20)
|
||||
}
|
||||
if ( key == 1 ) {
|
||||
this.spaceSize = res.width * (10 / 20)
|
||||
}
|
||||
if ( key == 2 ) {
|
||||
this.lowerSize = res.width * (10 / 20)
|
||||
}
|
||||
if ( key == 3 ) {
|
||||
this.upperSize = res.width * (10 / 20)
|
||||
}
|
||||
if ( key == 4 ) {
|
||||
this.numberSize = res.width * (10 / 20)
|
||||
}
|
||||
if ( key == 5 ) {
|
||||
this.specialSize = res.width * (10 / 20)
|
||||
}
|
||||
// console.log('chineseSize', this.chineseSize);
|
||||
// console.log('spaceSize', this.spaceSize);
|
||||
// console.log('lowerSize', this.lowerSize);
|
||||
// console.log('upperSize', this.upperSize);
|
||||
// console.log('numberSize', this.numberSize);
|
||||
// console.log('specialSize', this.specialSize);
|
||||
})
|
||||
})
|
||||
},
|
||||
async computedText (data, start) {
|
||||
let rect = await this.getRect()
|
||||
let viewWidth = rect.width - (this.options.slide * 2)
|
||||
@ -91,32 +138,41 @@ export default {
|
||||
text: []
|
||||
}
|
||||
let length = 0;
|
||||
let contentSync = data.content.substr(start);
|
||||
let contentSync = data.content.substr(start).replace(/\t/g, ' ').replace(/ /g, ' ');
|
||||
let lastIndex = 0;
|
||||
while ( (pageHeight + this.options.fontSize + this.options.lineHeight) <= viewHeight ) {
|
||||
strs.push('');
|
||||
let lineWidth = 0;
|
||||
let charText = ''
|
||||
for ( let i = lastIndex; i < contentSync.length; i++ ) {
|
||||
if ( JSON.stringify(contentSync[i]) == JSON.stringify('\r') || JSON.stringify(contentSync[i]) == JSON.stringify('\n') ) {
|
||||
length += 1
|
||||
const char = contentSync.charAt(i)
|
||||
if ( JSON.stringify(char) == JSON.stringify('\r') || JSON.stringify(char) == JSON.stringify('\n') ) {
|
||||
lineWidth += this.measureText(charText, this.options.fontSize);
|
||||
if ( lineWidth >= viewWidth ) {
|
||||
lastIndex = i - charText.length+ 1;
|
||||
break;
|
||||
}
|
||||
strs[strs.length - 1] += charText
|
||||
length += charText.length + 1
|
||||
page.end = page.start + length;
|
||||
lastIndex = i + 1;
|
||||
break;
|
||||
}
|
||||
lineWidth += JSON.stringify(contentSync[i]) == JSON.stringify('\t') ? 0 : this.measureText(contentSync[i], this.options.fontSize);
|
||||
if ( lineWidth >= viewWidth ) {
|
||||
lastIndex = i;
|
||||
break;
|
||||
} else {
|
||||
if ( JSON.stringify(contentSync[i]) != JSON.stringify('\t') ) {
|
||||
strs[strs.length - 1] += contentSync[i].replace(' ', ' ')
|
||||
length += 1
|
||||
page.end = page.start + length
|
||||
charText += char
|
||||
if ( !this.split || char == this.split ) {
|
||||
lineWidth += this.measureText(charText, this.options.fontSize);
|
||||
if ( lineWidth >= viewWidth ) {
|
||||
lastIndex = i - charText.length+ 1;
|
||||
break;
|
||||
}
|
||||
strs[strs.length - 1] += charText
|
||||
length += charText.length
|
||||
page.end = page.start + length
|
||||
charText = ''
|
||||
}
|
||||
}
|
||||
pageHeight += this.options.fontSize + this.options.lineHeight;
|
||||
if ( page.end >= data.content.replace(/\t/g, '').length - 1 ) {
|
||||
if ( page.end >= data.content.length - 1 ) {
|
||||
page.isLastPage = true;
|
||||
break;
|
||||
}
|
||||
@ -188,22 +244,48 @@ export default {
|
||||
arr = arr.concat(pages)
|
||||
if (i == contents.length - 1) {
|
||||
if ( this.options.pageType != 'scroll' ) {
|
||||
arr.unshift({
|
||||
title: contents[0].title || '',
|
||||
chapter: contents[0].chapter,
|
||||
type: contents[0].isStart ? 'top' : 'prevLoading',
|
||||
dataId: arr[0].dataId - 1,
|
||||
start: 0,
|
||||
end: 0
|
||||
})
|
||||
arr.push({
|
||||
title: item.title || '',
|
||||
chapter: item.chapter,
|
||||
type: item.isEnd ? 'bottom' : 'nextLoading',
|
||||
dataId: arr[arr.length - 1].dataId + 1,
|
||||
start: 0,
|
||||
end: 0
|
||||
})
|
||||
if ( !this.firstTipUnable ) {
|
||||
arr.unshift({
|
||||
title: contents[0].title || '',
|
||||
chapter: contents[0].chapter,
|
||||
type: contents[0].isStart ? 'top' : 'loading',
|
||||
direction: 'prev',
|
||||
dataId: arr[0].dataId - 1,
|
||||
start: 0,
|
||||
end: 0
|
||||
})
|
||||
} else if ( !contents[0].isStart ) {
|
||||
arr.unshift({
|
||||
title: contents[0].title || '',
|
||||
chapter: contents[0].chapter,
|
||||
type: 'loading',
|
||||
direction: 'prev',
|
||||
dataId: arr[0].dataId - 1,
|
||||
start: 0,
|
||||
end: 0
|
||||
})
|
||||
}
|
||||
if ( !this.lastTipUnable ) {
|
||||
arr.push({
|
||||
title: item.title || '',
|
||||
chapter: item.chapter,
|
||||
type: item.isEnd ? 'bottom' : 'loading',
|
||||
direction: 'next',
|
||||
dataId: arr[arr.length - 1].dataId + 1,
|
||||
start: 0,
|
||||
end: 0
|
||||
})
|
||||
} else if ( !contents[0].isEnd ) {
|
||||
arr.push({
|
||||
title: item.title || '',
|
||||
chapter: item.chapter,
|
||||
type: 'loading',
|
||||
direction: 'next',
|
||||
dataId: arr[arr.length - 1].dataId + 1,
|
||||
start: 0,
|
||||
end: 0
|
||||
})
|
||||
}
|
||||
}
|
||||
this.pages = arr
|
||||
if ( this.options.pageType == 'scroll' ) {
|
||||
@ -211,7 +293,8 @@ export default {
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
if ( this.options.pageType != 'scroll' ) {
|
||||
this.onChange(this.currentDataId);
|
||||
this.$refs.flip.refresh()
|
||||
this.handleFlipChange(this.currentDataId);
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
Util.getRect('#scroll-item_' + this.currentDataId, Util.getRefs(this, 'scrollItem_' + this.currentDataId, 0), this).then(rect => {
|
||||
@ -235,41 +318,69 @@ export default {
|
||||
computedPage(e) {
|
||||
this.computedChapter(e.content).then((pages) => {
|
||||
let arr = [];
|
||||
let newPages = [];
|
||||
const pagesSync = e.type == 'prev' ? pages.concat(this.pages) : this.pages.concat(pages);
|
||||
pagesSync.forEach(item => {
|
||||
if (arr.indexOf(item.chapter) == -1) arr.push(item.chapter)
|
||||
})
|
||||
if (arr.length > 3) {
|
||||
let reChapter = e.type == 'prev' ? pagesSync[pagesSync.length - 1].chapter : pagesSync[0].chapter;
|
||||
newPages = pagesSync.filter(item => item.chapter != reChapter && (item.type == 'text' || item.type == 'custom' || item.type == 'slot'));
|
||||
} else {
|
||||
newPages = pagesSync.filter(item => (item.type == 'text' || item.type == 'custom' || item.type == 'slot'));
|
||||
}
|
||||
let newPages = pagesSync.filter(item => (item.type == 'text' || item.type == 'custom' || item.type == 'slot'))
|
||||
// pagesSync.forEach(item => {
|
||||
// if (arr.indexOf(item.chapter) == -1) arr.push(item.chapter)
|
||||
// })
|
||||
// if (arr.length > 3) {
|
||||
// let reChapter = e.type == 'prev' ? pagesSync[pagesSync.length - 1].chapter : pagesSync[0].chapter;
|
||||
// newPages = pagesSync.filter(item => item.chapter != reChapter && (item.type == 'text' || item.type == 'custom' || item.type == 'slot'));
|
||||
// } else {
|
||||
// newPages = pagesSync.filter(item => (item.type == 'text' || item.type == 'custom' || item.type == 'slot'));
|
||||
// }
|
||||
if ( this.options.pageType != 'scroll' ) {
|
||||
const prevIndex = this.contents.findIndex(content => content.chapter == newPages[0].chapter);
|
||||
const nextIndex = this.contents.findIndex(content => content.chapter == newPages[newPages.length - 1].chapter);
|
||||
newPages.unshift({
|
||||
title: this.contents[prevIndex].title || '',
|
||||
chapter: this.contents[prevIndex].chapter,
|
||||
type: this.contents[prevIndex].isStart ? 'top' : 'prevLoading',
|
||||
dataId: newPages[0].dataId - 1,
|
||||
start: 0,
|
||||
end: 0
|
||||
})
|
||||
newPages.push({
|
||||
title: this.contents[nextIndex].title || '',
|
||||
chapter: this.contents[nextIndex].chapter,
|
||||
type: this.contents[nextIndex].isEnd ? 'bottom' : 'nextLoading',
|
||||
dataId: newPages[newPages.length - 1].dataId + 1,
|
||||
start: 0,
|
||||
end: 0
|
||||
})
|
||||
if ( !this.firstTipUnable && this.contents[prevIndex].isStart ) {
|
||||
newPages.unshift({
|
||||
title: this.contents[prevIndex].title || '',
|
||||
chapter: this.contents[prevIndex].chapter,
|
||||
type: 'top',
|
||||
direction: 'prev',
|
||||
dataId: newPages[0].dataId - 1,
|
||||
start: 0,
|
||||
end: 0
|
||||
})
|
||||
} else {
|
||||
newPages.unshift({
|
||||
title: this.contents[prevIndex].title || '',
|
||||
chapter: this.contents[prevIndex].chapter,
|
||||
type: 'loading',
|
||||
direction: 'prev',
|
||||
dataId: newPages[0].dataId - 1,
|
||||
start: 0,
|
||||
end: 0
|
||||
})
|
||||
}
|
||||
if ( !this.lastTipUnable && this.contents[nextIndex].isEnd ) {
|
||||
newPages.push({
|
||||
title: this.contents[nextIndex].title || '',
|
||||
chapter: this.contents[nextIndex].chapter,
|
||||
type: 'bottom',
|
||||
direction: 'next',
|
||||
dataId: newPages[newPages.length - 1].dataId + 1,
|
||||
start: 0,
|
||||
end: 0
|
||||
})
|
||||
} else {
|
||||
newPages.push({
|
||||
title: this.contents[nextIndex].title || '',
|
||||
chapter: this.contents[nextIndex].chapter,
|
||||
type: 'loading',
|
||||
direction: 'next',
|
||||
dataId: newPages[newPages.length - 1].dataId + 1,
|
||||
start: 0,
|
||||
end: 0
|
||||
})
|
||||
}
|
||||
this.pages = newPages
|
||||
const nowIndex = newPages.findIndex(page => page.dataId == this.currentDataId);
|
||||
if ( nowIndex == -1 ) {
|
||||
this.currentDataId = e.type == 'next' ? pages[0].dataId : pages[pages.length - 1].dataId;
|
||||
this.onChange(this.currentDataId)
|
||||
this.handleFlipChange(this.currentDataId)
|
||||
} else {
|
||||
this.startAutoplay()
|
||||
}
|
||||
} else {
|
||||
let dataId = e.type == 'prev' ? this.pages[0].dataId : this.pages[this.pages.length-1].dataId
|
||||
@ -322,7 +433,7 @@ export default {
|
||||
filterPage (pageInfo) {
|
||||
if ( pageInfo && pageInfo.dataId > -1 ) {
|
||||
const nowChapters = this.pages.filter(item => item.chapter == pageInfo.chapter && (item.type == 'text' || item.type == 'custom' || item.type == 'slot'))
|
||||
let currentPage = nowChapters.findIndex(item => item.dataId == pageInfo.dataId)
|
||||
const currentPage = nowChapters.findIndex(item => item.dataId == pageInfo.dataId)
|
||||
if ( currentPage > -1 ) {
|
||||
return (currentPage + 1) + ' / ' + nowChapters.length
|
||||
} else {
|
||||
@ -335,32 +446,6 @@ export default {
|
||||
filterDate () {
|
||||
let date = new Date()
|
||||
return Util.zeroize(date.getHours()) + ':' + Util.zeroize(date.getMinutes())
|
||||
},
|
||||
//翻往上一页
|
||||
pagePrev () {
|
||||
if ( this.options.pageType != 'scroll' ) {
|
||||
// #ifndef APP-NVUE
|
||||
this.pagePrevWxs()
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
this.pagePrevBinding()
|
||||
// #endif
|
||||
} else {
|
||||
this.scrollPrev()
|
||||
}
|
||||
},
|
||||
//翻往下一页
|
||||
pageNext () {
|
||||
if ( this.options.pageType != 'scroll' ) {
|
||||
// #ifndef APP-NVUE
|
||||
this.pageNextWxs()
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
this.pageNextBinding()
|
||||
// #endif
|
||||
} else {
|
||||
this.scrollNext()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
@ -1,250 +0,0 @@
|
||||
const Binding = uni.requireNativePlugin('bindingx')
|
||||
const animation = uni.requireNativePlugin('animation')
|
||||
import Util from '../../../js_sdk/util.js'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
disableTouch: false,
|
||||
isTouch: false,
|
||||
flipTouchTime: 0,
|
||||
interval: false,
|
||||
direction: ''
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
if ( this.flip_binding ) {
|
||||
Binding.unbind({
|
||||
token: this.flip_binding.token,
|
||||
eventType: 'pan'
|
||||
})
|
||||
this.flip_binding = null
|
||||
}
|
||||
if ( this.flip_animation_binding ) {
|
||||
Binding.unbind({
|
||||
token: this.flip_animation_binding.token,
|
||||
eventType: 'timing'
|
||||
})
|
||||
this.flip_animation_binding = null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//翻往上一页
|
||||
pagePrevBinding () {
|
||||
if ( !this.isTouch && !this.disableTouch ) {
|
||||
this.isTouch = true
|
||||
this.startX = 0
|
||||
this.onFilpTouchend()
|
||||
}
|
||||
},
|
||||
//翻往下一页
|
||||
pageNextBinding () {
|
||||
if ( !this.isTouch && !this.disableTouch ) {
|
||||
this.isTouch = true
|
||||
this.startX = this.viewWidth
|
||||
this.onFilpTouchend()
|
||||
}
|
||||
},
|
||||
onFilpTouchstart (event) {
|
||||
if ( this.isTouch || this.disableTouch ) {
|
||||
return
|
||||
}
|
||||
this.isTouch = true
|
||||
this.flipTouchTime = 0
|
||||
this.interval = true
|
||||
this.setInterval()
|
||||
let touch = event.touches[0]
|
||||
this.startX = touch.pageX
|
||||
this.startY = touch.pageY
|
||||
},
|
||||
async onFilpTouchmove (event) {
|
||||
if ( this.isTouch && (this.pageType == 'real' || this.pageType == 'cover') && !this.disableTouch && this.flipTouchTime > 200 ) {
|
||||
if ( !this.direction ) {
|
||||
let touch = event.touches[0]
|
||||
if ( touch.pageX < this.startX ) {
|
||||
if ( this.nextDataId ) {
|
||||
this.direction = 'next'
|
||||
}
|
||||
} else {
|
||||
if ( this.prevDataId ) {
|
||||
this.direction = 'prev'
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( this.direction ) {
|
||||
this.disableTouch = true
|
||||
let currentDataId = this.direction == 'next' ? this.currentDataId : this.prevDataId
|
||||
let props = [{
|
||||
element: Util.getEl(this.$refs['flipItem_' + currentDataId][0]),
|
||||
property: 'transform.translateX',
|
||||
expression: `${this.direction == 'next' ? ('x > 0 ? 0 : (x < -' + this.viewWidth + ' ? -' + this.viewWidth + ' : x + 0)') : ('x < 0 ? -' + this.viewWidth + ' : (x > ' + this.viewWidth + ' ? 0 : x-' + this.viewWidth + ')')}`
|
||||
}]
|
||||
if ( this.pageType == 'real' ) {
|
||||
props.push({
|
||||
element: Util.getEl(this.$refs['flipItemWrapper_' + currentDataId][0]),
|
||||
property: 'transform.translateX',
|
||||
expression: `${this.direction == 'next' ? ('x > 0 ? 0 : (x < -' + this.viewWidth + ' ? ' + this.viewWidth + ' : 0 - x)') : ('x < 0 ? ' + this.viewWidth + ' : (x > ' + this.viewWidth + ' ? 0 : ' + this.viewWidth + '-x)')}`
|
||||
})
|
||||
props.push({
|
||||
element: Util.getEl(this.$refs['flipItemBg_' + currentDataId][0]),
|
||||
property: 'transform.translateX',
|
||||
expression: `${this.direction == 'next' ? ('x > 0 ? 0 : (x < -' + this.viewWidth + ' ? -' + this.viewWidth + ' : x + 0)') : ('x < 0 ? -' + this.viewWidth + ' : (x > ' + this.viewWidth + ' ? 0 : x-' + this.viewWidth + ')')}`
|
||||
})
|
||||
let rect = await this.getRect(this.$refs['flipItemBg_' + currentDataId][0])
|
||||
let height = rect.height / 2;
|
||||
let maxDeg = height / 5;
|
||||
props.push({
|
||||
element: Util.getEl(this.$refs['flipItemBg_' + currentDataId][0]),
|
||||
property: 'transform.rotateZ',
|
||||
expression: `${this.direction == 'next' ? 'y/' + maxDeg : '-(y/' + maxDeg + ')'}`
|
||||
})
|
||||
props.push({
|
||||
element: Util.getEl(this.$refs['flipItemShadow_' + currentDataId][0]),
|
||||
property: 'width',
|
||||
expression: `${this.direction == 'next' ? 'abs(x) / 2 + 0' : this.viewWidth / 2 + '-abs(x) / 2'}`
|
||||
})
|
||||
}
|
||||
this.flip_binding = Binding.bind({
|
||||
anchor: Util.getEl(this.$refs.yingbingFlip),
|
||||
eventType: 'pan',
|
||||
props: props
|
||||
}, (e) => {
|
||||
if ((e.state == 'end' || e.state == 'cancel') && this.flip_binding) {
|
||||
this.clearInterval()
|
||||
Binding.unbind({
|
||||
token: this.flip_binding.token,
|
||||
eventType: 'pan'
|
||||
})
|
||||
this.flip_binding = null
|
||||
let value = this.direction == 'next' ? 1 : -1;
|
||||
if (this.flipTouchTime <= 200) {
|
||||
let duration = (this.pageType == 'real' || this.pageType == 'cover') ? 200 : 1
|
||||
this.pageAnimation(value, -value * this.viewWidth, duration);
|
||||
} else {
|
||||
let duration = (this.pageType == 'real' || this.pageType == 'cover') ? 200 : 1
|
||||
let deltaX = Binding.getComputedStyle(Util.getEl(this.$refs['flipItem_' + currentDataId][0])).translateX
|
||||
let late = this.direction == 'next' ? deltaX : this.viewWidth + deltaX
|
||||
if (Math.abs(late) >= this.viewWidth / 4) {
|
||||
this.pageAnimation(value, -value * this.viewWidth, duration)
|
||||
} else {
|
||||
let value = this.direction == 'next' ? 1 : -1;
|
||||
this.pageAnimation(value, 0, duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.resetPageBinding()
|
||||
}
|
||||
}
|
||||
},
|
||||
onFilpTouchend () {
|
||||
if ( this.isTouch && !this.disableTouch ) {
|
||||
this.disableTouch = true
|
||||
this.clearInterval()
|
||||
if ( this.flipTouchTime <= 200 ) {
|
||||
if ( !this.direction ) {
|
||||
if (this.startX > (this.viewWidth / 4) * 3) {
|
||||
if ( this.nextDataId ) {
|
||||
this.direction = 'next'
|
||||
}
|
||||
}
|
||||
if (this.startX < (this.viewWidth / 4)) {
|
||||
if ( this.prevDataId ) {
|
||||
this.direction = 'prev'
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( this.direction ) {
|
||||
let duration = (this.pageType == 'real' || this.pageType == 'cover') ? 200 : 1
|
||||
let value = this.direction == 'next' ? 1 : -1;
|
||||
this.pageAnimation(value, -value * this.viewWidth, duration);
|
||||
} else {
|
||||
this.resetPageBinding()
|
||||
}
|
||||
} else {
|
||||
this.resetPageBinding()
|
||||
}
|
||||
}
|
||||
},
|
||||
getRect (el) {
|
||||
return new Promise(resolve => {
|
||||
uni.requireNativePlugin('dom').getComponentRect(el, res => {
|
||||
resolve(res.size)
|
||||
})
|
||||
})
|
||||
},
|
||||
setInterval () {
|
||||
this.flipTouchTimer = setTimeout(() => {
|
||||
this.flipTouchTime += 10
|
||||
if ( this.interval ) {
|
||||
this.setInterval()
|
||||
}
|
||||
}, 10)
|
||||
},
|
||||
clearInterval () {
|
||||
this.interval = false
|
||||
if ( this.flipTouchTimer ) {
|
||||
clearTimeout(this.flipTouchTimer)
|
||||
this.flipTouchTimer = null
|
||||
}
|
||||
},
|
||||
pageAnimation (value, offset, duration) {
|
||||
let currentDataId = this.direction == 'next' ? this.currentDataId : this.prevDataId
|
||||
let late = this.direction == 'next' ? offset : offset - this.viewWidth;
|
||||
let flipItemTrans = Binding.getComputedStyle(Util.getEl(this.$refs['flipItem_' + currentDataId][0])).translateX
|
||||
let props = [{
|
||||
element: Util.getEl(this.$refs['flipItem_' + currentDataId][0]),
|
||||
property: 'transform.translateX',
|
||||
expression: `linear(t, ${flipItemTrans}, ${late - flipItemTrans}, ${duration})`
|
||||
}]
|
||||
if ( this.pageType == 'real' ) {
|
||||
let flipItemWrapperTrans = Binding.getComputedStyle(Util.getEl(this.$refs['flipItemWrapper_' + currentDataId][0])).translateX
|
||||
props.push({
|
||||
element: Util.getEl(this.$refs['flipItemWrapper_' + currentDataId][0]),
|
||||
property: 'transform.translateX',
|
||||
expression: `linear(t, ${flipItemWrapperTrans}, ${-late - flipItemWrapperTrans}, ${duration})`
|
||||
})
|
||||
let flipItemBgTrans = Binding.getComputedStyle(Util.getEl(this.$refs['flipItemBg_' + currentDataId][0])).translateX
|
||||
props.push({
|
||||
element: Util.getEl(this.$refs['flipItemBg_' + currentDataId][0]),
|
||||
property: 'transform.translateX',
|
||||
expression: `linear(t, ${flipItemBgTrans}, ${late - flipItemBgTrans}, ${duration})`
|
||||
})
|
||||
let flipItemShadowWidth = this.flipTouchTime <= 200 && this.direction == 'prev' ? this.viewWidth : Binding.getComputedStyle(Util.getEl(this.$refs['flipItemShadow_' + currentDataId][0])).width
|
||||
props.push({
|
||||
element: Util.getEl(this.$refs['flipItemShadow_' + currentDataId][0]),
|
||||
property: 'width',
|
||||
expression: `linear(t, ${flipItemShadowWidth}, ${-late - flipItemShadowWidth}, ${duration})`
|
||||
})
|
||||
}
|
||||
this.flip_animation_binding = Binding.bind({
|
||||
eventType: 'timing',
|
||||
exitExpression: 't>' + duration,
|
||||
props: props
|
||||
}, (e) => {
|
||||
if (e.state == 'exit' && this.flip_animation_binding && e.t > duration) {
|
||||
Binding.unbind({
|
||||
token: this.flip_animation_binding.token,
|
||||
eventType: 'timing'
|
||||
})
|
||||
this.flip_animation_binding = null
|
||||
if ( Math.abs(offset) > 0 ) {
|
||||
this.onChange(value > 0 ? this.nextDataId : this.prevDataId)
|
||||
}
|
||||
this.resetPageBinding();
|
||||
}
|
||||
})
|
||||
},
|
||||
resetPageBinding () {
|
||||
this.direction = ''
|
||||
this.flipTouchTime = 0
|
||||
this.startX = 0
|
||||
this.startY = 0
|
||||
this.$nextTick(function () {
|
||||
this.isTouch = false
|
||||
this.disableTouch = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,44 +5,17 @@
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.yingbing-flip {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* #endif */
|
||||
}
|
||||
.flip-item {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* #endif */
|
||||
}
|
||||
.flip-item-wrapper {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* #endif */
|
||||
bottom: 0;
|
||||
}
|
||||
.flip-item-header {
|
||||
/* #ifndef APP-NVUE */
|
||||
@ -55,7 +28,7 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
.flip-item-header-text {
|
||||
font-size: 30rpx;
|
||||
font-size: 24rpx;
|
||||
opacity: .4;
|
||||
font-weight: bold;
|
||||
/* #ifdef APP-NVUE */
|
||||
@ -88,13 +61,13 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
.flip-item-content {
|
||||
flex: 1;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
}
|
||||
.flip-item-text {
|
||||
/* #ifndef APP-NVUE */
|
||||
@ -115,20 +88,11 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.flip-item-bg {
|
||||
position: absolute;
|
||||
/* #ifdef APP-NVUE */
|
||||
box-shadow: 0 20rpx 20rpx rgba(0,0,0,0.2);
|
||||
/* #endif */
|
||||
.flip-loading-text {
|
||||
font-size: 20px;
|
||||
}
|
||||
.flip-item-shadow {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
/* #ifdef APP-NVUE */
|
||||
background-image: linear-gradient(to right, rgba(255,255,255, 0), rgba(0,0,0,.5));
|
||||
opacity: 0.5;
|
||||
/* #endif */
|
||||
}
|
||||
/* #ifndef APP-NVUE */
|
||||
view, image, input, scroll-view, swiper, swiper-item, text, textarea, video {
|
||||
position: static;
|
||||
}
|
||||
/* #endif */
|
@ -1,33 +1,14 @@
|
||||
import Util from '../../../js_sdk/util.js'
|
||||
// #ifdef APP-NVUE
|
||||
import FlipBindingx from './bindingx.js'
|
||||
// #endif
|
||||
export default {
|
||||
// #ifdef APP-NVUE
|
||||
mixins: [FlipBindingx],
|
||||
// #endif
|
||||
computed: {
|
||||
dataReverse () {
|
||||
let data = JSON.parse(JSON.stringify(this.pages))
|
||||
return data.reverse()
|
||||
},
|
||||
current () {
|
||||
return this.dataReverse.findIndex(item => item.dataId == this.currentDataId)
|
||||
return this.pages.findIndex(item => item.dataId == this.currentDataId)
|
||||
},
|
||||
prevDataId () {
|
||||
return this.dataReverse[this.current + 1] && this.dataReverse[this.current + 1].dataId
|
||||
return this.pages[this.current - 1] && this.pages[this.current - 1].dataId
|
||||
},
|
||||
nextDataId () {
|
||||
return this.dataReverse[this.current - 1] && this.dataReverse[this.current - 1].dataId
|
||||
},
|
||||
flipProp () {
|
||||
return {
|
||||
prevDataId: this.prevDataId,
|
||||
nextDataId: this.nextDataId,
|
||||
currentDataId: this.currentDataId,
|
||||
pageType: this.options.pageType,
|
||||
pageTo: this.pageTo
|
||||
}
|
||||
return this.pages[this.current + 1] && this.pages[this.current + 1].dataId
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@ -35,52 +16,27 @@ export default {
|
||||
currentDataId: -1,
|
||||
isShow: false,
|
||||
viewWidth: 0,
|
||||
viewHeight: 0,
|
||||
pageTo: 0,
|
||||
moreLoading: false,
|
||||
initLoading: true,
|
||||
loadingText: '正在加载内容',
|
||||
loadStatus: 'none',
|
||||
loadChapter: -1,
|
||||
loadValue: 0
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if ( this.pageType != 'scroll' ) {
|
||||
this.$nextTick(function () {
|
||||
setTimeout(() => {
|
||||
this.getViewRect()
|
||||
}, 50)
|
||||
})
|
||||
moreLoading: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//翻往上一页
|
||||
pagePrevWxs () {
|
||||
this.pageTo = 0
|
||||
this.$nextTick(function(){
|
||||
this.pageTo = -1
|
||||
})
|
||||
pagePrevFlip () {
|
||||
this.$refs.flip.flipToPrev()
|
||||
},
|
||||
//翻往下一页
|
||||
pageNextWxs () {
|
||||
this.pageTo = 0
|
||||
this.$nextTick(function(){
|
||||
this.pageTo = 1
|
||||
})
|
||||
pageNextFlip () {
|
||||
this.$refs.flip.flipToNext()
|
||||
},
|
||||
reload () {
|
||||
if ( this.loadStatus == 'fail' || this.loadStatus == 'timeout' ) {
|
||||
this.initLoading = false
|
||||
this.loadingText = '正在加载内容'
|
||||
this.loadStatus = 'none';
|
||||
this.loadmore(this.loadChapter, this.loadValue);
|
||||
this.loadChapter = -1;
|
||||
this.loadValue = 0;
|
||||
}
|
||||
reloadLoadmoreFlip (p) {
|
||||
let loadIndex = this.pages.findIndex(page => p.dataId == page.dataId)
|
||||
this.$set(this.pages[loadIndex], 'type', 'loading')
|
||||
let nextChapter = p.direction == 'next' ? p.chapter + 1 : p.chapter - 1
|
||||
this.loadmoreFlip(nextChapter, p.direction == 'next' ? 1 : -1);
|
||||
},
|
||||
loadmore (chapter, value) {
|
||||
loadmoreFlip (chapter, value) {
|
||||
this.$emit('loadmore', chapter, (status, content) => {
|
||||
this.moreLoading = false;
|
||||
if (status == 'success') {
|
||||
const index = this.contents.findIndex(item => item.chapter == content.chapter)
|
||||
if (index > -1) {
|
||||
@ -93,33 +49,16 @@ export default {
|
||||
type: value > 0 ? 'next' : 'prev'
|
||||
});
|
||||
this.preload(chapter)
|
||||
this.moreLoading = false;
|
||||
} else if ( status == 'fail' ) {
|
||||
this.loadStatus = status;
|
||||
this.loadingText = '请求失败,点击重试'
|
||||
this.initLoading = true
|
||||
this.loadChapter = chapter;
|
||||
this.loadValue = value;
|
||||
} else {
|
||||
this.loadStatus = status;
|
||||
this.loadingText = '请求超时,点击重试'
|
||||
this.initLoading = true
|
||||
this.loadChapter = chapter;
|
||||
this.loadValue = value;
|
||||
let loadIndex = this.pages.findIndex(page => page.type == 'loading' && page.direction == (value > 0 ? 'next' : 'prev'))
|
||||
this.$set(this.pages[loadIndex], 'type', status)
|
||||
}
|
||||
})
|
||||
},
|
||||
getViewRect () {
|
||||
return new Promise(resolve => {
|
||||
Util.getRect('.yingbing-flip', this.$refs.yingbingFlip, this).then(res => {
|
||||
this.viewWidth = res.width
|
||||
this.viewHeight = res.height
|
||||
this.isShow = true
|
||||
resolve(true)
|
||||
})
|
||||
})
|
||||
handleFlipChangeRender (e) {
|
||||
this.handleFlipChange(e.detail.dataId)
|
||||
},
|
||||
onChange(dataId) {
|
||||
handleFlipChange (dataId) {
|
||||
const value = dataId < this.currentDataId ? -1 : 1
|
||||
this.currentDataId = dataId
|
||||
const index = this.pages.findIndex(page => page.dataId == dataId);
|
||||
@ -130,10 +69,9 @@ export default {
|
||||
pageInfo.currentPage = nowChapters.findIndex(item => item.dataId == pageInfo.dataId) + 1
|
||||
if ( this.contents[contentIndex].title ) pageInfo.title = this.contents[contentIndex].title
|
||||
this.pageInfo = pageInfo
|
||||
this.$emit('change', pageInfo, this.pages)
|
||||
this._emitPageInfo(pageInfo, this.pages)
|
||||
const nextType = this.pages[index + value] && this.pages[index + value].type
|
||||
const loadings = ['nextLoading', 'prevLoading']
|
||||
if ( loadings.indexOf(this.pages[index].type) >-1 || loadings.indexOf(nextType) >-1) {
|
||||
if ( this.pages[index].type == 'loading' || nextType == 'loading') {
|
||||
if (this.moreLoading) return
|
||||
this.moreLoading = true;
|
||||
const loadChapter = this.pages[index].chapter + value;
|
||||
@ -146,8 +84,10 @@ export default {
|
||||
this.preload(loadChapter)
|
||||
this.moreLoading = false;
|
||||
} else {
|
||||
this.loadmore(loadChapter, value)
|
||||
this.loadmoreFlip(loadChapter, value)
|
||||
}
|
||||
} else {
|
||||
this.startAutoplay()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,569 +0,0 @@
|
||||
<template>
|
||||
<view
|
||||
class="yingbing-flip"
|
||||
ref="yingbingFlip"
|
||||
:style="{
|
||||
'background-color': options.bgColor
|
||||
}"
|
||||
:prop="flipProp"
|
||||
:change:prop="flip.propWatcher"
|
||||
@touchstart="flip.touchstart"
|
||||
@touchmove="flip.touchmove"
|
||||
@touchend="flip.touchend">
|
||||
<template v-if="isShow">
|
||||
<view v-if="(item.dataId == currentDataIdSync || item.dataId == prevDataId || item.dataId == nextDataId)"
|
||||
class="flip-item"
|
||||
:class="'flip-item_' + item.dataId"
|
||||
v-for="(item, index) in dataReverse"
|
||||
:key="item.dataId"
|
||||
:style="{
|
||||
'transform': item.dataId < currentDataIdSync ? `translateX(${-viewWidth}px)` : ''
|
||||
}">
|
||||
<view
|
||||
class="flip-item-wrapper"
|
||||
:class="'flip-item-wrapper_' + item.dataId"
|
||||
:style="{
|
||||
'padding-left': options.slide + 'px',
|
||||
'padding-right': options.slide + 'px',
|
||||
'padding-top': options.topGap + 'px',
|
||||
'padding-bottom': options.bottomGap + 'px',
|
||||
'background': options.bgColor,
|
||||
'transform': item.dataId < currentDataIdSync ? options.pageType == 'real' ? `translateX(${viewWidth}px)` : 'translateX(0)' : ''
|
||||
}">
|
||||
<view class="flip-item-header" v-if="options.headerShow">
|
||||
<text class="flip-item-header-text" :style="{
|
||||
color: options.color
|
||||
}">{{item.title}}</text>
|
||||
</view>
|
||||
<template v-if="item.type == 'text'">
|
||||
<view class="flip-item-text flip-item-content"
|
||||
>
|
||||
<text class="flip-text"
|
||||
v-for="(text, i) in item.text" :key="i"
|
||||
:style="{
|
||||
'margin-top': options.lineHeight + 'px',
|
||||
'height': options.fontSize + 'px',
|
||||
'font-size': options.fontSize + 'px',
|
||||
'color': options.color
|
||||
}">{{text}}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else-if="item.type == 'custom'">
|
||||
<view class="flip-custom flip-item-content" v-html="item.text">
|
||||
</view>
|
||||
</template>
|
||||
<template v-else-if="item.type == 'slot'">
|
||||
<view class="flip-slot flip-item-content">
|
||||
<slot :name="item.text"></slot>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else-if="item.type == 'nextLoading' || item.type == 'prevLoading' ">
|
||||
<view class="flip-loading flip-item-content">
|
||||
<text :style="{
|
||||
'color': options.color,
|
||||
'font-size': options.fontSize + 'px'
|
||||
}">正在加载内容</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else-if="item.type == 'top' || item.type == 'bottom' ">
|
||||
<view class="flip-loading flip-item-content">
|
||||
<text :style="{
|
||||
'color': options.color,
|
||||
'font-size': options.fontSize + 'px'
|
||||
}">{{item.type == 'top' ? '前面已经没有了' : '后面已经没有了'}}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view class="flip-loading flip-item-content">
|
||||
<text :style="{
|
||||
'color': options.color,
|
||||
'font-size': options.fontSize + 'px'
|
||||
}">未知类型页面</text>
|
||||
</view>
|
||||
</template>
|
||||
<view class="flip-item-footer" v-if="options.footerShow">
|
||||
<text class="flip-item-footer-text" :style="{
|
||||
color: options.color
|
||||
}">{{filterDate()}}</text>
|
||||
<text class="flip-item-footer-text" :style="{
|
||||
color: options.color
|
||||
}">{{filterPage(item)}}</text>
|
||||
<battery :color="options.color" style="opacity: 0.5"></battery>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="flip-item-bg"
|
||||
:class="'flip-item-bg_' + item.dataId"
|
||||
:style="{
|
||||
left: viewWidth + 'px',
|
||||
width: viewWidth + 'px',
|
||||
height: (viewHeight * 1.5) + 'px',
|
||||
top: (viewHeight / 2 - (viewHeight * 1.5) / 2) + 'px',
|
||||
background: options.bgColor,
|
||||
}"></view>
|
||||
<view class="flip-item-shadow" :class="'flip-item-shadow_' + item.dataId"></view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Util from '../../../js_sdk/util.js'
|
||||
import Battery from '../battery.vue'
|
||||
export default {
|
||||
components: {
|
||||
Battery
|
||||
},
|
||||
props: {
|
||||
currentDataId: {
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
data: {
|
||||
type: Array,
|
||||
default () {
|
||||
return new Array
|
||||
}
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
default () {
|
||||
return new Object
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dataReverse () {
|
||||
let data = JSON.parse(JSON.stringify(this.data))
|
||||
data.reverse()
|
||||
return data
|
||||
},
|
||||
prevDataId () {
|
||||
return this.dataReverse[this.current + 1] && this.dataReverse[this.current + 1].dataId
|
||||
},
|
||||
nextDataId () {
|
||||
return this.dataReverse[this.current - 1] && this.dataReverse[this.current - 1].dataId
|
||||
},
|
||||
flipProp () {
|
||||
return {
|
||||
current: this.current,
|
||||
prevDataId: this.prevDataId,
|
||||
nextDataId: this.nextDataId,
|
||||
currentDataId: this.currentDataIdSync,
|
||||
pageType: this.options.pageType,
|
||||
pageTo: this.pageTo
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
isShow: false,
|
||||
viewWidth: 0,
|
||||
viewHeight: 0,
|
||||
currentDataIdSync: -1,
|
||||
current: -1,
|
||||
pageTo: 0
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.currentDataIdSync = this.currentDataId
|
||||
this.current = this.dataReverse.findIndex(item => item.dataId == this.currentDataIdSync)
|
||||
this.$nextTick(function () {
|
||||
setTimeout(() => {
|
||||
// #ifndef APP-NVUE
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
query.select('.yingbing-flip').boundingClientRect(data => {
|
||||
this.viewWidth = data.width
|
||||
this.viewHeight = data.height
|
||||
this.isShow = true
|
||||
}).exec();
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
uni.requireNativePlugin('dom').getComponentRect(this.$refs.yingbingFlip, res => {
|
||||
this.viewWidth = res.size.width
|
||||
this.viewHeight = res.size.height
|
||||
this.isShow = true
|
||||
})
|
||||
// #endif
|
||||
}, 50)
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
onChange (e) {
|
||||
this.current = e.current
|
||||
this.currentDataIdSync = this.dataReverse[this.current].dataId
|
||||
this.$emit('change', this.currentDataIdSync)
|
||||
},
|
||||
pagePrev () {
|
||||
this.pageTo = 0
|
||||
this.$nextTick(function(){
|
||||
this.pageTo = -1
|
||||
})
|
||||
},
|
||||
pageNext () {
|
||||
this.pageTo = 0
|
||||
this.$nextTick(function(){
|
||||
this.pageTo = 1
|
||||
})
|
||||
},
|
||||
filterPage (pageInfo) {
|
||||
const nowChapters = this.data.filter(item => item.chapter == pageInfo.chapter && (item.type == 'text' || item.type == 'custom' || item.type == 'slot'))
|
||||
let currentPage = nowChapters.findIndex(item => item.dataId == pageInfo.dataId)
|
||||
if ( currentPage > -1 ) {
|
||||
return (currentPage + 1) + ' / ' + nowChapters.length
|
||||
} else {
|
||||
return pageInfo.type == 'top' ? '最前面' : pageInfo.type == 'bottom' ? '最后面' : pageInfo.type.indexOf('Loading') > -1 ? '请等待' : ''
|
||||
}
|
||||
},
|
||||
filterDate () {
|
||||
let date = new Date()
|
||||
return Util.zeroize(date.getHours()) + ':' + Util.zeroize(date.getMinutes())
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
currentDataId (newVal) {
|
||||
this.currentDataIdSync = newVal
|
||||
this.current = this.dataReverse.findIndex(item => item.dataId == this.currentDataIdSync)
|
||||
},
|
||||
data (newVal) {
|
||||
this.$nextTick(function () {
|
||||
this.current = this.dataReverse.findIndex(item => item.dataId == this.currentDataIdSync)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- #ifdef APP-VUE || H5 || MP-QQ || MP-WEIXIN -->
|
||||
<script lang="wxs" module="flip">
|
||||
function touchstart (event, ins) {
|
||||
var state = ins.getState()
|
||||
if ( state.isTouch || state.disableTouch ) {
|
||||
return
|
||||
}
|
||||
state.isTouch = true
|
||||
state.touchTime = 0
|
||||
state.interval = true
|
||||
setInterval(ins)
|
||||
var touch = event.touches[0]
|
||||
state.startX = touch.pageX
|
||||
state.startY = touch.pageY
|
||||
}
|
||||
function touchmove (event, ins) {
|
||||
event.preventDefault && event.preventDefault()
|
||||
var state = ins.getState()
|
||||
if ( state.isTouch && (state.pageType == 'real' || state.pageType == 'cover') && !state.disableTouch ) {
|
||||
var touch = event.touches[0]
|
||||
if (state.direction) {
|
||||
var rect = ins.getBoundingClientRect()
|
||||
var height = rect.height / 2;
|
||||
var maxDeg = height / 5;
|
||||
state.rotate = state.direction == 'next' ? ((touch.pageY - height) / maxDeg) : -((touch.pageY - height) / maxDeg);
|
||||
state.offset = touch.pageX - state.startX;
|
||||
if ( (state.offset > 0 && state.direction == 'next') || (state.offset < 0 && state.direction == 'prev') ) {
|
||||
state.offset = 0
|
||||
}
|
||||
if ( Math.abs(state.offset) <= rect.width ) {
|
||||
animation(state.offset, 0, ins);
|
||||
}
|
||||
} else {
|
||||
if ( touch.pageX < state.startX ) {
|
||||
if ( state.nextDataId ) {
|
||||
state.direction = 'next'
|
||||
}
|
||||
} else {
|
||||
if ( state.prevDataId ) {
|
||||
state.direction = 'prev'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function touchend (event, ins) {
|
||||
var state = ins.getState()
|
||||
clearInterval(ins)
|
||||
if ( state.isTouch && !state.disableTouch ) {
|
||||
var rect = ins.getBoundingClientRect()
|
||||
if ( !state.direction && state.touchTime <= 200 ) {
|
||||
//获取点击位置,判断向哪里翻页
|
||||
if (state.startX > (rect.width / 4) * 3) {
|
||||
if ( state.nextDataId ) {
|
||||
state.direction = 'next'
|
||||
}
|
||||
}
|
||||
if (state.startX < (rect.width / 4)) {
|
||||
if ( state.prevDataId ) {
|
||||
state.direction = 'prev'
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state.direction) {
|
||||
state.disableTouch = true
|
||||
if (state.touchTime <= 200) {
|
||||
var duration = (state.pageType == 'real' || state.pageType == 'cover') ? 200 : 0
|
||||
var value = state.direction == 'next' ? 1 : -1;
|
||||
animation(-value * rect.width, duration, ins);
|
||||
ins.setTimeout(function () {
|
||||
reset(-value * rect.width, ins);
|
||||
state.current -= value
|
||||
ins.callMethod('onChange', {
|
||||
current: state.current
|
||||
})
|
||||
}, duration)
|
||||
} else {
|
||||
var duration = (state.pageType == 'real' || state.pageType == 'cover') ? 100 : 0
|
||||
if (Math.abs(state.offset) >= rect.width / 4) {
|
||||
var value = state.direction == 'next' ? 1 : -1;
|
||||
animation(-value * rect.width, duration, ins);
|
||||
ins.setTimeout(function () {
|
||||
reset(-value * rect.width, ins);
|
||||
state.current -= value
|
||||
ins.callMethod('onChange', {
|
||||
current: state.current
|
||||
})
|
||||
}, duration)
|
||||
} else {
|
||||
animation(0, duration, ins);
|
||||
ins.setTimeout(function () {
|
||||
reset(0, ins);
|
||||
}, duration)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reset(0, ins)
|
||||
}
|
||||
}
|
||||
}
|
||||
function propWatcher (newVal, oldVal, ins) {
|
||||
ins.setTimeout(function () {
|
||||
var state = ins.getState()
|
||||
state.current = newVal.current
|
||||
state.currentDataId = newVal.currentDataId
|
||||
state.prevDataId = newVal.prevDataId
|
||||
state.nextDataId = newVal.nextDataId
|
||||
state.pageType = newVal.pageType
|
||||
if (newVal.pageTo != (oldVal && oldVal.pageTo)) {
|
||||
if ( !state.disableTouch ) {
|
||||
if ( newVal.pageTo == -1 && state.prevDataId ) {
|
||||
state.isTouch = true
|
||||
state.startX = 1
|
||||
state.touchTime = 0
|
||||
state.direction = 'prev'
|
||||
touchend(null, ins)
|
||||
}
|
||||
if ( newVal.pageTo == 1 && state.nextDataId ) {
|
||||
state.isTouch = true
|
||||
var rect = ins.getBoundingClientRect()
|
||||
state.startX = rect.width
|
||||
state.touchTime = 0
|
||||
state.direction = 'next'
|
||||
touchend(null, ins)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 50)
|
||||
}
|
||||
function setInterval (ins) {
|
||||
var state = ins.getState()
|
||||
state.touchTimer = ins.setTimeout(function () {
|
||||
state.touchTime += 10
|
||||
if ( state.interval ) {
|
||||
setInterval(ins)
|
||||
}
|
||||
}, 10)
|
||||
}
|
||||
function clearInterval (ins) {
|
||||
var state = ins.getState()
|
||||
state.interval = false
|
||||
if ( state.touchTimer ) {
|
||||
ins.clearTimeout(state.touchTimer)
|
||||
state.touchTimer = null
|
||||
}
|
||||
}
|
||||
function reset (offset, ins) {
|
||||
var state = ins.getState()
|
||||
var rect = ins.getBoundingClientRect()
|
||||
if ( state.direction ) {
|
||||
var late = state.direction == 'next' ? offset : offset - rect.width;
|
||||
var currentDataId = state.direction == 'next' ? state.currentDataId : state.prevDataId
|
||||
if ( currentDataId ) {
|
||||
ins.selectComponent('.flip-item_' + currentDataId).setStyle({
|
||||
transform: 'translateX(' + (-late) + 'px)',
|
||||
'box-shadow': '',
|
||||
transition: ''
|
||||
})
|
||||
if ( state.pageType == 'real' ) {
|
||||
ins.selectComponent('.flip-item-bg_' + currentDataId).setStyle({
|
||||
transform: 'translateX(' + late + 'px) rotateZ(' + state.rotate + 'deg)',
|
||||
'box-shadow': '',
|
||||
transition: ''
|
||||
})
|
||||
}
|
||||
ins.selectComponent('.flip-item-shadow_' + currentDataId).setStyle({
|
||||
'box-shadow': '',
|
||||
transition: ''
|
||||
})
|
||||
}
|
||||
}
|
||||
state.direction = null
|
||||
state.isTouch = false
|
||||
state.disableTouch = false
|
||||
state.offset = 0
|
||||
state.touchTime = 0
|
||||
state.startX = 0
|
||||
state.startY = 0
|
||||
}
|
||||
function animation (offset, duration, ins) {
|
||||
var state = ins.getState()
|
||||
var rect = ins.getBoundingClientRect()
|
||||
var late = state.direction == 'next' ? offset : offset - rect.width;
|
||||
var currentDataId = state.direction == 'next' ? state.currentDataId : state.prevDataId
|
||||
ins.selectComponent('.flip-item_' + currentDataId).setStyle({
|
||||
transform: 'translateX(' + late + 'px)',
|
||||
'box-shadow': state.pageType == 'real' ? '0 0 30px 20px rgba(0,0,0,0.4)' : state.pageType == 'cover' ? '0 0 10px 5px rgba(0,0,0,0.3)' : '',
|
||||
transition: duration > 0 ? 'transform ' + duration + 'ms' : ''
|
||||
})
|
||||
if ( state.pageType == 'real' ) {
|
||||
ins.selectComponent('.flip-item-wrapper_' + currentDataId).setStyle({
|
||||
transform: 'translateX(' + (-late) + 'px)',
|
||||
transition: duration > 0 ? 'transform ' + duration + 'ms' : ''
|
||||
})
|
||||
ins.selectComponent('.flip-item-bg_' + currentDataId).setStyle({
|
||||
transform: 'translateX(' + late + 'px) rotateZ(' + state.rotate + 'deg)',
|
||||
'box-shadow': '-5px 0 20px rgba(0,0,0,0.1)',
|
||||
transition: duration > 0 ? 'transform ' + duration + 'ms, ' + 'boxShadow ' + duration + 'ms' : ''
|
||||
})
|
||||
ins.selectComponent('.flip-item-shadow_' + currentDataId).setStyle({
|
||||
'box-shadow': '0 0 60px ' + (Math.abs(late) > 30 ? 30 : Math.abs(late)) + 'px rgba(0,0,0,0.4)',
|
||||
transition: duration > 0 ? 'boxShadow ' + duration + 'ms' : ''
|
||||
})
|
||||
} else {
|
||||
ins.selectComponent('.flip-item-wrapper_' + currentDataId).setStyle({
|
||||
transform: 'translateX(0px)',
|
||||
transition: duration > 0 ? 'transform ' + duration + 'ms' : ''
|
||||
})
|
||||
ins.selectComponent('.flip-item-shadow_' + currentDataId).setStyle({
|
||||
'box-shadow': '0 0 60px 0 rgba(0,0,0,0.5)',
|
||||
transition: duration > 0 ? 'boxShadow ' + duration + 'ms' : ''
|
||||
})
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
touchstart: touchstart,
|
||||
touchmove: touchmove,
|
||||
touchend: touchend,
|
||||
propWatcher: propWatcher
|
||||
}
|
||||
</script>
|
||||
<!-- #endif -->
|
||||
|
||||
<style scoped>
|
||||
.yingbing-flip {
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
position: relative;
|
||||
}
|
||||
.flip-item {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* #endif */
|
||||
}
|
||||
.flip-item-wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* #endif */
|
||||
}
|
||||
.flip-item-header {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
justify-content: center;
|
||||
height: 50rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.flip-item-header-text {
|
||||
font-size: 24rpx;
|
||||
opacity: .4;
|
||||
font-weight: bold;
|
||||
}
|
||||
.flip-item-footer {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
height: 50rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.flip-item-footer-text {
|
||||
font-size: 24rpx;
|
||||
opacity: .4;
|
||||
font-weight: bold;
|
||||
}
|
||||
.flip-item-content {
|
||||
flex: 1;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* #endif */
|
||||
}
|
||||
.flip-item-text {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* #endif */
|
||||
},
|
||||
.flip-text {
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
white-space: pre-wrap;
|
||||
font-family: Microsoft YaHei, 微软雅黑;
|
||||
/* #endif */
|
||||
}
|
||||
.flip-loading {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.flip-item-bg {
|
||||
position: absolute;
|
||||
}
|
||||
.flip-item-shadow {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
</style>
|
@ -1,208 +0,0 @@
|
||||
function touchstart (event, ins) {
|
||||
var state = ins.getState()
|
||||
if ( state.isTouch || state.disableTouch ) {
|
||||
return
|
||||
}
|
||||
state.isTouch = true
|
||||
state.touchTime = 0
|
||||
state.interval = true
|
||||
setInterval(ins)
|
||||
var touch = event.touches[0]
|
||||
state.startX = touch.pageX
|
||||
state.startY = touch.pageY
|
||||
}
|
||||
function touchmove (event, ins) {
|
||||
event.preventDefault && event.preventDefault()
|
||||
var state = ins.getState()
|
||||
if ( state.isTouch && (state.pageType == 'real' || state.pageType == 'cover') && !state.disableTouch ) {
|
||||
var touch = event.touches[0]
|
||||
if (state.direction) {
|
||||
var rect = ins.getBoundingClientRect()
|
||||
var height = rect.height / 2;
|
||||
var maxDeg = height / 5;
|
||||
state.rotate = state.direction == 'next' ? ((touch.pageY - height) / maxDeg) : -((touch.pageY - height) / maxDeg);
|
||||
state.offset = touch.pageX - state.startX;
|
||||
if ( (state.offset > 0 && state.direction == 'next') || (state.offset < 0 && state.direction == 'prev') ) {
|
||||
state.offset = 0
|
||||
}
|
||||
if ( Math.abs(state.offset) <= rect.width ) {
|
||||
animation(state.offset, 0, ins)
|
||||
}
|
||||
} else {
|
||||
if ( touch.pageX < state.startX ) {
|
||||
if ( state.nextDataId ) {
|
||||
state.direction = 'next'
|
||||
}
|
||||
} else {
|
||||
if ( state.prevDataId ) {
|
||||
state.direction = 'prev'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function touchend (event, ins) {
|
||||
var state = ins.getState()
|
||||
clearInterval(ins)
|
||||
if ( state.isTouch && !state.disableTouch ) {
|
||||
var rect = ins.getBoundingClientRect()
|
||||
if ( !state.direction && state.touchTime <= 200 ) {
|
||||
//获取点击位置,判断向哪里翻页
|
||||
if (state.startX > (rect.width / 4) * 3) {
|
||||
if ( state.nextDataId ) {
|
||||
state.direction = 'next'
|
||||
}
|
||||
}
|
||||
if (state.startX < (rect.width / 4)) {
|
||||
if ( state.prevDataId ) {
|
||||
state.direction = 'prev'
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state.direction) {
|
||||
state.disableTouch = true
|
||||
if (state.touchTime <= 200) {
|
||||
var duration = (state.pageType == 'real' || state.pageType == 'cover') ? 200 : 0
|
||||
var value = state.direction == 'next' ? 1 : -1;
|
||||
animation(-value * rect.width, duration, ins);
|
||||
ins.setTimeout(function () {
|
||||
reset(-value * rect.width, ins);
|
||||
ins.callMethod('onChange', value > 0 ? state.nextDataId : state.prevDataId)
|
||||
}, duration)
|
||||
} else {
|
||||
var duration = (state.pageType == 'real' || state.pageType == 'cover') ? 100 : 0
|
||||
if (Math.abs(state.offset) >= rect.width / 4) {
|
||||
var value = state.direction == 'next' ? 1 : -1;
|
||||
animation(-value * rect.width, duration, ins);
|
||||
ins.setTimeout(function () {
|
||||
reset(-value * rect.width, ins);
|
||||
ins.callMethod('onChange', value > 0 ? state.nextDataId : state.prevDataId)
|
||||
}, duration)
|
||||
} else {
|
||||
animation(0, duration, ins);
|
||||
ins.setTimeout(function () {
|
||||
reset(0, ins);
|
||||
}, duration)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reset(0, ins)
|
||||
}
|
||||
}
|
||||
}
|
||||
function propWatcher (newVal, oldVal, ins) {
|
||||
if ( oldVal ) {
|
||||
var state = ins.getState()
|
||||
state.currentDataId = newVal.currentDataId
|
||||
state.prevDataId = newVal.prevDataId
|
||||
state.nextDataId = newVal.nextDataId
|
||||
state.pageType = newVal.pageType
|
||||
if (newVal.pageTo != oldVal.pageTo) {
|
||||
if ( !state.disableTouch ) {
|
||||
if ( newVal.pageTo == -1 && state.prevDataId ) {
|
||||
state.isTouch = true
|
||||
state.startX = 1
|
||||
state.touchTime = 0
|
||||
state.direction = 'prev'
|
||||
touchend(null, ins)
|
||||
}
|
||||
if ( newVal.pageTo == 1 && state.nextDataId ) {
|
||||
state.isTouch = true
|
||||
var rect = ins.getBoundingClientRect()
|
||||
state.startX = rect.width
|
||||
state.touchTime = 0
|
||||
state.direction = 'next'
|
||||
touchend(null, ins)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function setInterval (ins) {
|
||||
var state = ins.getState()
|
||||
state.touchTimer = ins.setTimeout(function () {
|
||||
state.touchTime += 10
|
||||
if ( state.interval ) {
|
||||
setInterval(ins)
|
||||
}
|
||||
}, 10)
|
||||
}
|
||||
function clearInterval (ins) {
|
||||
var state = ins.getState()
|
||||
state.interval = false
|
||||
if ( state.touchTimer ) {
|
||||
ins.clearTimeout(state.touchTimer)
|
||||
state.touchTimer = null
|
||||
}
|
||||
}
|
||||
function reset (offset, ins) {
|
||||
var state = ins.getState()
|
||||
var rect = ins.getBoundingClientRect()
|
||||
if ( state.direction ) {
|
||||
var late = state.direction == 'next' ? offset : offset - rect.width;
|
||||
var currentDataId = state.direction == 'next' ? state.currentDataId : state.prevDataId
|
||||
if ( currentDataId ) {
|
||||
var draw = function () {
|
||||
ins.selectComponent('.flip-item_' + currentDataId).setStyle({
|
||||
transform: 'translateX(' + late + 'px)',
|
||||
'box-shadow': '',
|
||||
transition: ''
|
||||
})
|
||||
if ( state.pageType == 'real' ) {
|
||||
ins.selectComponent('.flip-item-bg_' + currentDataId).setStyle({
|
||||
transform: 'translateX(' + late + 'px) rotateZ(' + state.rotate + 'deg)',
|
||||
'box-shadow': '',
|
||||
transition: ''
|
||||
})
|
||||
}
|
||||
ins.selectComponent('.flip-item-shadow_' + currentDataId).setStyle({
|
||||
'box-shadow': '',
|
||||
transition: ''
|
||||
})
|
||||
}
|
||||
ins.requestAnimationFrame(draw)
|
||||
}
|
||||
}
|
||||
state.direction = null
|
||||
state.isTouch = false
|
||||
state.disableTouch = false
|
||||
state.offset = 0
|
||||
state.touchTime = 0
|
||||
state.startX = 0
|
||||
state.startY = 0
|
||||
}
|
||||
function animation (offset, duration, ins) {
|
||||
var state = ins.getState()
|
||||
var rect = ins.getBoundingClientRect()
|
||||
var late = state.direction == 'next' ? offset : offset - rect.width;
|
||||
var currentDataId = state.direction == 'next' ? state.currentDataId : state.prevDataId
|
||||
var draw = function () {
|
||||
ins.selectComponent('.flip-item_' + currentDataId).setStyle({
|
||||
transform: 'translateX(' + late + 'px)',
|
||||
'box-shadow': state.pageType == 'real' ? '0 0 30px 20px rgba(0,0,0,0.4)' : state.pageType == 'cover' ? '0 0 10px 5px rgba(0,0,0,0.3)' : '',
|
||||
transition: duration > 0 ? 'transform ' + duration + 'ms' : ''
|
||||
})
|
||||
if ( state.pageType == 'real' ) {
|
||||
ins.selectComponent('.flip-item-wrapper_' + currentDataId).setStyle({
|
||||
transform: 'translateX(' + (-late) + 'px)',
|
||||
transition: duration > 0 ? 'transform ' + duration + 'ms' : ''
|
||||
})
|
||||
ins.selectComponent('.flip-item-bg_' + currentDataId).setStyle({
|
||||
transform: 'translateX(' + late + 'px) rotateZ(' + state.rotate + 'deg)',
|
||||
'box-shadow': '-5px 0 20px rgba(0,0,0,0.1)',
|
||||
transition: duration > 0 ? 'transform ' + duration + 'ms, ' + 'boxShadow ' + duration + 'ms' : ''
|
||||
})
|
||||
ins.selectComponent('.flip-item-shadow_' + currentDataId).setStyle({
|
||||
'box-shadow': '0 0 60px 30px rgba(0,0,0,0.4)',
|
||||
transition: duration > 0 ? 'boxShadow ' + duration + 'ms' : ''
|
||||
})
|
||||
}
|
||||
}
|
||||
ins.requestAnimationFrame(draw)
|
||||
}
|
||||
module.exports = {
|
||||
touchstart: touchstart,
|
||||
touchmove: touchmove,
|
||||
touchend: touchend,
|
||||
propWatcher: propWatcher
|
||||
}
|
@ -76,7 +76,7 @@
|
||||
})
|
||||
},
|
||||
setFontFace () {
|
||||
this.$refs.webview.evalJS("setFontFace(" + encodeURIComponent(JSON.stringify(this.fontFace)) + ")")
|
||||
this.$refs.webview && this.$refs.webview.evalJS("setFontFace(" + encodeURIComponent(JSON.stringify(this.fontFace)) + ")")
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -23,7 +23,7 @@ export default {
|
||||
return
|
||||
}
|
||||
this.scrolling = true
|
||||
this.$refs.list.scrollTo(this.scrollTop + this.options.fontSize + this.options.lineHeight, true)
|
||||
this.$refs.list.scrollTo(this.scrollTop + (this.windowHeight / 2), true)
|
||||
this.scrollTimer = setTimeout(() => {
|
||||
this.scrolling = false
|
||||
clearTimeout(this.scrollTimer)
|
||||
@ -35,14 +35,14 @@ export default {
|
||||
return
|
||||
}
|
||||
this.scrolling = true
|
||||
this.$refs.list.scrollTo(this.scrollTop - (this.options.fontSize + this.options.lineHeight), true)
|
||||
this.$refs.list.scrollTo(this.scrollTop - (this.windowHeight / 2), true)
|
||||
this.scrollTimer = setTimeout(() => {
|
||||
this.scrolling = false
|
||||
clearTimeout(this.scrollTimer)
|
||||
this.scrollTimer = null
|
||||
}, 300)
|
||||
},
|
||||
onPulldown (callback) {
|
||||
pulldownScroll (callback) {
|
||||
let contentsIndex = this.contents.findIndex(content => content.chapter == this.pages[0].chapter)
|
||||
if ( this.contents[contentsIndex].isStart ) {
|
||||
callback('end')
|
||||
@ -64,7 +64,8 @@ export default {
|
||||
this.$refs.list.resetLoadmore()
|
||||
}
|
||||
},
|
||||
onLoadmore (callback) {
|
||||
loadmoreScroll (callback) {
|
||||
this.stopAutoplay()
|
||||
let contentsIndex = this.contents.findIndex(content => content.chapter == this.pages[this.pages.length - 1].chapter)
|
||||
if ( this.contents[contentsIndex].isEnd ) {
|
||||
callback('end')
|
||||
@ -103,12 +104,13 @@ export default {
|
||||
});
|
||||
this.preload(chapter)
|
||||
}
|
||||
callback && callback('success')
|
||||
callback && callback(status)
|
||||
})
|
||||
}
|
||||
},
|
||||
async scrollEnd(e) {
|
||||
let rate = Math.floor(e.scrollTop / this.viewHeight)
|
||||
const size = await this.getRect()
|
||||
let rate = Math.floor(e.scrollTop / size.height)
|
||||
let maybe = this.pages[rate] ? rate : this.pages.length-1
|
||||
let top = -1
|
||||
let pageInfo = null
|
||||
@ -127,7 +129,8 @@ export default {
|
||||
//刷新当前时间和设备电量
|
||||
this.scrollDate = this.filterDate()
|
||||
this.$refs.scrollBattery.getBattery()
|
||||
this.$emit('change', pageInfo, this.pages)
|
||||
this._emitPageInfo(pageInfo, this.pages)
|
||||
this.startAutoplay()
|
||||
}
|
||||
},
|
||||
getScrollItemRect (dataId) {
|
||||
@ -138,6 +141,7 @@ export default {
|
||||
})
|
||||
},
|
||||
onScroll (e) {
|
||||
this.stopAutoplay()
|
||||
if ( this.options.pageType == 'scroll' ) {
|
||||
this.scrollTop = e.scrollTop
|
||||
if ( this.scrollTimer ) {
|
||||
|
@ -1,152 +1,124 @@
|
||||
<template>
|
||||
<view class="yingbing-read-page" ref="yingbingReadPage" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend">
|
||||
<!-- <computed ref="computedPage" :options="options"></computed> -->
|
||||
<view class="computed">
|
||||
<text class="computed-text computed-text-chinese" ref="computedTextChinese" :style="{
|
||||
'font-family': fontFamily
|
||||
}">中</text>
|
||||
<text class="computed-text computed-text-space" ref="computedTextSpace" :style="{
|
||||
'font-family': fontFamily
|
||||
}">s</text>
|
||||
<text class="computed-text computed-text-lower" ref="computedTextLower" :style="{
|
||||
'font-family': fontFamily
|
||||
}">a</text>
|
||||
<text class="computed-text computed-text-upper" ref="computedTextUpper" :style="{
|
||||
'font-family': fontFamily
|
||||
}">A</text>
|
||||
<text class="computed-text computed-text-number" ref="computedTextNumber" :style="{
|
||||
'font-family': fontFamily
|
||||
}">9</text>
|
||||
<text class="computed-text computed-text-special" ref="computedTextSpecial" :style="{
|
||||
'font-family': fontFamily
|
||||
}">&</text>
|
||||
</view>
|
||||
<!-- 翻页模式 -->
|
||||
<view class="yingbing-read-page-flip" :style="{
|
||||
'visibility': pageType != 'scroll' ? 'visible' : 'hidden'
|
||||
}">
|
||||
<template v-if="pageType != 'scroll'">
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<view
|
||||
class="yingbing-flip"
|
||||
ref="yingbingFlip"
|
||||
:style="{
|
||||
'background': options.bgColor
|
||||
}"
|
||||
:prop="flipProp"
|
||||
:change:prop="flip.propWatcher"
|
||||
@touchstart="flip.touchstart"
|
||||
@touchmove="flip.touchmove"
|
||||
@touchend="flip.touchend">
|
||||
<yingbing-flip ref="flip" class="yingbing-read-page-flip" :data="pages" :current="current" :bgColor="bgColor" :duration="300" :unableClickPage="unableClickPage" :type="pageType" @change="handleFlipChangeRender">
|
||||
<!-- #ifdef MP -->
|
||||
<template v-for="(item, index) in pages" :slot="index">
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<view
|
||||
class="yingbing-flip"
|
||||
ref="yingbingFlip"
|
||||
:style="{
|
||||
'background': options.bgColor
|
||||
}"
|
||||
@touchstart="onFilpTouchstart"
|
||||
@touchmove="onFilpTouchmove"
|
||||
@touchend="onFilpTouchend">
|
||||
<!-- #ifndef MP -->
|
||||
<template v-slot="{item, index}">
|
||||
<!-- #endif -->
|
||||
<template v-if="isShow">
|
||||
<view
|
||||
class="flip-item"
|
||||
v-for="(item, index) in dataReverse"
|
||||
:key="item.dataId + '_flip'"
|
||||
:style="{
|
||||
'visibility': item.dataId == currentDataId || item.dataId == prevDataId || item.dataId == nextDataId ? 'visible' : 'hidden'
|
||||
}">
|
||||
<view
|
||||
v-if="item.dataId == currentDataId || item.dataId == prevDataId || item.dataId == nextDataId"
|
||||
class="flip-item"
|
||||
:ref="'flipItem_' + item.dataId"
|
||||
:class="'flip-item_' + item.dataId"
|
||||
:style="{
|
||||
'transform': item.dataId < currentDataId ? `translateX(${-viewWidth}px)` : '',
|
||||
}">
|
||||
<view
|
||||
class="flip-item-wrapper"
|
||||
:ref="'flipItemWrapper_' + item.dataId"
|
||||
:class="'flip-item-wrapper_' + item.dataId"
|
||||
:style="{
|
||||
'padding-left': options.slide + 'px',
|
||||
'padding-right': options.slide + 'px',
|
||||
'padding-top': options.topGap + 'px',
|
||||
'padding-bottom': options.bottomGap + 'px',
|
||||
'background': options.bgColor,
|
||||
'transform': item.dataId < currentDataId ? options.pageType == 'real' ? `translateX(${viewWidth}px)` : 'translateX(0)' : ''
|
||||
}">
|
||||
<view class="flip-item-header" v-if="options.headerShow">
|
||||
<text class="flip-item-header-text" :style="{
|
||||
color: options.color,
|
||||
'font-family': options.fontFamily
|
||||
}">{{item.title}}</text>
|
||||
</view>
|
||||
<template v-if="item.type == 'text'">
|
||||
<view class="flip-item-text flip-item-content"
|
||||
>
|
||||
<text class="flip-text"
|
||||
v-for="(text, i) in item.text" :key="i"
|
||||
:style="{
|
||||
'margin-top': options.lineHeight + 'px',
|
||||
'height': options.fontSize + 'px',
|
||||
'font-size': options.fontSize + 'px',
|
||||
'color': options.color,
|
||||
'font-family': options.fontFamily
|
||||
}">{{text}}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else-if="item.type == 'custom'">
|
||||
<read-rich-text style="flex: 1;" :richtext="item.text" :fontFace="fontFace" :pageType="pageType" @customClick="customClick"></read-rich-text>
|
||||
</template>
|
||||
<template v-else-if="item.type == 'slot'">
|
||||
<view class="flip-slot flip-item-content">
|
||||
<slot :name="item.text"></slot>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else-if="item.type == 'nextLoading' || item.type == 'prevLoading' ">
|
||||
<view class="flip-loading flip-item-content">
|
||||
<text :style="{
|
||||
'color': options.color,
|
||||
'font-size': options.fontSize + 'px',
|
||||
'font-family': options.fontFamily
|
||||
}">正在加载内容</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else-if="item.type == 'top' || item.type == 'bottom' ">
|
||||
<view class="flip-loading flip-item-content">
|
||||
<text :style="{
|
||||
'color': options.color,
|
||||
'font-size': options.fontSize + 'px',
|
||||
'font-family': options.fontFamily
|
||||
}">{{item.type == 'top' ? '前面已经没有了' : '后面已经没有了'}}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view class="flip-loading flip-item-content">
|
||||
<text :style="{
|
||||
'color': options.color,
|
||||
'font-size': options.fontSize + 'px',
|
||||
'font-family': options.fontFamily
|
||||
}">未知类型页面</text>
|
||||
</view>
|
||||
</template>
|
||||
<view class="flip-item-footer" v-if="options.footerShow">
|
||||
<!-- <text class="flip-item-footer-text" :style="{
|
||||
color: options.color,
|
||||
'font-family': options.fontFamily
|
||||
}">{{filterDate()}}</text> -->
|
||||
<text class="flip-item-footer-text" :style="{
|
||||
color: options.color,
|
||||
'font-family': options.fontFamily
|
||||
}">{{filterPage(item)}}</text>
|
||||
<!-- <battery :color="options.color" style="opacity: 0.5"></battery> -->
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="flip-item-bg"
|
||||
:ref="'flipItemBg_' + item.dataId"
|
||||
:class="'flip-item-bg_' + item.dataId"
|
||||
:style="{
|
||||
left: viewWidth + 'px',
|
||||
width: viewWidth + 'px',
|
||||
height: (viewHeight * 1.5) + 'px',
|
||||
transform: item.dataId < currentDataId && options.pageType == 'real' ? 'translateX(' + viewWidth + 'px)' : '',
|
||||
top: (viewHeight / 2 - (viewHeight * 1.5) / 2) + 'px',
|
||||
background: options.bgColor,
|
||||
}"></view>
|
||||
<view
|
||||
class="flip-item-shadow"
|
||||
:ref="'flipItemShadow_' + item.dataId"
|
||||
:class="'flip-item-shadow_' + item.dataId">
|
||||
</view>
|
||||
</view>
|
||||
<view class="flip-item-wrapper" :style="{
|
||||
'padding-left': slide + 'px',
|
||||
'padding-right': slide + 'px',
|
||||
'padding-top': topGap + 'px',
|
||||
'padding-bottom': bottomGap + 'px'
|
||||
}">
|
||||
<view class="flip-item-header" v-if="headerShow">
|
||||
<text class="flip-item-header-text" :style="{
|
||||
color: color,
|
||||
'font-family': fontFamily
|
||||
}">{{item.title}}</text>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="item.type == 'text'">
|
||||
<view class="flip-item-text flip-item-content"
|
||||
>
|
||||
<text class="flip-text"
|
||||
v-for="(text, i) in item.text" :key="i"
|
||||
:style="{
|
||||
'margin-top': options.lineHeight + 'px',
|
||||
'height': options.fontSize + 'px',
|
||||
'font-size': options.fontSize + 'px',
|
||||
'color': options.color,
|
||||
'font-family': options.fontFamily,
|
||||
'line-height': options.fontSize + 'px'
|
||||
}">{{text}}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="item.type == 'custom'">
|
||||
<read-rich-text style="flex: 1;" :richtext="item.text" :fontFace="fontFace" :pageType="pageType" @customClick="customClick"></read-rich-text>
|
||||
</template>
|
||||
<template v-if="item.type == 'slot'">
|
||||
<view class="flip-slot flip-item-content">
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<slot :name="item.text" :prop="item"></slot>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<slot :name="item.text"></slot>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="item.type == 'loading'">
|
||||
<view class="flip-loading flip-item-content">
|
||||
<text class="flip-loading-text" :style="{
|
||||
'color': options.color,
|
||||
'font-family': options.fontFamily
|
||||
}">正在加载内容</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="item.type == 'fail' || item.type == 'timeout' ">
|
||||
<view class="flip-loading flip-item-content">
|
||||
<text class="flip-loading-text" @tap="reloadLoadmoreFlip(item)" :style="{
|
||||
'color': options.color,
|
||||
'font-family': options.fontFamily
|
||||
}">{{item.type == 'timeout' ? '加载超时' : '加载失败'}},点击刷新</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="item.type == 'top' || item.type == 'bottom' ">
|
||||
<view class="flip-loading flip-item-content">
|
||||
<slot :name="item.type">
|
||||
<text class="flip-loading-text" :style="{
|
||||
'color': options.color,
|
||||
'font-family': options.fontFamily
|
||||
}">{{item.type == 'top' ? firstTip : lastTip}}</text>
|
||||
</slot>
|
||||
</view>
|
||||
</template>
|
||||
<!-- <template v-else>
|
||||
<view class="flip-loading flip-item-content">
|
||||
<text class="flip-loading-text" :style="{
|
||||
'color': options.color,
|
||||
'font-family': options.fontFamily
|
||||
}">未知类型页面</text>
|
||||
</view>
|
||||
</template> -->
|
||||
<view class="flip-item-footer" v-if="footerShow">
|
||||
<text class="flip-item-footer-text" :style="{
|
||||
color: color,
|
||||
'font-family': fontFamily
|
||||
}">{{filterDate()}}</text>
|
||||
<text class="flip-item-footer-text" :style="{
|
||||
color: color,
|
||||
'font-family': fontFamily
|
||||
}">{{filterPage(item)}}</text>
|
||||
<battery :color="color" style="opacity: 0.5"></battery>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</yingbing-flip>
|
||||
</view>
|
||||
<!-- 翻页模式 -->
|
||||
|
||||
@ -171,16 +143,16 @@
|
||||
<scroll-list
|
||||
ref="list"
|
||||
@scroll="onScroll"
|
||||
:pulldown="{show: true, color: options.color, endText: '已经到最前面了'}"
|
||||
:loadmore="{show: true, color: options.color, endText: '已经到最后面了'}"
|
||||
@pulldown="onPulldown"
|
||||
@loadmore="onLoadmore"
|
||||
:pulldown="{show: true, color: options.color, defaultText: '下拉获取上一章节', endText: firstTip, failText: '获取上一章节失败'}"
|
||||
:loadmore="{show: true, color: options.color, defaultText: '上拉获取上一章节', endText: lastTip, failText: '获取下一章节失败'}"
|
||||
@pulldown="pulldownScroll"
|
||||
@loadmore="loadmoreScroll"
|
||||
@scrolltoupper="scrolltoupper">
|
||||
<view class="scroll-item-wrapper" ref="scrollItemWrapper">
|
||||
<view
|
||||
:id="'scroll-item_' + item.dataId"
|
||||
v-for="(item, index) in pages"
|
||||
:key="item.dataId + '_scroll'"
|
||||
:key="item.dataId"
|
||||
class="scroll-item"
|
||||
:ref="'scrollItem_' + item.dataId"
|
||||
:style="{
|
||||
@ -197,7 +169,8 @@
|
||||
'height': options.fontSize + 'px',
|
||||
'font-size': options.fontSize + 'px',
|
||||
'color': options.color,
|
||||
'font-family': options.fontFamily
|
||||
'font-family': options.fontFamily,
|
||||
'line-height': options.fontSize + 'px'
|
||||
}">{{text}}</text>
|
||||
</view>
|
||||
</template>
|
||||
@ -248,8 +221,13 @@
|
||||
</view> -->
|
||||
</template>
|
||||
</view>
|
||||
<view class="yingbing-loading" v-if="initLoading" :style="{background: options.bgColor}" @tap="reload">
|
||||
<list-loading :size="40":visible="initLoading" :color="options.color" :text="loadingText"></list-loading>
|
||||
<view class="yingbing-loading" v-if="loadstatus" :style="{background: options.bgColor}" @tap="_reload">
|
||||
<text class="error-text" :style="{
|
||||
color: options.color
|
||||
}">{{loadstatus == 'fail' ? '加载失败' : '加载超时'}},点击刷新</text>
|
||||
</view>
|
||||
<view class="yingbing-loading" v-if="initLoading" :style="{background: options.bgColor}">
|
||||
<list-loading :size="40" :visible="initLoading" :color="options.color" text="正在加载中"></list-loading>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@ -275,6 +253,16 @@
|
||||
ListLoading
|
||||
},
|
||||
props: {
|
||||
//自动翻页/滚动
|
||||
autoplay: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//自动翻页/滚动周期
|
||||
autoplayTime: {
|
||||
type: [String, Number],
|
||||
default: 5000
|
||||
},
|
||||
//字体颜色
|
||||
color: {
|
||||
type: String,
|
||||
@ -297,11 +285,34 @@
|
||||
return new Array
|
||||
}
|
||||
},
|
||||
firstTip: {
|
||||
type: String,
|
||||
default: '前面已经没有了'
|
||||
},
|
||||
lastTip: {
|
||||
type: String,
|
||||
default: '后面已经没有了'
|
||||
},
|
||||
//关闭第一页提示
|
||||
firstTipUnable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//关闭最后一页提示
|
||||
lastTipUnable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//背景颜色
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: '#fcd281'
|
||||
},
|
||||
//是否关闭点击左右2侧位置翻页
|
||||
unableClickPage: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//翻页方式
|
||||
pageType: {
|
||||
type: String,
|
||||
@ -352,6 +363,11 @@
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
//分隔符
|
||||
split: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
//点击事件位置设置
|
||||
clickOption: {
|
||||
type: Object,
|
||||
@ -363,7 +379,7 @@
|
||||
top: 'auto'
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@ -379,7 +395,11 @@
|
||||
touchmoveY: 0,
|
||||
touchTime: 0,
|
||||
windowWidth: 0,
|
||||
windowHeight: 0
|
||||
windowHeight: 0,
|
||||
initLoading: true,
|
||||
loadstatus: '',
|
||||
loadchapter: -1,
|
||||
loadstart: -1
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -388,6 +408,7 @@
|
||||
},
|
||||
options () {
|
||||
return {
|
||||
unableClickPage: this.unableClickPage,
|
||||
pageType: this.pageType,
|
||||
color: this.color,
|
||||
bgColor: this.bgColor,
|
||||
@ -405,10 +426,8 @@
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
if ( this.refreshTimer ) {
|
||||
clearTimeout(this.refreshTimer)
|
||||
this.refreshTimer = null
|
||||
}
|
||||
this.clearRefreshTimer()
|
||||
this.stopAutoplay()
|
||||
},
|
||||
mounted () {
|
||||
this.$nextTick(function () {
|
||||
@ -423,6 +442,7 @@
|
||||
},
|
||||
methods: {
|
||||
touchstart (e) {
|
||||
this.stopAutoplay()
|
||||
if ( !this.enableClick ) {
|
||||
return
|
||||
}
|
||||
@ -449,6 +469,7 @@
|
||||
this.touchmoveY = touch.pageY;
|
||||
},
|
||||
touchend (e) {
|
||||
this.startAutoplay()
|
||||
if ( this.touchInter ) {
|
||||
clearTimeout(this.touchInter);
|
||||
this.touchInter = null
|
||||
@ -501,11 +522,9 @@
|
||||
this.$emit('setCatalog', e);
|
||||
},
|
||||
//初始化
|
||||
init (data) {
|
||||
if ( this.refreshTimer ) {
|
||||
clearTimeout(this.refreshTimer)
|
||||
this.refreshTimer = null
|
||||
}
|
||||
async init (data) {
|
||||
this.clearRefreshTimer()
|
||||
await this.getComputedTextSize()
|
||||
if ( !this.noChapter ) {
|
||||
this.contents = data.contents;
|
||||
this.initLoading = true;
|
||||
@ -519,21 +538,57 @@
|
||||
},
|
||||
//重计算
|
||||
refresh () {
|
||||
if ( this.refreshTimer ) {
|
||||
clearTimeout(this.refreshTimer)
|
||||
this.refreshTimer = null
|
||||
this.stopAutoplay()
|
||||
this.clearRefreshTimer()
|
||||
if ( this.isRefreshing ) {
|
||||
this.refreshTimer = setTimeout(() => {
|
||||
this.refresh()
|
||||
}, 100)
|
||||
return
|
||||
}
|
||||
this.isRefreshing = true
|
||||
this.resetPage({
|
||||
start: this.pageInfo.start,
|
||||
currentChapter: this.pageInfo.chapter
|
||||
})
|
||||
},
|
||||
_emitPageInfo (pageInfo, pages) {
|
||||
this.isRefreshing = false
|
||||
this.$emit('change', pageInfo, pages)
|
||||
},
|
||||
_reload () {
|
||||
this.initLoading = true
|
||||
if ( this.loadchapter > -1 ) {
|
||||
this.$emit('loadmore', parseInt(this.loadchapter), (status, content) => {
|
||||
this.initLoading = false
|
||||
if (status == 'success') {
|
||||
this._resetReload()
|
||||
const index = this.contents.findIndex(item => item.chapter == content.chapter)
|
||||
if (index > -1) {
|
||||
this.contents[index] = content
|
||||
} else {
|
||||
this.contents.push(content)
|
||||
}
|
||||
this.resetPage({
|
||||
start: this.loadstart || 0,
|
||||
currentChapter: this.loadchapter
|
||||
})
|
||||
} else {
|
||||
this.loadstatus = status
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
_resetReload () {
|
||||
this.loadstatus = '';
|
||||
this.loadchapter = -1;
|
||||
this.loadstart = -1;
|
||||
},
|
||||
//跳转
|
||||
change (data) {
|
||||
if ( this.refreshTimer ) {
|
||||
clearTimeout(this.refreshTimer)
|
||||
this.refreshTimer = null
|
||||
}
|
||||
this.stopAutoplay()
|
||||
this.clearRefreshTimer()
|
||||
this._resetReload()
|
||||
if ( data.contents && data.contents.length > 0 ) {
|
||||
data.contents.forEach(item => {
|
||||
let index = this.contents.findIndex(content => content.chapter == item.chapter)
|
||||
@ -552,10 +607,71 @@
|
||||
currentChapter: parseInt(data.currentChapter || 1)
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '未找到该章节内容',
|
||||
icon: 'none'
|
||||
})
|
||||
if ( this.noChapter ) {
|
||||
uni.showToast({
|
||||
title: '未找到该章节',
|
||||
icon: 'none'
|
||||
})
|
||||
} else {
|
||||
this.initLoading = true;
|
||||
this.$emit('loadmore', parseInt(data.currentChapter), (status, content) => {
|
||||
this.initLoading = false
|
||||
if (status == 'success') {
|
||||
const index = this.contents.findIndex(item => item.chapter == content.chapter)
|
||||
if (index > -1) {
|
||||
this.contents[index] = content
|
||||
} else {
|
||||
this.contents.push(content)
|
||||
}
|
||||
this.resetPage({
|
||||
start: parseInt(data.start || 0),
|
||||
currentChapter: parseInt(data.currentChapter || 1)
|
||||
})
|
||||
} else {
|
||||
this.loadstatus = status;
|
||||
this.loadstart = parseInt(data.start || 0)
|
||||
this.loadchapter = parseInt(data.currentChapter || 1);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
//翻往上一页
|
||||
pagePrev () {
|
||||
this.stopAutoplay()
|
||||
if ( this.options.pageType != 'scroll' ) {
|
||||
this.pagePrevFlip()
|
||||
} else {
|
||||
this.scrollPrev()
|
||||
}
|
||||
},
|
||||
//翻往下一页
|
||||
pageNext () {
|
||||
this.stopAutoplay()
|
||||
if ( this.options.pageType != 'scroll' ) {
|
||||
this.pageNextFlip()
|
||||
} else {
|
||||
this.scrollNext()
|
||||
}
|
||||
},
|
||||
startAutoplay () {
|
||||
if ( this.autoplay && this.pages.length > 0 && this.pages.findIndex(page => page.dataId == this.currentDataId) < this.pages.length - 1 ) {
|
||||
this.stopAutoplay()
|
||||
this.autoplayTimer = setTimeout(() => {
|
||||
this.pageNext()
|
||||
}, this.autoplayTime)
|
||||
}
|
||||
},
|
||||
stopAutoplay () {
|
||||
if ( this.autoplayTimer ) {
|
||||
clearTimeout(this.autoplayTimer)
|
||||
this.autoplayTimer = null
|
||||
}
|
||||
},
|
||||
clearRefreshTimer () {
|
||||
if ( this.refreshTimer ) {
|
||||
clearTimeout(this.refreshTimer)
|
||||
this.refreshTimer = null
|
||||
}
|
||||
},
|
||||
initFont () {
|
||||
@ -576,84 +692,58 @@
|
||||
})
|
||||
// #endif
|
||||
})
|
||||
},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
pageType (newVal, oldVal) {
|
||||
this.$nextTick(function () {
|
||||
if ( this.refreshTimer ) {
|
||||
clearTimeout(this.refreshTimer)
|
||||
this.refreshTimer = null
|
||||
}
|
||||
this.refreshTimer = setTimeout(() => {
|
||||
if ( newVal != 'scroll' ) {
|
||||
this.getViewRect().then(res => {
|
||||
this.refresh()
|
||||
})
|
||||
} else {
|
||||
this.refresh()
|
||||
}
|
||||
}, 100)
|
||||
this.refresh()
|
||||
})
|
||||
},
|
||||
fontSize () {
|
||||
this.$nextTick(function () {
|
||||
if ( this.refreshTimer ) {
|
||||
clearTimeout(this.refreshTimer)
|
||||
this.refreshTimer = null
|
||||
}
|
||||
this.refreshTimer = setTimeout(() => {
|
||||
this.refresh()
|
||||
}, 100)
|
||||
this.refresh()
|
||||
})
|
||||
},
|
||||
lineHeight () {
|
||||
this.$nextTick(function () {
|
||||
if ( this.refreshTimer ) {
|
||||
clearTimeout(this.refreshTimer)
|
||||
this.refreshTimer = null
|
||||
}
|
||||
this.refreshTimer = setTimeout(() => {
|
||||
this.refresh()
|
||||
}, 100)
|
||||
this.refresh()
|
||||
})
|
||||
},
|
||||
slide () {
|
||||
this.$nextTick(function () {
|
||||
if ( this.refreshTimer ) {
|
||||
clearTimeout(this.refreshTimer)
|
||||
this.refreshTimer = null
|
||||
}
|
||||
this.refreshTimer = setTimeout(() => {
|
||||
this.refresh()
|
||||
}, 100)
|
||||
this.refresh()
|
||||
})
|
||||
},
|
||||
topGap () {
|
||||
this.$nextTick(function () {
|
||||
if ( this.refreshTimer ) {
|
||||
clearTimeout(this.refreshTimer)
|
||||
this.refreshTimer = null
|
||||
}
|
||||
this.refreshTimer = setTimeout(() => {
|
||||
this.refresh()
|
||||
}, 100)
|
||||
this.refresh()
|
||||
})
|
||||
},
|
||||
bottomGap () {
|
||||
this.$nextTick(function () {
|
||||
if ( this.refreshTimer ) {
|
||||
clearTimeout(this.refreshTimer)
|
||||
this.refreshTimer = null
|
||||
}
|
||||
this.refreshTimer = setTimeout(() => {
|
||||
this.refresh()
|
||||
}, 100)
|
||||
this.refresh()
|
||||
})
|
||||
},
|
||||
firstTipUnable () {
|
||||
this.$nextTick(function () {
|
||||
this.refresh()
|
||||
})
|
||||
},
|
||||
lastTipUnable () {
|
||||
this.$nextTick(function () {
|
||||
this.refresh()
|
||||
})
|
||||
},
|
||||
fontFamily () {
|
||||
this.$nextTick(async function () {
|
||||
await this.getComputedTextSize()
|
||||
this.refresh()
|
||||
})
|
||||
},
|
||||
fontFace () {
|
||||
this.initFont()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -680,11 +770,9 @@
|
||||
}
|
||||
</script>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-VUE || H5 || MP-QQ || MP-WEIXIN -->
|
||||
<script lang="wxs" module="flip" src="../modules/flip/flip.wxs"></script>
|
||||
<!-- #endif -->
|
||||
|
||||
<style scoped>
|
||||
@import url(../modules/computed/computed.css);
|
||||
@import url(../modules/flip/flip.css);
|
||||
@import url(../modules/scroll/scroll.css);
|
||||
.yingbing-read-page {
|
||||
@ -712,6 +800,9 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.yingbing-loading .error-text {
|
||||
font-size: 20px;
|
||||
}
|
||||
.yingbing-slot {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"id": "yingbing-ReadPage",
|
||||
"displayName": "小说阅读分页插件",
|
||||
"version": "1.4.3",
|
||||
"description": "给小说分页的插件,包含翻页",
|
||||
"displayName": "好用阅读分页插件",
|
||||
"version": "1.5.9",
|
||||
"description": "给小说分页的插件",
|
||||
"keywords": [
|
||||
"小说",
|
||||
"阅读",
|
||||
|
File diff suppressed because one or more lines are too long
10
uni_modules/yingbing-flip/changelog.md
Normal file
10
uni_modules/yingbing-flip/changelog.md
Normal file
@ -0,0 +1,10 @@
|
||||
## 1.0.4(2023-09-02)
|
||||
* 解决插槽中有scroll-view等滚动组件时滑动报错的问题
|
||||
## 1.0.3(2023-08-23)
|
||||
* 解决APP-NVUE端resetLoading不生效的问题
|
||||
## 1.0.2(2023-07-25)
|
||||
* 解决竖直翻页时,点击上下2侧翻页不准确得问题
|
||||
## 1.0.1(2023-07-24)
|
||||
* 解决APP-NVUE无法点击左右2侧翻页得问题
|
||||
## 1.0.0(2023-07-22)
|
||||
* 第一次更新
|
367
uni_modules/yingbing-flip/components/modules/flip.wxs
Normal file
367
uni_modules/yingbing-flip/components/modules/flip.wxs
Normal file
@ -0,0 +1,367 @@
|
||||
function touchstart (event, ins) {
|
||||
var state = ins.getState()
|
||||
if ( state.isTouch || state.disableTouch ) {
|
||||
return
|
||||
}
|
||||
state.isTouch = true
|
||||
state.touchTime = 0
|
||||
state.interval = true
|
||||
setInterval(ins)
|
||||
var touch = event.touches[0]
|
||||
state.startX = touch.pageX
|
||||
state.startY = touch.pageY
|
||||
}
|
||||
function touchmove (event, ins) {
|
||||
var state = ins.getState()
|
||||
if ( state.isTouch && !state.disableTouch ) {
|
||||
var touch = event.touches[0]
|
||||
state.offset = state.vertical ? touch.pageY - state.startY : touch.pageX - state.startX;
|
||||
if (state.direction) {
|
||||
var rect = ins.getBoundingClientRect()
|
||||
var size = state.vertical ? rect.height : rect.width
|
||||
state.offset = state.direction == 'next' ? state.offset + state.sliderFault : state.offset - state.sliderFault
|
||||
if ( (state.offset > 0 && state.direction == 'next') || (state.offset < 0 && state.direction == 'prev') ) {
|
||||
state.offset = 0
|
||||
}
|
||||
if ( Math.abs(state.offset) <= size ) {
|
||||
animation(state.offset, 0, ins)
|
||||
}
|
||||
} else {
|
||||
if ( Math.abs(state.offset) < state.sliderFault ) {
|
||||
return
|
||||
}
|
||||
if ( state.offset < 0 ) {
|
||||
if ( state.nextIndex < state.count && state.nextIndex != 0 ) {
|
||||
if ( state.type != 'none' ) {state.direction = 'next'}
|
||||
} else if ( state.pullupable && state.loadingState != 'loading' && state.loadingState != 'success' && state.loadingState != 'fail' ) {
|
||||
state.loadingType = 'pullup'
|
||||
state.offset = state.offset + state.sliderFault
|
||||
pulling(state.offset, ins)
|
||||
}
|
||||
} else {
|
||||
if ( state.prevIndex >= 0 && state.prevIndex != state.count - 1 ) {
|
||||
if ( state.type != 'none' ) {state.direction = 'prev'}
|
||||
} else if ( state.pulldownable && state.loadingState != 'loading' && state.loadingState != 'success' && state.loadingState != 'fail' ) {
|
||||
state.loadingType = 'pulldown'
|
||||
state.offset = state.offset - state.sliderFault
|
||||
pulling(state.offset, ins)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function touchend (event, ins) {
|
||||
touchaction(event, ins)
|
||||
}
|
||||
function touchcancel (event, ins) {
|
||||
touchaction(event, ins)
|
||||
}
|
||||
function touchaction (event, ins,isFlipTo) {
|
||||
var state = ins.getState()
|
||||
clearInterval(ins)
|
||||
if ( state.isTouch && !state.disableTouch ) {
|
||||
var rect = ins.getBoundingClientRect()
|
||||
var size = state.vertical ? rect.height : rect.width
|
||||
var start = state.vertical ? state.startY : state.startX
|
||||
if ( !state.direction && state.touchTime <= 200 && (!state.unableClickPage || state.type == 'none') && !isFlipTo ) {
|
||||
//获取点击位置,判断向哪里翻页
|
||||
if (start > (size / 4) * 3 && state.nextIndex < state.count && state.nextIndex != 0 ) {
|
||||
state.direction = 'next'
|
||||
}
|
||||
if (start < (size / 4) && state.prevIndex >= 0 && state.prevIndex != state.count - 1 ) {
|
||||
state.direction = 'prev'
|
||||
}
|
||||
}
|
||||
if (state.direction) {
|
||||
state.disableTouch = true
|
||||
if (state.touchTime <= 200) {
|
||||
var duration = state.type == 'none' ? 0 : state.duration;
|
||||
var value = state.direction == 'next' ? 1 : -1;
|
||||
animation(-value * size, duration, ins);
|
||||
ins.setTimeout(function () {
|
||||
resetShadow(ins, true)
|
||||
ins.callMethod('handleFlipChange', value);
|
||||
}, duration + 50)
|
||||
} else {
|
||||
var duration = state.type == 'none' ? 0 : state.duration;
|
||||
if (Math.abs(state.offset) >= size / 4) {
|
||||
var value = state.direction == 'next' ? 1 : -1;
|
||||
animation(-value * size, duration, ins);
|
||||
ins.setTimeout(function () {
|
||||
resetShadow(ins, true)
|
||||
ins.callMethod('handleFlipChange', value);
|
||||
}, duration + 50)
|
||||
} else {
|
||||
animation(0, duration, ins);
|
||||
ins.setTimeout(function () {
|
||||
resetShadow(ins)
|
||||
resetFlip(ins);
|
||||
}, duration + 50)
|
||||
}
|
||||
}
|
||||
} else if ( state.loadingState == 'default' ) {
|
||||
resetPulling(ins)
|
||||
} else if ( state.loadingState == 'ready' ) {
|
||||
pullingRefresh(ins)
|
||||
} else {
|
||||
resetShadow(ins, false)
|
||||
resetFlip(ins)
|
||||
}
|
||||
}
|
||||
}
|
||||
function propWatcher (newVal, oldVal, ins) {
|
||||
ins.setTimeout(function () {
|
||||
var state = ins.getState()
|
||||
state.vertical = newVal.vertical
|
||||
state.pulldownable = newVal.pulldownable
|
||||
state.pullupable = newVal.pullupable
|
||||
state.pulldownHeight = newVal.pulldownHeight
|
||||
state.loadingState = newVal.loadingState
|
||||
state.pullupHeight = newVal.pullupHeight
|
||||
state.duration = newVal.duration
|
||||
state.nextIndex = newVal.nextIndex
|
||||
state.prevIndex = newVal.prevIndex
|
||||
state.currentIndex = newVal.currentIndex
|
||||
state.sliderFault = newVal.sliderFault
|
||||
state.count = newVal.count
|
||||
state.type = newVal.type
|
||||
state.unableClickPage = newVal.unableClickPage
|
||||
state.translate = newVal.translate
|
||||
if ( oldVal && newVal.currentIndex != oldVal.currentIndex ) {
|
||||
resetFlip(ins);
|
||||
}
|
||||
if ( oldVal && newVal.loadingState != oldVal.loadingState && state.loadingState ) {
|
||||
resetPulling(ins)
|
||||
ins.callMethod('resetLoading')
|
||||
}
|
||||
if (oldVal && newVal.flipTo != oldVal.flipTo && newVal.flipTo != 0 ) {
|
||||
if ( !state.disableTouch ) {
|
||||
if ( newVal.flipTo < 0 && state.prevIndex >= 0 && (state.prevIndex != state.count - 1) ) {
|
||||
state.isTouch = true
|
||||
state.touchTime = 0
|
||||
state.direction = 'prev'
|
||||
touchaction(null, ins, true)
|
||||
}
|
||||
if ( newVal.flipTo > 0 && state.nextIndex < state.count && state.nextIndex != 0 ) {
|
||||
state.isTouch = true
|
||||
state.touchTime = 0
|
||||
state.direction = 'next'
|
||||
touchaction(null, ins, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 100)
|
||||
}
|
||||
function setInterval (ins) {
|
||||
var state = ins.getState()
|
||||
state.touchTimer = ins.setTimeout(function () {
|
||||
state.touchTime += 10
|
||||
if ( state.interval ) {
|
||||
setInterval(ins)
|
||||
}
|
||||
}, 10)
|
||||
}
|
||||
function clearInterval (ins) {
|
||||
var state = ins.getState()
|
||||
state.interval = false
|
||||
if ( state.touchTimer ) {
|
||||
ins.clearTimeout(state.touchTimer)
|
||||
state.touchTimer = null
|
||||
}
|
||||
}
|
||||
function resetShadow (ins, isChange) {
|
||||
var state = ins.getState()
|
||||
var direction = state.direction
|
||||
if ( !direction ) {
|
||||
return
|
||||
}
|
||||
var index = direction == 'next' ? state.currentIndex : state.prevIndex
|
||||
var translate = state.translate
|
||||
var rect = ins.getBoundingClientRect()
|
||||
var size = state.vertical ? rect.height : rect.width;
|
||||
var draw = function () {
|
||||
ins.selectComponent('.yingbing-flip-item_' + index).setStyle({
|
||||
'box-shadow': '',
|
||||
transform: translate + '(' + (isChange ? (direction == 'next'? -size : 0) : (direction == 'next'? 0 : -size)) + 'px)',
|
||||
transition: ''
|
||||
})
|
||||
if ( state.type == 'real' ) {
|
||||
ins.selectComponent('.yingbing-flip-item-bg_' + index).setStyle({
|
||||
'box-shadow': '',
|
||||
transform: translate + '(' + (isChange ? (direction == 'next' ? 0 : size) : (direction == 'next' ? size : 0)) + 'px)',
|
||||
transition: ''
|
||||
})
|
||||
}
|
||||
ins.selectComponent('.yingbing-flip-item-shadow_' + index).setStyle({
|
||||
'box-shadow': '',
|
||||
transition: ''
|
||||
})
|
||||
}
|
||||
ins.requestAnimationFrame(draw)
|
||||
}
|
||||
function resetFlip (ins) {
|
||||
var state = ins.getState()
|
||||
state.direction = null
|
||||
state.isTouch = false
|
||||
state.disableTouch = false
|
||||
state.offset = 0
|
||||
state.touchTime = 0
|
||||
state.startX = 0
|
||||
state.startY = 0
|
||||
}
|
||||
function animation (offset, duration, ins, noshadow) {
|
||||
var state = ins.getState()
|
||||
var rect = ins.getBoundingClientRect()
|
||||
var size = state.vertical ? rect.height : rect.width
|
||||
var translate = state.translate
|
||||
var late = offset
|
||||
var draw = function () {
|
||||
if ( state.direction == 'prev' ) {
|
||||
if ( state.prevIndex >= 0 ) {
|
||||
ins.selectComponent('.yingbing-flip-item_' + state.prevIndex).setStyle({
|
||||
transform: translate + '(' + (late - size) + 'px)',
|
||||
'box-shadow': noshadow ? '' : state.type == 'real' ? '0 0 30px 20px rgba(0,0,0,0.4)' : state.type == 'cover' ? '0 0 10px 5px rgba(0,0,0,0.3)' : '',
|
||||
transition: duration > 0 ? 'transform ' + duration + 'ms' : ''
|
||||
})
|
||||
if ( state.type == 'real' ) {
|
||||
ins.selectComponent('.yingbing-flip-item-content_' + state.prevIndex).setStyle({
|
||||
transform: translate + '(' + (size-late) + 'px)',
|
||||
transition: duration > 0 ? 'transform ' + duration + 'ms' : ''
|
||||
})
|
||||
ins.selectComponent('.yingbing-flip-item-bg_' + state.prevIndex).setStyle({
|
||||
transform: translate + '(' + (late) + 'px)',
|
||||
'box-shadow': noshadow ? '' : '-5px 0 20px rgba(0,0,0,0.1)',
|
||||
transition: duration > 0 ? 'transform ' + duration + 'ms, ' + 'boxShadow ' + duration + 'ms' : ''
|
||||
})
|
||||
ins.selectComponent('.yingbing-flip-item-shadow_' + state.prevIndex).setStyle({
|
||||
'box-shadow': noshadow ? '' : '0 0 60px 30px rgba(0,0,0,0.4)',
|
||||
transition: duration > 0 ? 'boxShadow ' + duration + 'ms' : ''
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( state.nextIndex < state.count ) {
|
||||
ins.selectComponent('.yingbing-flip-item_' + state.nextIndex).setStyle({
|
||||
transform: translate + '(0)',
|
||||
transition: ''
|
||||
})
|
||||
}
|
||||
ins.selectComponent('.yingbing-flip-item_' + state.currentIndex).setStyle({
|
||||
transform: translate + '(' + late + 'px)',
|
||||
'box-shadow': noshadow ? '' : state.type == 'real' ? '0 0 30px 20px rgba(0,0,0,0.4)' : state.type == 'cover' ? '0 0 10px 5px rgba(0,0,0,0.3)' : '',
|
||||
transition: duration > 0 ? 'transform ' + duration + 'ms' : ''
|
||||
})
|
||||
if ( state.type == 'real' ) {
|
||||
ins.selectComponent('.yingbing-flip-item-content_' + state.currentIndex).setStyle({
|
||||
transform: translate + '(' + (-late) + 'px)',
|
||||
transition: duration > 0 ? 'transform ' + duration + 'ms' : ''
|
||||
})
|
||||
ins.selectComponent('.yingbing-flip-item-bg_' + state.currentIndex).setStyle({
|
||||
transform: translate + '(' + (late + size) + 'px)',
|
||||
'box-shadow': noshadow ? '' : '-5px 0 20px rgba(0,0,0,0.1)',
|
||||
transition: duration > 0 ? 'transform ' + duration + 'ms, ' + 'boxShadow ' + duration + 'ms' : ''
|
||||
})
|
||||
ins.selectComponent('.yingbing-flip-item-shadow_' + state.currentIndex).setStyle({
|
||||
'box-shadow': noshadow ? '' : '0 0 60px 30px rgba(0,0,0,0.4)',
|
||||
transition: duration > 0 ? 'boxShadow ' + duration + 'ms' : ''
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
ins.requestAnimationFrame(draw)
|
||||
}
|
||||
function pulling (offset, ins) {
|
||||
var state = ins.getState()
|
||||
var loadingType = state.loadingType
|
||||
var translate = state.translate
|
||||
var size = loadingType == 'pullup' ? state.pullupHeight : state.pulldownHeight
|
||||
var late = offset
|
||||
if ( Math.abs(state.offset) < size ) {
|
||||
state.loadingState = 'default'
|
||||
} else {
|
||||
state.loadingState = 'ready'
|
||||
}
|
||||
var draw = function () {
|
||||
var pullingItems = ins.selectAllComponents('.yingbing-flip-' + loadingType + '-item')
|
||||
for ( var i = 0; i < pullingItems.length; i++ ) {
|
||||
if ( pullingItems[i].hasClass('yingbing-flip-' + loadingType + '-' + state.loadingState) ) {
|
||||
pullingItems[i].setStyle({
|
||||
visibility: 'visible'
|
||||
})
|
||||
} else {
|
||||
pullingItems[i].setStyle({
|
||||
visibility: 'hidden'
|
||||
})
|
||||
}
|
||||
}
|
||||
if ( Math.abs(late) <= size ) {
|
||||
ins.selectComponent('.yingbing-flip-' + loadingType).setStyle({
|
||||
transform: translate + '(' + (loadingType == 'pullup' ? late + size : late - size) + 'px)',
|
||||
transition: ''
|
||||
})
|
||||
}
|
||||
}
|
||||
ins.requestAnimationFrame(draw)
|
||||
}
|
||||
function resetPulling (ins) {
|
||||
var state = ins.getState()
|
||||
var loadingType = state.loadingType
|
||||
var translate = state.translate
|
||||
var size = loadingType == 'pullup' ? state.pullupHeight : state.pulldownHeight
|
||||
var draw = function () {
|
||||
var pullingItems = ins.selectAllComponents('.yingbing-flip-' + loadingType + '-item')
|
||||
for ( var i = 0; i < pullingItems.length; i++ ) {
|
||||
if ( pullingItems[i].hasClass('yingbing-flip-' + loadingType + '-' + state.loadingState) ) {
|
||||
pullingItems[i].setStyle({
|
||||
visibility: 'visible'
|
||||
})
|
||||
} else {
|
||||
pullingItems[i].setStyle({
|
||||
visibility: 'hidden'
|
||||
})
|
||||
}
|
||||
}
|
||||
ins.selectComponent('.yingbing-flip-' + loadingType).setStyle({
|
||||
transform: translate + '(' + (loadingType == 'pullup' ? size : -size) + 'px)',
|
||||
transition: 'transform .3s'
|
||||
})
|
||||
}
|
||||
ins.requestAnimationFrame(draw)
|
||||
if ( state.loadingState ) {
|
||||
ins.setTimeout( function () {
|
||||
state.loadingState = ''
|
||||
resetPulling(ins)
|
||||
}, 300)
|
||||
} else {
|
||||
state.loadingType = ''
|
||||
resetFlip(ins)
|
||||
}
|
||||
}
|
||||
function pullingRefresh (ins) {
|
||||
var state = ins.getState()
|
||||
state.loadingState = 'loading'
|
||||
var loadingType = state.loadingType
|
||||
var draw = function () {
|
||||
var pullingItems = ins.selectAllComponents('.yingbing-flip-' + loadingType + '-item')
|
||||
for ( var i = 0; i < pullingItems.length; i++ ) {
|
||||
if ( pullingItems[i].hasClass('yingbing-flip-' + loadingType + '-loading') ) {
|
||||
pullingItems[i].setStyle({
|
||||
visibility: 'visible'
|
||||
})
|
||||
} else {
|
||||
pullingItems[i].setStyle({
|
||||
visibility: 'hidden'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
ins.requestAnimationFrame(draw)
|
||||
ins.callMethod('pullingRefresh', state.loadingType)
|
||||
}
|
||||
module.exports = {
|
||||
touchstart: touchstart,
|
||||
touchmove: touchmove,
|
||||
touchend: touchend,
|
||||
touchcancel: touchcancel,
|
||||
propWatcher: propWatcher
|
||||
}
|
546
uni_modules/yingbing-flip/components/modules/flip_bindingx.js
Normal file
546
uni_modules/yingbing-flip/components/modules/flip_bindingx.js
Normal file
@ -0,0 +1,546 @@
|
||||
const Binding = uni.requireNativePlugin('bindingx')
|
||||
const animation = uni.requireNativePlugin('animation')
|
||||
const dom = uni.requireNativePlugin('dom')
|
||||
import Util from '../../js_sdk/util.js'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
disableTouch: false,
|
||||
isTouch: false,
|
||||
touchTime: 0,
|
||||
interval: false,
|
||||
loadingType: '',
|
||||
direction: ''
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
if ( this.flipBinding ) {
|
||||
Binding.unbind({
|
||||
token: this.flipBinding.token,
|
||||
eventType: 'pan'
|
||||
})
|
||||
this.sliderBinding = null
|
||||
}
|
||||
this.resetFlipAnimationBinding()
|
||||
},
|
||||
methods: {
|
||||
fliptouchstart (event) {
|
||||
if ( this.isTouch || this.disableTouch ) {
|
||||
return
|
||||
}
|
||||
this.isTouch = true
|
||||
this.touchTime = 0
|
||||
this.interval = true
|
||||
this.setInterval()
|
||||
let touch = event.touches[0]
|
||||
this.startX = touch.pageX
|
||||
this.startY = touch.pageY
|
||||
},
|
||||
fliptouchmove (event) {
|
||||
if ( this.isTouch && !this.disableTouch ) {
|
||||
let touch = event.touches[0]
|
||||
let offset = this.vertical ? touch.pageY - this.startY : touch.pageX - this.startX
|
||||
if ( !this.direction ) {
|
||||
if ( Math.abs(offset) < this.sliderFault ) return
|
||||
if ( offset < 0 ) {
|
||||
if ( this.nextIndex < this.count && this.nextIndex != 0 ) {
|
||||
if ( this.type != 'none' ) {this.direction = 'next'}
|
||||
} else if ( this.pullupable && this.loadingState != 'loading' && this.loadingState != 'success' && this.loadingState != 'fail' ) {
|
||||
this.loadingType = 'pullup'
|
||||
this.disableTouch = true
|
||||
this.clearInterval()
|
||||
this.pulling()
|
||||
}
|
||||
} else {
|
||||
if ( this.prevIndex > -1 && this.prevIndex != this.count - 1 ) {
|
||||
if ( this.type != 'none' ) {this.direction = 'prev'}
|
||||
} else if ( this.pulldownable && this.loadingState != 'loading' && this.loadingState != 'success' && this.loadingState != 'fail' ) {
|
||||
this.loadingType = 'pulldown'
|
||||
this.disableTouch = true
|
||||
this.clearInterval()
|
||||
this.pulling()
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( this.direction ) {
|
||||
this.disableTouch = true
|
||||
this.flipTouchAction()
|
||||
} else {
|
||||
this.resetPageBinding()
|
||||
}
|
||||
}
|
||||
},
|
||||
async fliptouchend (e) {
|
||||
if ( this.isTouch && !this.disableTouch ) {
|
||||
let rect = await this.getRect(this.$refs.yingbingFlip)
|
||||
let size = this.vertical ? rect.height : rect.width
|
||||
this.clearInterval()
|
||||
let start = this.vertical ? this.startY : this.startX
|
||||
if ( this.touchTime <= 200 && (!this.unableClickPage || this.type == 'none') ) {
|
||||
if (start > (size / 4) * 3 && this.nextIndex < this.count && this.nextIndex != 0 ) {
|
||||
this.flipToNextBindingX()
|
||||
} else if (start < (size / 4) && this.prevIndex >= 0 && this.prevIndex != this.count - 1 ) {
|
||||
this.flipToPrevBindingX()
|
||||
} else {
|
||||
this.resetPageBinding()
|
||||
}
|
||||
} else {
|
||||
this.resetPageBinding()
|
||||
}
|
||||
}
|
||||
},
|
||||
async flipTouchAction () {
|
||||
let props = []
|
||||
let rect = await this.getRect(this.$refs.yingbingFlip)
|
||||
let size = this.vertical ? rect.height : rect.width
|
||||
let translate = this.translate
|
||||
let shadowProperty = this.vertical ? 'height' : 'width'
|
||||
let key = this.vertical ? 'y' : 'x'
|
||||
if ( this.direction == 'prev' ) {
|
||||
if ( this.prevIndex > -1 ) {
|
||||
props.push({
|
||||
element: this.getEl('yingbingFlipItem_' + this.prevIndex),
|
||||
property: 'transform.' + translate,
|
||||
expression: `${key} < 0 ? ${-size} : (${key} > ${size} ? 0 : ${key}-${size})`
|
||||
})
|
||||
if ( this.type == 'real' ) {
|
||||
props.push({
|
||||
element: this.getEl('yingbingFlipItemContent_' + this.prevIndex),
|
||||
property: 'transform.' + translate,
|
||||
expression: `${key} < 0 ? ${size} : (${key} > ${size} ? 0 : ${size}-${key})`
|
||||
})
|
||||
props.push({
|
||||
element: this.getEl('yingbingFlipItemBg_' + this.prevIndex),
|
||||
property: 'transform.' + translate,
|
||||
expression: `${key} < 0 ? 0 : (${key} > ${size} ? ${size} : ${key} + 0)`
|
||||
})
|
||||
props.push({
|
||||
element: this.getEl('yingbingFlipItemShadow_' + this.prevIndex),
|
||||
property: shadowProperty,
|
||||
expression: `${size} / 2 - abs(${key}) / 2'`
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( this.nextIndex < this.count ) {
|
||||
props.push({
|
||||
element: this.getEl('yingbingFlipItem_' + this.nextIndex),
|
||||
property: 'transform.' + translate,
|
||||
expression: '0+0'
|
||||
})
|
||||
}
|
||||
props.push({
|
||||
element: this.getEl('yingbingFlipItem_' + this.currentIndex),
|
||||
property: 'transform.' + translate,
|
||||
expression: `${key} > 0 ? 0 : (${key} < ${-size} ? ${-size} : ${key} + 0)`
|
||||
})
|
||||
if ( this.type == 'real' ) {
|
||||
props.push({
|
||||
element: this.getEl('yingbingFlipItemContent_' + this.currentIndex),
|
||||
property: 'transform.' + translate,
|
||||
expression: `${key} > 0 ? 0 : (${key} < ${-size} ? ${size} : 0 - ${key})'`
|
||||
})
|
||||
props.push({
|
||||
element: this.getEl('yingbingFlipItemBg_' + this.currentIndex),
|
||||
property: 'transform.' + translate,
|
||||
expression: `${key} > 0 ? ${size} : (${key} < ${-size} ? 0 : ${key}+${size})`
|
||||
})
|
||||
props.push({
|
||||
element: this.getEl('yingbingFlipItemShadow_' + this.currentIndex),
|
||||
property: shadowProperty,
|
||||
expression: `abs(${key})/2+0`
|
||||
})
|
||||
}
|
||||
}
|
||||
this.flipBinding = Binding.bind({
|
||||
anchor: this.getEl('yingbingFlip'),
|
||||
eventType: 'pan',
|
||||
props: props
|
||||
}, (e) => {
|
||||
if ((e.state == 'end' || e.state == 'cancel') && this.flipBinding) {
|
||||
this.clearInterval()
|
||||
Binding.unbind({
|
||||
token: this.flipBinding.token,
|
||||
eventType: 'pan'
|
||||
})
|
||||
this.flipBinding = null
|
||||
let value = this.direction == 'next' ? 1 : -1;
|
||||
if (this.touchTime <= 200) {
|
||||
this.pageAnimation(-value * size, size);
|
||||
} else {
|
||||
let index = this.direction == 'next' ? this.currentIndex : this.prevIndex
|
||||
let deltaX = Binding.getComputedStyle(this.getEl('yingbingFlipItem_' + index))[translate]
|
||||
let offset = this.direction == 'next' ? Math.abs(deltaX) : size - Math.abs(deltaX)
|
||||
if ( offset >= size / 4) {
|
||||
this.pageAnimation(-value * size, size)
|
||||
} else {
|
||||
this.pageAnimation(0, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
flipToNextBindingX () {
|
||||
if ( !this.disableTouch && this.nextIndex < this.count && (this.nextIndex != 0 || this.circular) ) {
|
||||
this.direction = 'next'
|
||||
this.flipToBindingX()
|
||||
}
|
||||
},
|
||||
flipToPrevBindingX () {
|
||||
if ( !this.disableTouch && this.prevIndex >= 0 && (this.prevIndex != this.count - 1 || this.circular) ) {
|
||||
this.direction = 'prev'
|
||||
this.flipToBindingX()
|
||||
}
|
||||
},
|
||||
async flipToBindingX () {
|
||||
this.disableTouch = true
|
||||
let value = this.direction == 'next' ? 1 : -1;
|
||||
let rect = await this.getRect(this.$refs.yingbingFlip)
|
||||
let size = this.vertical ? rect.height : rect.width
|
||||
this.pageAnimation(-value * size, size)
|
||||
},
|
||||
getRect (el) {
|
||||
return new Promise(resolve => {
|
||||
dom.getComponentRect(el, res => {
|
||||
resolve(res.size)
|
||||
})
|
||||
})
|
||||
},
|
||||
setInterval () {
|
||||
this.touchTimer = setTimeout(() => {
|
||||
this.touchTime += 10
|
||||
if ( this.interval ) {
|
||||
this.setInterval()
|
||||
}
|
||||
}, 10)
|
||||
},
|
||||
clearInterval () {
|
||||
this.interval = false
|
||||
if ( this.touchTimer ) {
|
||||
clearTimeout(this.touchTimer)
|
||||
this.touchTimer = null
|
||||
}
|
||||
},
|
||||
pageAnimation (offset, size) {
|
||||
let duration = this.type == 'none' ? 0.1 : this.duration
|
||||
let late = offset
|
||||
let translate = this.translate
|
||||
let shadowProperty = this.vertical ? 'height' : 'width'
|
||||
let props = []
|
||||
if ( this.direction == 'prev' ) {
|
||||
if ( this.prevIndex > -1 ) {
|
||||
let itemTrans = Binding.getComputedStyle(this.getEl('yingbingFlipItem_' + this.prevIndex))[translate]
|
||||
props.push({
|
||||
element: this.getEl('yingbingFlipItem_' + this.prevIndex),
|
||||
property: 'transform.' + translate,
|
||||
expression: `linear(t, ${itemTrans}, ${late - size - itemTrans}, ${duration})`
|
||||
})
|
||||
if ( this.type == 'real' ) {
|
||||
let contentTrans = Binding.getComputedStyle(this.getEl('yingbingFlipItemContent_' + this.prevIndex))[translate]
|
||||
props.push({
|
||||
element: this.getEl('yingbingFlipItemContent_' + this.prevIndex),
|
||||
property: 'transform.' + translate,
|
||||
expression: `linear(t, ${contentTrans}, ${-(late - size) - contentTrans}, ${duration})`
|
||||
})
|
||||
let bgTrans = Binding.getComputedStyle(this.getEl('yingbingFlipItemBg_' + this.prevIndex))[translate]
|
||||
props.push({
|
||||
element: this.getEl('yingbingFlipItemBg_' + this.prevIndex),
|
||||
property: 'transform.' + translate,
|
||||
expression: `linear(t, ${bgTrans}, ${late - bgTrans}, ${duration})`
|
||||
})
|
||||
let shadowSize = Binding.getComputedStyle(this.getEl('yingbingFlipItemShadow_' + this.prevIndex))[shadowProperty] || size
|
||||
props.push({
|
||||
element: this.getEl('yingbingFlipItemShadow_' + this.prevIndex),
|
||||
property: shadowProperty,
|
||||
expression: `linear(t, ${shadowSize}, ${-(late - size) - shadowSize}, ${duration})`
|
||||
})
|
||||
}
|
||||
this.flipAnimationBinding = Binding.bind({
|
||||
eventType: 'timing',
|
||||
exitExpression: 't>' + duration,
|
||||
props: props
|
||||
}, (e) => {
|
||||
if (e.state == 'exit' && this.flipAnimationBinding && e.t > duration) {
|
||||
Binding.unbind({
|
||||
token: this.flipAnimationBinding.token,
|
||||
eventType: 'timing'
|
||||
})
|
||||
this.flipAnimationBinding = null
|
||||
if ( Math.abs(offset) > 0 ) {
|
||||
this.handleFlipChange(this.direction == 'next' ? 1 : -1)
|
||||
this.$nextTick(function () {
|
||||
this.resetPageBinding()
|
||||
})
|
||||
} else {
|
||||
this.resetPageBinding();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if ( this.nextIndex < this.count ) {
|
||||
animation.transition(this.getRef('yingbingFlipItem_' + this.nextIndex), {
|
||||
styles: {
|
||||
transform: `${translate}(0)`
|
||||
},
|
||||
duration: 0,
|
||||
timingFunction: 'linear',
|
||||
needLayout: true
|
||||
})
|
||||
}
|
||||
animation.transition(this.getRef('yingbingFlipItem_' + this.currentIndex), {
|
||||
styles: {
|
||||
transform: `${translate}(${late}px)`
|
||||
},
|
||||
duration: duration,
|
||||
timingFunction: 'linear',
|
||||
needLayout: true
|
||||
}, () => {
|
||||
if ( Math.abs(offset) > 0 ) {
|
||||
this.handleFlipChange(this.direction == 'next' ? 1 : -1)
|
||||
this.$nextTick(function () {
|
||||
this.resetPageBinding()
|
||||
})
|
||||
} else {
|
||||
this.resetPageBinding();
|
||||
}
|
||||
})
|
||||
if ( this.type == 'real' ) {
|
||||
animation.transition(this.getRef('yingbingFlipItemContent_' + this.currentIndex), {
|
||||
styles: {
|
||||
transform: `${translate}(${-late}px)`
|
||||
},
|
||||
duration: duration,
|
||||
timingFunction: 'linear',
|
||||
needLayout: true
|
||||
})
|
||||
animation.transition(this.getRef('yingbingFlipItemBg_' + this.currentIndex), {
|
||||
styles: {
|
||||
transform: `${translate}(${size + late}px)`
|
||||
},
|
||||
duration: duration,
|
||||
timingFunction: 'linear',
|
||||
needLayout: true
|
||||
})
|
||||
let styles = {}
|
||||
styles[shadowProperty] = -late + 'px'
|
||||
animation.transition(this.getRef('yingbingFlipItemShadow_' + this.currentIndex), {
|
||||
styles: styles,
|
||||
duration: duration,
|
||||
timingFunction: 'linear',
|
||||
needLayout: true
|
||||
})
|
||||
}
|
||||
// if ( this.nextIndex < this.count ) {
|
||||
// props.push({
|
||||
// element: this.getEl('yingbingFlipItem_' + this.nextIndex),
|
||||
// property: 'transform.' + translate,
|
||||
// expression: '0+0'
|
||||
// })
|
||||
// }
|
||||
// let itemTrans = Binding.getComputedStyle(this.getEl('yingbingFlipItem_' + this.currentIndex))[translate]
|
||||
// props.push({
|
||||
// element: this.getEl('yingbingFlipItem_' + this.currentIndex),
|
||||
// property: 'transform.' + translate,
|
||||
// expression: `linear(t, ${itemTrans}, ${late - itemTrans}, ${duration})`
|
||||
// })
|
||||
// if ( this.type == 'real' ) {
|
||||
// let contentTrans = Binding.getComputedStyle(this.getEl('yingbingFlipItemContent_' + this.currentIndex))[translate]
|
||||
// props.push({
|
||||
// element: this.getEl('yingbingFlipItemContent_' + this.currentIndex),
|
||||
// property: 'transform.' + translate,
|
||||
// expression: `linear(t, ${contentTrans}, ${-late - contentTrans}, ${duration})`
|
||||
// })
|
||||
// let bgTrans = Binding.getComputedStyle(this.getEl('yingbingFlipItemBg_' + this.currentIndex))[translate]
|
||||
// props.push({
|
||||
// element: this.getEl('yingbingFlipItemBg_' + this.currentIndex),
|
||||
// property: 'transform.' + translate,
|
||||
// expression: `linear(t, ${bgTrans}, ${size + late - bgTrans}, ${duration})`
|
||||
// })
|
||||
// let shadowSize = Binding.getComputedStyle(this.getEl('yingbingFlipItemShadow_' + this.currentIndex))[shadowProperty]
|
||||
// props.push({
|
||||
// element: this.getEl('yingbingFlipItemShadow_' + this.currentIndex),
|
||||
// property: shadowProperty,
|
||||
// expression: `linear(t, ${shadowSize}, ${-late - shadowSize}, ${duration})`
|
||||
// })
|
||||
// }
|
||||
}
|
||||
},
|
||||
pulling () {
|
||||
let loadingType = this.loadingType
|
||||
let size = loadingType == 'pullup' ? this.pullupHeight : this.pulldownHeight
|
||||
let key = this.vertical ? 'y' : 'x'
|
||||
let translate = this.translate
|
||||
let props = [
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType),
|
||||
property: 'transform.' + translate,
|
||||
expression: loadingType == 'pullup' ? `abs(${key}) > ${size} ? 0 : ${key} + ${size}` : `abs(${key}) > ${size} ? 0 : ${key} - ${size}`
|
||||
},
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_default'),
|
||||
property: 'opacity',
|
||||
expression: `abs(${key}) < ${size} ? 1 : 0`
|
||||
},
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_ready'),
|
||||
property: 'opacity',
|
||||
expression: `abs(${key}) < ${size} ? 0 : 1`
|
||||
},
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_loading'),
|
||||
property: 'opacity',
|
||||
expression: '0+0'
|
||||
},
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_success'),
|
||||
property: 'opacity',
|
||||
expression: '0+0'
|
||||
},
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_fail'),
|
||||
property: 'opacity',
|
||||
expression: '0+0'
|
||||
}
|
||||
]
|
||||
this.flipBinding = Binding.bind({
|
||||
anchor: this.getEl('yingbingFlip'),
|
||||
eventType: 'pan',
|
||||
props: props
|
||||
}, (e) => {
|
||||
if ((e.state == 'end' || e.state == 'cancel') && this.flipBinding) {
|
||||
Binding.unbind({
|
||||
token: this.flipBinding.token,
|
||||
eventType: 'pan'
|
||||
})
|
||||
this.flipBinding = null
|
||||
let deltaX = Binding.getComputedStyle(this.getEl('yingbing_flip_' + loadingType))[translate]
|
||||
if ( deltaX == 0 ) {
|
||||
this.loadingState = 'ready'
|
||||
this.pullingRefreshBindingx()
|
||||
} else {
|
||||
this.loadingState = 'default'
|
||||
this.resetPullingBindingx()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
resetPullingBindingx () {
|
||||
let loadingType = this.loadingType
|
||||
let translate = this.translate
|
||||
let size = loadingType == 'pullup' ? this.pullupHeight : this.pulldownHeight
|
||||
let trans = loadingType == 'pullup' ? size : -size
|
||||
let deltaX = Binding.getComputedStyle(this.getEl('yingbing_flip_' + loadingType))[translate]
|
||||
let duration = 300
|
||||
let props = [
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType),
|
||||
property: 'transform.' + translate,
|
||||
expression: `linear(t, ${deltaX}, ${trans}, ${duration})`
|
||||
},
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_default'),
|
||||
property: 'opacity',
|
||||
expression: this.loadingState == 'default' ? '1+0' : '0+0'
|
||||
},
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_ready'),
|
||||
property: 'opacity',
|
||||
expression: '0+0'
|
||||
},
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_loading'),
|
||||
property: 'opacity',
|
||||
expression: '0+0'
|
||||
},
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_success'),
|
||||
property: 'opacity',
|
||||
expression: this.loadingState == 'success' ? '1+0' : '0+0'
|
||||
},
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_fail'),
|
||||
property: 'opacity',
|
||||
expression: this.loadingState == 'fail' ? '1+0' : '0+0'
|
||||
}
|
||||
]
|
||||
this.flipAnimationBinding = Binding.bind({
|
||||
eventType: 'timing',
|
||||
exitExpression: 't>' + duration,
|
||||
props: props
|
||||
}, (e) => {
|
||||
if (e.state == 'exit' && this.flipAnimationBinding && e.t > duration) {
|
||||
this.resetFlipAnimationBinding()
|
||||
this.loadingState = ''
|
||||
this.resetPageBinding()
|
||||
}
|
||||
})
|
||||
},
|
||||
pullingRefreshBindingx () {
|
||||
let loadingType = this.loadingType
|
||||
let duration = 1
|
||||
let props = [
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_default'),
|
||||
property: 'opacity',
|
||||
expression: '0+0'
|
||||
},
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_ready'),
|
||||
property: 'opacity',
|
||||
expression: '0+0'
|
||||
},
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_loading'),
|
||||
property: 'opacity',
|
||||
expression: '1+0'
|
||||
},
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_success'),
|
||||
property: 'opacity',
|
||||
expression: '0+0'
|
||||
},
|
||||
{
|
||||
element: this.getEl('yingbing_flip_' + loadingType + '_fail'),
|
||||
property: 'opacity',
|
||||
expression: '0+0'
|
||||
}
|
||||
]
|
||||
this.flipAnimationBinding = Binding.bind({
|
||||
eventType: 'timing',
|
||||
exitExpression: 't>' + duration,
|
||||
props: props
|
||||
}, (e) => {
|
||||
if (e.state == 'exit' && this.flipAnimationBinding && e.t > duration) {
|
||||
this.resetFlipAnimationBinding()
|
||||
this.pullingRefresh(loadingType)
|
||||
}
|
||||
})
|
||||
},
|
||||
resetFlipAnimationBinding () {
|
||||
if ( this.flipAnimationBinding ) {
|
||||
Binding.unbind({
|
||||
token: this.flipAnimationBinding.token,
|
||||
eventType: 'timing'
|
||||
})
|
||||
this.flipAnimationBinding = null
|
||||
}
|
||||
},
|
||||
getEl (selector) {
|
||||
return this.$refs[selector] ? Util.getEl(this.$refs[selector].length > 0 ? this.$refs[selector][0] : this.$refs[selector]) : null
|
||||
},
|
||||
getRef (selector) {
|
||||
return this.$refs[selector] ? this.$refs[selector].length > 0 ? this.$refs[selector][0] : this.$refs[selector] : null
|
||||
},
|
||||
resetPageBinding () {
|
||||
this.direction = ''
|
||||
this.touchTime = 0
|
||||
this.startX = 0
|
||||
this.startY = 0
|
||||
this.$nextTick(function () {
|
||||
this.isTouch = false
|
||||
this.disableTouch = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,420 @@
|
||||
<template>
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<view
|
||||
class="yingbing-flip"
|
||||
:prop="flipProp"
|
||||
:change:prop="flip.propWatcher"
|
||||
@touchstart="flip.touchstart"
|
||||
@touchmove="flip.touchmove"
|
||||
@touchend="flip.touchend"
|
||||
@touchcancel="flip.touchcancel"
|
||||
:style="{
|
||||
background: bgColor
|
||||
}">
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<view
|
||||
class="yingbing-flip"
|
||||
ref="yingbingFlip"
|
||||
@touchstart="fliptouchstart"
|
||||
@touchmove="fliptouchmove"
|
||||
@touchend="fliptouchend"
|
||||
:style="{
|
||||
background: bgColor
|
||||
}">
|
||||
<!-- #endif -->
|
||||
<view
|
||||
class="yingbing-flip-item"
|
||||
:class="'yingbing-flip-item_' + item"
|
||||
v-for="(item, index) in dataSync"
|
||||
:ref="'yingbingFlipItem_' + item"
|
||||
:style="{
|
||||
'background': bgColor,
|
||||
'transform': item > currentIndex ? translate + '(' + fullSize + ')' : item < currentIndex ? translate + '(-' + fullSize + ')' : '',
|
||||
'box-shadow': vertical ? '0 0 15rpx rgba(0,0,0,.2)' : ''
|
||||
}"
|
||||
:key="item">
|
||||
<view
|
||||
class="yingbing-flip-item-content"
|
||||
:ref="'yingbingFlipItemContent_' + item"
|
||||
:class="'yingbing-flip-item-content_' + item"
|
||||
:style="{
|
||||
'background': bgColor,
|
||||
'transform': item < currentIndex ? type == 'real' ? translate + '(' + fullSize + ')' : translate + '(0)' : translate + '(0)'
|
||||
}">
|
||||
<!-- #ifdef MP -->
|
||||
<slot v-if="item > -1 && item < count" :name="item"></slot>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP -->
|
||||
<slot v-if="item > -1 && item < count" :item="data[item]" :index="item"></slot>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<view
|
||||
class="yingbing-flip-item-bg"
|
||||
:ref="'yingbingFlipItemBg_' + item"
|
||||
:class="'yingbing-flip-item-bg_' + item"
|
||||
:style="{
|
||||
background: bgColor,
|
||||
transform: item < currentIndex && type == 'real' ? translate + '(0)' : translate + '(' + fullSize + ')',
|
||||
}"></view>
|
||||
<view
|
||||
class="yingbing-flip-item-shadow"
|
||||
:ref="'yingbingFlipItemShadow_' + item"
|
||||
:class="'yingbing-flip-item-shadow_' + item"
|
||||
:style="[shadowStyle]"></view>
|
||||
</view>
|
||||
<view class="yingbing-flip-pulldown"
|
||||
:style="[pulldownStyle]" v-if="pulldownable" ref="yingbing_flip_pulldown">
|
||||
<view class="yingbing-flip-pulldown-item yingbing-flip-pulldown-default" ref="yingbing_flip_pulldown_default">
|
||||
<slot name="pulldownDefault"></slot>
|
||||
</view>
|
||||
<view class="yingbing-flip-pulldown-item yingbing-flip-pulldown-ready" ref="yingbing_flip_pulldown_ready">
|
||||
<slot name="pulldownReady"></slot>
|
||||
</view>
|
||||
<view class="yingbing-flip-pulldown-item yingbing-flip-pulldown-loading" ref="yingbing_flip_pulldown_loading">
|
||||
<slot name="pulldownLoading"></slot>
|
||||
</view>
|
||||
<view class="yingbing-flip-pulldown-item yingbing-flip-pulldown-success" ref="yingbing_flip_pulldown_success">
|
||||
<slot name="pulldownSuccess"></slot>
|
||||
</view>
|
||||
<view class="yingbing-flip-pulldown-item yingbing-flip-pulldown-fail" ref="yingbing_flip_pulldown_fail">
|
||||
<slot name="pulldownFail"></slot>
|
||||
</view>
|
||||
</view>
|
||||
<view class="yingbing-flip-pullup"
|
||||
:style="[pullupStyle]" v-if="pullupable" ref="yingbing_flip_pullup">
|
||||
<view class="yingbing-flip-pullup-item yingbing-flip-pullup-default" ref="yingbing_flip_pullup_default">
|
||||
<slot name="pullupDefault"></slot>
|
||||
</view>
|
||||
<view class="yingbing-flip-pullup-item yingbing-flip-pullup-ready" ref="yingbing_flip_pullup_ready">
|
||||
<slot name="pullupReady"></slot>
|
||||
</view>
|
||||
<view class="yingbing-flip-pullup-item yingbing-flip-pullup-loading" ref="yingbing_flip_pullup_loading">
|
||||
<slot name="pullupLoading"></slot>
|
||||
</view>
|
||||
<view class="yingbing-flip-pullup-item yingbing-flip-pullup-success" ref="yingbing_flip_pullup_success">
|
||||
<slot name="pullupSuccess"></slot>
|
||||
</view>
|
||||
<view class="yingbing-flip-pullup-item yingbing-flip-pullup-fail" ref="yingbing_flip_pullup_fail">
|
||||
<slot name="pullupFail"></slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
// #ifdef APP-NVUE
|
||||
import flipBindingx from '../modules/flip_bindingx.js'
|
||||
// #endif
|
||||
export default {
|
||||
// #ifdef APP-NVUE
|
||||
mixins: [flipBindingx],
|
||||
// #endif
|
||||
props: {
|
||||
data: {
|
||||
type: Array,
|
||||
default () {
|
||||
return new Array
|
||||
}
|
||||
},
|
||||
vertical: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
current: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
//翻页方式
|
||||
type: {
|
||||
type: String,
|
||||
default: 'real'
|
||||
},
|
||||
//滑动周期
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
//容错距离
|
||||
sliderFault: {
|
||||
type: Number,
|
||||
default: 20
|
||||
},
|
||||
//背景颜色
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: '#fcd281'
|
||||
},
|
||||
//是否关闭点击左右2侧位置翻页
|
||||
unableClickPage: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//开启下拉刷新
|
||||
pulldownable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//下拉刷新高度
|
||||
pulldownHeight: {
|
||||
type: Number,
|
||||
default: 80
|
||||
},
|
||||
//开启上拉加载
|
||||
pullupable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//上拉加载高度
|
||||
pullupHeight: {
|
||||
type: Number,
|
||||
default: 80
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dataSync () {
|
||||
let arr = []
|
||||
if ( this.prevIndex >= 0 ) {
|
||||
arr.push(this.prevIndex)
|
||||
}
|
||||
arr.push(this.currentIndex)
|
||||
if ( this.nextIndex < this.count ) {
|
||||
arr.push(this.nextIndex)
|
||||
}
|
||||
return this.refreshing ? [] : arr.sort((a, b) => b-a)
|
||||
},
|
||||
nextIndex () {
|
||||
return this.currentIndex + 1 > this.count - 1 && this.count > 2 ? 0 : this.currentIndex + 1
|
||||
},
|
||||
prevIndex () {
|
||||
return this.currentIndex - 1 < 0 && this.count > 2 ? this.count - 1 : this.currentIndex - 1
|
||||
},
|
||||
count () {
|
||||
return this.data.length
|
||||
},
|
||||
flipProp () {
|
||||
return {
|
||||
vertical: this.vertical,
|
||||
pulldownable: this.pulldownable,
|
||||
pullupable: this.pullupable,
|
||||
pulldownHeight: this.pulldownHeight,
|
||||
pullupHeight: this.pullupHeight,
|
||||
loadingState: this.loadingState,
|
||||
duration: this.duration,
|
||||
unableClickPage: this.unableClickPage,
|
||||
nextIndex: this.nextIndex,
|
||||
prevIndex: this.prevIndex,
|
||||
currentIndex: this.currentIndex,
|
||||
type: this.type,
|
||||
count: this.count,
|
||||
flipTo: this.flipTo,
|
||||
sliderFault: this.sliderFault,
|
||||
translate: this.translate
|
||||
}
|
||||
},
|
||||
pulldownStyle () {
|
||||
return this.vertical ? {
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
height: this.pulldownHeight + 'px',
|
||||
transform: this.translate + '(-' + this.pulldownHeight + 'px)'
|
||||
} : {
|
||||
left: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
width: this.pulldownHeight + 'px',
|
||||
transform: this.translate + '(-' + this.pulldownHeight + 'px)'
|
||||
}
|
||||
},
|
||||
pullupStyle () {
|
||||
return this.vertical ? {
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
height: this.pullupHeight + 'px',
|
||||
transform: this.translate + '(' + this.pullupHeight + 'px)'
|
||||
} : {
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
width: this.pullupHeight + 'px',
|
||||
transform: this.translate + '(' + this.pullupHeight + 'px)'
|
||||
}
|
||||
},
|
||||
shadowStyle () {
|
||||
return this.vertical ? {
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
height: 0,
|
||||
// #ifdef APP-NVUE
|
||||
'background-image': 'linear-gradient(to bottom, rgba(255,255,255, 0), rgba(0,0,0,.5))'
|
||||
// #endif
|
||||
} : {
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
width: 0,
|
||||
// #ifdef APP-NVUE
|
||||
'background-image': 'linear-gradient(to right, rgba(255,255,255, 0), rgba(0,0,0,.5))'
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
translate () {
|
||||
return this.vertical ? 'translateY' : 'translateX'
|
||||
},
|
||||
fullSize () {
|
||||
return this.vertical ? '3050rpx' : '750rpx'
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
refreshing: false,
|
||||
currentIndex: 0,
|
||||
flipTo: 0,
|
||||
loadingState: '',
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.currentIndex = this.current
|
||||
},
|
||||
methods: {
|
||||
handleFlipChange (value) {
|
||||
if ( value > 0 ) {
|
||||
this.currentIndex = this.currentIndex + value > this.count - 1 ? 0 : this.currentIndex + value
|
||||
} else {
|
||||
this.currentIndex = this.currentIndex + value < 0 ? this.count - 1 : this.currentIndex + value
|
||||
}
|
||||
this.$emit('change', {
|
||||
current: this.currentIndex,
|
||||
detail: this.data[this.currentIndex]
|
||||
})
|
||||
this.$emit('update:current', this.currentIndex)
|
||||
},
|
||||
pullingRefresh (type) {
|
||||
this.$emit(type, (state) => {
|
||||
this.loadingState = state
|
||||
// #ifdef APP-NVUE
|
||||
this.resetPullingBindingx()
|
||||
// #endif
|
||||
})
|
||||
},
|
||||
flipToNext () {
|
||||
// #ifdef APP-NVUE
|
||||
this.flipToNextBindingX()
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
this.flipTo = 0
|
||||
this.$nextTick(function () {
|
||||
this.flipTo = 1
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
flipToPrev () {
|
||||
// #ifdef APP-NVUE
|
||||
this.flipToPrevBindingX()
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
this.flipTo = 0
|
||||
this.$nextTick(function () {
|
||||
this.flipTo = -1
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
refresh () {
|
||||
this.refreshing = true
|
||||
this.$nextTick(function () {
|
||||
this.currentIndex = this.current
|
||||
this.refreshing = false
|
||||
})
|
||||
},
|
||||
resetLoading () {
|
||||
this.loadingState = ''
|
||||
// #ifdef APP-NVUE
|
||||
this.resetPullingBindingx()
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
current (newVal) {
|
||||
this.currentIndex = newVal
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<!-- #ifdef APP-VUE || H5 || MP-QQ || MP-WEIXIN -->
|
||||
<script lang="wxs" module="flip" src="../modules/flip.wxs"></script>
|
||||
<!-- #endif -->
|
||||
<style>
|
||||
.yingbing-flip {
|
||||
/* #ifdef APP-NVUE */
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
height: 100%;
|
||||
/* #endif */
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.yingbing-flip-item {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
overflow: hidden;
|
||||
/* #endif */
|
||||
}
|
||||
.yingbing-flip-item-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.yingbing-flip-item-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
/* #ifdef APP-NVUE */
|
||||
box-shadow: 0 0 20rpx rgba(0,0,0,0.2);
|
||||
/* #endif */
|
||||
}
|
||||
.yingbing-flip-item-shadow {
|
||||
position: absolute;
|
||||
/* #ifdef APP-NVUE */
|
||||
opacity: 0.5;
|
||||
/* #endif */
|
||||
}
|
||||
.yingbing-flip-pulldown, .yingbing-flip-pullup {
|
||||
position: absolute;
|
||||
}
|
||||
.yingbing-flip-pulldown-item, .yingbing-flip-pullup-item {
|
||||
/* #ifndef APP-NVUE */
|
||||
visibility: hidden;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
opacity: 0;
|
||||
/* #endif */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
/* #ifdef MP */
|
||||
/deep/ .scoped-ref {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
yingbing-flip {
|
||||
display: block;
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
446
uni_modules/yingbing-flip/js_sdk/util.js
Normal file
446
uni_modules/yingbing-flip/js_sdk/util.js
Normal file
@ -0,0 +1,446 @@
|
||||
|
||||
export default {
|
||||
/**
|
||||
* 补零
|
||||
* @param {Number} val 数字
|
||||
**/
|
||||
zeroize (val) {
|
||||
return zeroize(val);
|
||||
},
|
||||
/**
|
||||
* 时间格式化
|
||||
* @param {String} time 时间戳or时间
|
||||
**/
|
||||
dateFormat (time, formats = 'yyyy-mm-dd hh:mm:ss') {
|
||||
let arr = formats.split(' ')
|
||||
let dateFormats = ''
|
||||
let timeFormats = ''
|
||||
arr.forEach(item => {
|
||||
if ( item.indexOf('yy') > -1 ) {
|
||||
dateFormats = item
|
||||
} else {
|
||||
timeFormats = item
|
||||
}
|
||||
})
|
||||
const d = new Date(time);
|
||||
let result = ''
|
||||
if ( dateFormats.indexOf('yyyy') > -1 ) {
|
||||
result += d.getFullYear() + '-'
|
||||
}
|
||||
if ( dateFormats.indexOf('mm') > -1 ) {
|
||||
result += zeroize(d.getMonth() + 1) + '-'
|
||||
}
|
||||
if ( dateFormats.indexOf('dd') > -1 ) {
|
||||
result += zeroize(d.getDate()) + ' '
|
||||
}
|
||||
if ( timeFormats.indexOf('hh') > -1 ) {
|
||||
result += zeroize(d.getHours()) + ':'
|
||||
}
|
||||
if ( timeFormats.indexOf('mm') > -1 ) {
|
||||
result += zeroize(d.getMinutes()) + ':'
|
||||
}
|
||||
if ( timeFormats.indexOf('ss') > -1 ) {
|
||||
result += zeroize(d.getSeconds()) + ':'
|
||||
}
|
||||
return result.substring(0, result.length - 1)
|
||||
},
|
||||
/**
|
||||
* 秒数转化为分秒
|
||||
* @param {String} value 秒数
|
||||
**/
|
||||
minutesFormat (value) {
|
||||
let minutes = Math.floor(value / 60 % 60) >= 10 ? Math.floor(value / 60 % 60) : '0' + Math.floor(value / 60 % 60);
|
||||
let seconds = Math.floor(value % 60) >= 10 ? Math.floor(value % 60) : '0' + Math.floor(value % 60);
|
||||
return minutes + ':' + seconds;
|
||||
},
|
||||
/**
|
||||
* 时间转化为秒数
|
||||
* @param {String} time 时间(HH:mm:ss)
|
||||
**/
|
||||
time2seconds (time){
|
||||
const seconds = parseInt(time.split(':')[0]) * 60 + parseInt(time.split(':')[1].split('.')[0]) + parseInt(time.split(':')[1].split('.')[1]) / 1000;
|
||||
return seconds;
|
||||
},
|
||||
/**
|
||||
* 移除url地址域名
|
||||
* @param {String} str http地址
|
||||
**/
|
||||
removeUrl (url) {
|
||||
let str = url.replace(/^http:\/\/[^/]+/, '');
|
||||
return str.substr(1);
|
||||
},
|
||||
/**
|
||||
* 获取文件后缀
|
||||
* @param {String} name 带后缀的文件名称
|
||||
**/
|
||||
suffix (name) {
|
||||
//获取图片后缀
|
||||
let fileName = name.lastIndexOf(".");
|
||||
let fileNameLength = name.length;
|
||||
let fileFormat = name.substring(fileName + 1, fileNameLength);
|
||||
return fileFormat;
|
||||
},
|
||||
|
||||
/**
|
||||
* 清除文件后缀
|
||||
* @param {String} name 带后缀的文件名称
|
||||
*/
|
||||
removeSuffix (name) {
|
||||
//获取图片后缀
|
||||
let fileName = name.lastIndexOf(".");
|
||||
if ( fileName > -1 ) {
|
||||
let fileNameFormat = name.substring(0, fileName);
|
||||
return fileNameFormat;
|
||||
} else {
|
||||
return name
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 数组查找符合条件元素并返回下标
|
||||
* @param {Array} arr 传入数组
|
||||
* @param {String} value 条件元素
|
||||
* @param {String} query 对比key值
|
||||
*/
|
||||
indexOf (arr, query, value) {
|
||||
let len = arr.length;
|
||||
for ( let i = 0; i < len; i++ ) {
|
||||
if ( arr[i][query] == value ) {
|
||||
return parseInt(i);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
|
||||
/**
|
||||
* 正则匹配
|
||||
* @param {String} type 匹配类型
|
||||
* @param {String} value 匹配值
|
||||
*/
|
||||
reg (type, value) {
|
||||
const regs = {
|
||||
//身份证证则
|
||||
idcard: new RegExp(/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/),
|
||||
//手机正则
|
||||
mobile: new RegExp(/^1[3456789]\d{9}$/),
|
||||
//固定电话正则
|
||||
phone: new RegExp(/^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$/),
|
||||
//金额验证
|
||||
price: new RegExp(/^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0.\d{1,2}$/),
|
||||
//邮箱验证
|
||||
email: new RegExp(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/),
|
||||
//银行卡
|
||||
bankcard: new RegExp(/^([1-9]{1})(\d{15}|\d{18})$/)
|
||||
}
|
||||
return regs[type].test(value);
|
||||
},
|
||||
/**
|
||||
* 计算2个时间差的分钟数或者秒钟数或时钟数
|
||||
* @param {datetime} time1 开始时间
|
||||
* @param {datetime} time2 结束时间
|
||||
*/
|
||||
timeMinuse (time1, time2, type = 'minutes') {
|
||||
//判断开始时间是否大于结束日期
|
||||
let date1 = new Date(time1);
|
||||
let date2 = new Date(time2);
|
||||
if ( date1 > date2 ) {
|
||||
console.log("开始时间不能大于结束时间!");
|
||||
return false;
|
||||
}
|
||||
let seconds = date2.getTime() / 1000 - date1.getTime() / 1000;
|
||||
return type == 'minutes' ? (seconds / 60) : type == 'hours' ? (seconds / 60 / 60) : seconds;
|
||||
},
|
||||
/**
|
||||
* 判断值类型返回字符
|
||||
* @param {datetime} value 需要判断类型的值
|
||||
*/
|
||||
typeof (value) {
|
||||
let type = Object.prototype.toString.call(value);
|
||||
return type.slice(8, type.length - 1)
|
||||
},
|
||||
/**
|
||||
* 生成随机字符串
|
||||
* @param {Number} len 长度
|
||||
*/
|
||||
randomString (len) {
|
||||
len = len || 32;
|
||||
var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
|
||||
var maxPos = $chars.length;
|
||||
var pwd = '';
|
||||
for (let i = 0; i < len; i++) {
|
||||
pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
|
||||
}
|
||||
return pwd;
|
||||
},
|
||||
|
||||
/**
|
||||
* 生成随机ID
|
||||
*/
|
||||
randomID () {
|
||||
let mydate = new Date();
|
||||
return mydate.getMinutes() + mydate.getSeconds() + mydate.getMilliseconds() + Math.round(Math.random() * 10000);
|
||||
},
|
||||
|
||||
/**
|
||||
* 生成随机不重复整数
|
||||
* @param {Number} len 长度
|
||||
*/
|
||||
randomSoleNumber (len) {
|
||||
let min = 0;
|
||||
let max = len - 1;
|
||||
let arr = [];
|
||||
while ( arr.length < len ) {
|
||||
let value = Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
if ( arr.indexOf(value) == -1 ) {
|
||||
arr.push( value )
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
|
||||
/**
|
||||
* 16进制颜色转化为rgb
|
||||
* @param {String} hex 16进制颜色
|
||||
*/
|
||||
hex2rgb (hex) {
|
||||
hex = hex.length == 7 ? hex : '#' + hex.slice(1, 4) + hex.slice(1, 4)
|
||||
let str="rgb("
|
||||
const r = parseInt(hex.slice(1,3),16).toString(); //ff slice不包括end
|
||||
const g = parseInt(hex.slice(3,5),16).toString(); //00
|
||||
const b = parseInt(hex.slice(5,7),16).toString(); //ff
|
||||
str += r+","+g+","+b+")";
|
||||
return str
|
||||
},
|
||||
|
||||
/**
|
||||
* 16进制颜色转化为rgba
|
||||
* @param {String} hex 16进制颜色
|
||||
*/
|
||||
hex2rgba (hex, opacity) {
|
||||
hex = hex.length == 7 ? hex : '#' + hex.slice(1, 4) + hex.slice(1, 4)
|
||||
let str="rgba("
|
||||
const r = parseInt(hex.slice(1,3),16).toString(); //ff slice不包括end
|
||||
const g = parseInt(hex.slice(3,5),16).toString(); //00
|
||||
const b = parseInt(hex.slice(5,7),16).toString(); //ff
|
||||
str += r+","+g+","+b+","+opacity+")";
|
||||
return str
|
||||
},
|
||||
|
||||
/**
|
||||
* byte转化为文件大小
|
||||
* @param {Number} byte 位
|
||||
*/
|
||||
byte2Size (byte) {
|
||||
let sizeString = ''
|
||||
if(byte == 0){
|
||||
sizeString = "0B";
|
||||
}else if(byte < 1024){
|
||||
sizeString = byte + "B";
|
||||
}else if(byte < 1048576){
|
||||
sizeString = (byte/1024).toFixed(2) + "KB";
|
||||
}else if (byte < 1073741824){
|
||||
sizeString = (byte/1048576).toFixed(2) + "MB";
|
||||
}else{
|
||||
sizeString = (byte/1073741824).toFixed(2) + "GB";
|
||||
}
|
||||
return sizeString;
|
||||
},
|
||||
|
||||
// 深度克隆
|
||||
deepClone (obj) {
|
||||
if(typeof obj !== "object" && typeof obj !== 'function') {
|
||||
//原始类型直接返回
|
||||
return obj;
|
||||
}
|
||||
var o = isArray(obj) ? [] : {};
|
||||
for(let i in obj) {
|
||||
if(obj.hasOwnProperty(i)){
|
||||
o[i] = typeof obj[i] === "object" ? this.deepClone(obj[i]) : obj[i];
|
||||
}
|
||||
}
|
||||
return o;
|
||||
},
|
||||
|
||||
/**
|
||||
* 将数字转为带中文单位的字符串
|
||||
* @param {Number} num 数字
|
||||
*/
|
||||
numtounit (num) {
|
||||
let units = [{
|
||||
label: '万',
|
||||
value: 10000,
|
||||
min: 1000
|
||||
},{
|
||||
label: '亿',
|
||||
value: 100000000,
|
||||
min: 100000000
|
||||
},{
|
||||
label: '兆',
|
||||
value: 10000000000000000,
|
||||
min: 100000000000000000
|
||||
}]
|
||||
let value = num
|
||||
units.forEach(unit => {
|
||||
if ( num >= unit.min ) {
|
||||
value = (num / unit.value).toFixed(2) + unit.label
|
||||
}
|
||||
})
|
||||
return value
|
||||
},
|
||||
/**
|
||||
* 判断像素单位,没有则加上rpx
|
||||
* @param {String} value 像素
|
||||
*/
|
||||
pixelunit (value) {
|
||||
if ( value.toString().indexOf('px') > -1 || value.toString().indexOf('em') > -1 || value.toString().indexOf('auto') > -1 || value.toString().indexOf('%') > -1 ) {
|
||||
return value
|
||||
} else {
|
||||
return value + 'rpx'
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 判断像素单位,全部转为px
|
||||
* @param {String} value 像素
|
||||
*/
|
||||
unitpixel (value) {
|
||||
if ( value.toString().indexOf('rpx') > -1 ) {
|
||||
return uni.upx2px(value.replace('rpx', ''))
|
||||
} else if ( value.toString().indexOf('px') > -1 ) {
|
||||
return parseFloat(value.replace('px', ''))
|
||||
} else if ( value.toString().indexOf('em') > -1 || value.toString().indexOf('auto') > -1 || value.toString().indexOf('%') > -1 ) {
|
||||
return value
|
||||
} else {
|
||||
return parseFloat(uni.upx2px(value))
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 判断像素单位,转化为rpx
|
||||
* @param {String} value 值
|
||||
* @param {String} unit 返回结果是否带上单位
|
||||
*/
|
||||
anytorpx (value, unit = true) {
|
||||
if ( value.toString().indexOf('rpx') > -1 ) {
|
||||
return unit ? value : parseFloat(value.replace('rpx', ''))
|
||||
} else if ( value.toString().indexOf('px') > -1 ) {
|
||||
return parseFloat(value.replace('px', '') * (750 / uni.getSystemInfoSync().windowWidth)) + (unit ? 'rpx' : 0)
|
||||
} else if ( value.toString().indexOf('auto') > -1 ) {
|
||||
return 'auto'
|
||||
} else if ( value.toString().indexOf('%') > -1 ) {
|
||||
return parseFloat((value.replace('%', '') / 100) * 750) + (unit ? 'rpx' : 0)
|
||||
} else if (value.toString().indexOf('em') > -1 || value.toString().indexOf('rem') > -1 ) {
|
||||
return parseFloat(value.replace('em', '').replace('rem', '') * 32) + (unit ? 'rpx' : 0)
|
||||
} else if ( /^\d+$/.test(value) ) {
|
||||
return parseFloat(value) + (unit ? 'rpx' : 0)
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 判断像素单位,转化为px
|
||||
* @param {String} value 值
|
||||
* @param {String} unit 返回结果是否带上单位
|
||||
*/
|
||||
anytopx (value, unit = false) {
|
||||
if ( value.toString().indexOf('rpx') > -1 ) {
|
||||
return uni.upx2px(value.replace('rpx', '')) + (unit ? 'px' : 0)
|
||||
} else if ( value.toString().indexOf('px') > -1 ) {
|
||||
return parseFloat(value.replace('px', '')) + (unit ? 'px' : 0)
|
||||
} else if ( value.toString().indexOf('auto') > -1 ) {
|
||||
return 'auto'
|
||||
} else if ( value.toString().indexOf('%') > -1 ) {
|
||||
return parseFloat((value.replace('%', '') / 100) * uni.getSystemInfoSync().windowWidth) + (unit ? 'px' : 0)
|
||||
} else if (value.toString().indexOf('em') > -1 || value.toString().indexOf('rem') > -1 ) {
|
||||
return parseFloat(value.replace('em', '').replace('rem', '') * uni.getSystemInfoSync().windowWidth) + (unit ? 'px' : 0)
|
||||
} else if ( /^\d+$/.test(value) ) {
|
||||
return parseFloat(value) + (unit ? 'px' : 0)
|
||||
}
|
||||
},
|
||||
getRefs (components, name, current) {
|
||||
// #ifndef MP
|
||||
return current >= 0 ? components.$refs[name][current] : components.$refs[name]
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
return {}
|
||||
// #endif
|
||||
},
|
||||
//获取节点
|
||||
getEl (el) {
|
||||
if (typeof el === 'string' || typeof el === 'number') return el;
|
||||
if (WXEnvironment) {
|
||||
return el.ref;
|
||||
} else {
|
||||
return el instanceof HTMLElement ? el : el.$el;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 获取指定父节点
|
||||
* @param {String} components 当前实例
|
||||
* @param {String} name 父节点名称
|
||||
*/
|
||||
getParent(name, components) {
|
||||
let parent = components.$parent
|
||||
if (parent) {
|
||||
let parentName = parent.$options.name
|
||||
while (parentName !== name) {
|
||||
parent = parent.$parent
|
||||
if (parent) {
|
||||
parentName = parent.$options.name
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
return parent
|
||||
}
|
||||
return null
|
||||
},
|
||||
/**
|
||||
* 获取指定子节点
|
||||
* @param {String} components 当前实例
|
||||
* @param {String} name 父节点名称
|
||||
*/
|
||||
getChildrens(names, components) {
|
||||
let arr = []
|
||||
let childs = names.split(',')
|
||||
const dowhile = (children) => {
|
||||
if ( this.typeof(children) == 'Array' ) {
|
||||
children.forEach(child => {
|
||||
if ( childs.indexOf(child.$options.name) > -1 ) {
|
||||
arr.push(child)
|
||||
}
|
||||
if ( child.$children && child.$children.length > 0 ) {
|
||||
dowhile(child.$children)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
dowhile(components.$children)
|
||||
return arr;
|
||||
},
|
||||
/**
|
||||
* 获取指定子节点
|
||||
* @param {String} selector 节点class或者id
|
||||
* @param {String} el 节点
|
||||
* @param {String} components 当前实例
|
||||
*/
|
||||
getRect (selector, el, components) {
|
||||
return new Promise(resolve => {
|
||||
// #ifdef APP-NVUE
|
||||
uni.requireNativePlugin('dom').getComponentRect(el, res => {
|
||||
resolve(res.size)
|
||||
})
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
uni.createSelectorQuery().in(components).select(selector).boundingClientRect(data => {
|
||||
resolve(data)
|
||||
}).exec();
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 判断arr是否为一个数组,返回一个bool值
|
||||
function isArray (arr) {
|
||||
return Object.prototype.toString.call(arr) === '[object Array]';
|
||||
}
|
||||
|
||||
function zeroize (val) {
|
||||
return val >= 10 ? val : '0' + val;
|
||||
}
|
81
uni_modules/yingbing-flip/package.json
Normal file
81
uni_modules/yingbing-flip/package.json
Normal file
@ -0,0 +1,81 @@
|
||||
{
|
||||
"id": "yingbing-flip",
|
||||
"displayName": "好用翻页组件",
|
||||
"version": "1.0.4",
|
||||
"description": "高性能翻页组件",
|
||||
"keywords": [
|
||||
"翻页"
|
||||
],
|
||||
"repository": "https://gitee.com/yingbing-developer/yingbing-flip.git",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "u",
|
||||
"vue3": "u"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "u",
|
||||
"app-nvue": "u"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "u",
|
||||
"Android Browser": "u",
|
||||
"微信浏览器(Android)": "u",
|
||||
"QQ浏览器(Android)": "u"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "u",
|
||||
"IE": "u",
|
||||
"Edge": "u",
|
||||
"Firefox": "u",
|
||||
"Safari": "u"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "u",
|
||||
"阿里": "u",
|
||||
"百度": "u",
|
||||
"字节跳动": "u",
|
||||
"QQ": "u",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
344
uni_modules/yingbing-flip/readme.md
Normal file
344
uni_modules/yingbing-flip/readme.md
Normal file
@ -0,0 +1,344 @@
|
||||
#使用须知
|
||||
|
||||
* 1、这是一个翻页组件,适用于小说翻页或答题功能
|
||||
* 2、这个插件支持APP-NVUE、APP-VUE、H5、微信小程序
|
||||
* 3、该组件滑动项同时只能存在当前项、前面项、后面项3个,其余项会被销毁
|
||||
* 4、如果想要构建阅读器需要配合[好用阅读分页插件](https://ext.dcloud.net.cn/plugin?id=6026)使用
|
||||
* 5、有什么不懂,可以加群 1087735942 聊
|
||||
|
||||
#props属性
|
||||
| 属性名 | 类型 | 默认值 | 可选值 | 说明 |
|
||||
| :----- | :----: | :----: | :----: | :---- |
|
||||
| data | Array | ---- | ---- | 列表数据 |
|
||||
| current | Number | 0 | ---- | 初始化位置 |
|
||||
| vertical | Boolean | false | true/false | 垂直滑动 |
|
||||
| duration | Number | 100 | ---- | 滑动动画时间 |
|
||||
| bgColor | String | ---- | ---- | 背景色 |
|
||||
| pulldownable | Boolean | false | true/false | 开启下拉刷新 |
|
||||
| pullupable | Boolean | false | true/false | 开启上拉加载 |
|
||||
| pulldownHeight | Number | 80 | ---- | 下拉刷新控件高度(px) |
|
||||
| pullupHeight | Number | 80 | ---- | 上拉加载控件高度(px) |
|
||||
| sliderFault | Number | 20 | ---- | 滑动容错距离(px) |
|
||||
| type | String | real | real(仿真)/cover(覆盖)/none(无动画) | 翻页方式 |
|
||||
| unableClickPage | Boolean | false | true/false | 关闭点击左右2侧翻页功能(type为none时忽略此属性) |
|
||||
|
||||
#event事件
|
||||
| 事件名 | 参数 | 说明 |
|
||||
| :----- | :----: | :---- |
|
||||
| change | current: 当前滑动位置, detail: 当前滑动位置列表数据 | 位置改变事件 |
|
||||
| pulldown | callback: 回调 | 下拉刷新事件 |
|
||||
| pullup | callback: 回调 | 上拉加载事件 |
|
||||
|
||||
#内置方法
|
||||
| 方法名 | 参数 | 说明 |
|
||||
| :--- | :------ | :---- |
|
||||
| refresh | ---- | 刷新滑动位置(替换数据时使用) |
|
||||
| flipToNext | ---- | 翻到到下个位置 |
|
||||
| flipToPrev | ---- | 翻到上个位置 |
|
||||
|
||||
#slot插槽
|
||||
| 名称 | 说明 |
|
||||
| :----- | :---- | :---- |
|
||||
| pulldownDefault | 下拉加载默认提示 |
|
||||
| pulldownReady | 下拉加载准备提示 |
|
||||
| pulldownLoading | 下拉加载等待提示 |
|
||||
| pulldownSuccess | 下拉加载成功提示 |
|
||||
| pulldownFail | 下拉加载失败提示 |
|
||||
| pullupDefault | 上拉加载默认提示 |
|
||||
| pullupReady | 上拉加载准备提示 |
|
||||
| pullupLoading | 上拉加载等待提示 |
|
||||
| pullupSuccess | 上拉加载成功提示 |
|
||||
| pullupFail | 上拉加载失败提示 |
|
||||
|
||||
|
||||
#快速开始
|
||||
```html
|
||||
<yingbing-flip :data="list" style="height: 100vh;">
|
||||
<!-- #ifndef MP -->
|
||||
<template v-slot="{item, index}">
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP -->
|
||||
<template v-for="(item, index) in list" :slot="index">
|
||||
<!-- #endif -->
|
||||
<view style="height: 100%">
|
||||
<text style="font-size: 50px;font-weight: bold;color: #fff;">{{item}}</text>
|
||||
</view>
|
||||
</template>
|
||||
</yingbing-flip>
|
||||
```
|
||||
```javascript
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
list: []
|
||||
}
|
||||
},
|
||||
onReady () {
|
||||
for ( let i = 0; i < 10; i++ ) {
|
||||
this.list.push(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#垂直滑动
|
||||
```html
|
||||
<yingbing-flip vertical :data="list" style="height: 100vh;">
|
||||
<!-- #ifndef MP -->
|
||||
<template v-slot="{item, index}">
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP -->
|
||||
<template v-for="(item, index) in list" :slot="index">
|
||||
<!-- #endif -->
|
||||
<view style="height: 100%">
|
||||
<text style="font-size: 50px;font-weight: bold;color: #fff;">{{item}}</text>
|
||||
</view>
|
||||
</template>
|
||||
</yingbing-flip>
|
||||
```
|
||||
```javascript
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
list: []
|
||||
}
|
||||
},
|
||||
onReady () {
|
||||
for ( let i = 0; i < 10; i++ ) {
|
||||
this.list.push(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#下拉刷新
|
||||
```html
|
||||
<yingbing-flip :data="list" vertical pulldownable @pulldown="handlePulldown" style="height: 100vh;">
|
||||
<!-- #ifndef MP -->
|
||||
<template v-slot="{item, index}">
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP -->
|
||||
<template v-for="(item, index) in list" :slot="index">
|
||||
<!-- #endif -->
|
||||
<view style="height: 100%">
|
||||
<text style="font-size: 50px;font-weight: bold;color: #fff;">{{item}}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template #pulldownDefault>
|
||||
<view class="pulldown">
|
||||
<text>下拉刷新</text>
|
||||
</view>
|
||||
</template>
|
||||
<template #pulldownReady>
|
||||
<view class="pulldown">
|
||||
<text>松开刷新</text>
|
||||
</view>
|
||||
</template>
|
||||
<template #pulldownLoading>
|
||||
<view class="pulldown">
|
||||
<text>正在刷新</text>
|
||||
</view>
|
||||
</template>
|
||||
<template #pulldownSuccess>
|
||||
<view class="pulldown">
|
||||
<text>刷新成功</text>
|
||||
</view>
|
||||
</template>
|
||||
<template #pulldownFail>
|
||||
<view class="pulldown">
|
||||
<text>刷新失败</text>
|
||||
</view>
|
||||
</template>
|
||||
</yingbing-flip>
|
||||
```
|
||||
```javascript
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
list: []
|
||||
}
|
||||
},
|
||||
onReady () {
|
||||
for ( let i = 0; i < 10; i++ ) {
|
||||
this.list.push(i)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handlePulldown (callback) {
|
||||
//模拟请求
|
||||
setTimeout(() => {
|
||||
let arr = []
|
||||
for ( let i = 0; i < 10; i++ ) {
|
||||
arr.push(i)
|
||||
}
|
||||
this.list = arr
|
||||
callback('success') //成功回调
|
||||
// callback('fail') //失败回调
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
```css
|
||||
.pulldown {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/* #ifdef APP-NVUE */
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* #endif */
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#上拉加载
|
||||
```html
|
||||
<yingbing-flip :data="list" vertical pullupable @pullup="handlePullup" style="height: 100vh;">
|
||||
<!-- #ifndef MP -->
|
||||
<template v-slot="{item, index}">
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP -->
|
||||
<template v-for="(item, index) in list" :slot="index">
|
||||
<!-- #endif -->
|
||||
<view style="height: 100%">
|
||||
<text style="font-size: 50px;font-weight: bold;color: #fff;">{{item}}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template #pullupDefault>
|
||||
<view class="pulldown">
|
||||
<text>上拉加载</text>
|
||||
</view>
|
||||
</template>
|
||||
<template #pullupReady>
|
||||
<view class="pulldown">
|
||||
<text>松开刷新</text>
|
||||
</view>
|
||||
</template>
|
||||
<template #pullupLoading>
|
||||
<view class="pulldown">
|
||||
<text>正在刷新</text>
|
||||
</view>
|
||||
</template>
|
||||
<template #pullupSuccess>
|
||||
<view class="pulldown">
|
||||
<text>刷新成功</text>
|
||||
</view>
|
||||
</template>
|
||||
<template #pullupFail>
|
||||
<view class="pulldown">
|
||||
<text>刷新失败</text>
|
||||
</view>
|
||||
</template>
|
||||
</yingbing-flip>
|
||||
```
|
||||
```javascript
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
list: []
|
||||
}
|
||||
},
|
||||
onReady () {
|
||||
for ( let i = 0; i < 10; i++ ) {
|
||||
this.list.push(i)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handlePullup (callback) {
|
||||
//模拟请求
|
||||
setTimeout(() => {
|
||||
for ( let i = 0; i < 10; i++ ) {
|
||||
this.list.push(i)
|
||||
}
|
||||
callback('success') //成功回调
|
||||
// callback('fail') //失败回调
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
```css
|
||||
.pulldown {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/* #ifdef APP-NVUE */
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* #endif */
|
||||
}
|
||||
```
|
||||
|
||||
#JS控制滑动
|
||||
```html
|
||||
<yingbing-flip ref="flip" :data="list" style="height: 100vh;">
|
||||
<!-- #ifndef MP -->
|
||||
<template v-slot="{item, index}">
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP -->
|
||||
<template v-for="(item, index) in list" :slot="index">
|
||||
<!-- #endif -->
|
||||
<view style="height: 100%">
|
||||
<text style="font-size: 50px;font-weight: bold;color: #fff;">{{item}}</text>
|
||||
</view>
|
||||
</template>
|
||||
</yingbing-flip>
|
||||
<button @tap="flipToPrev">向前滑动</button>
|
||||
<button @tap="flipToNext">向后滑动</button>
|
||||
```
|
||||
```javascript
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
list: [1,2,3,5,6]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
flipToNext () {
|
||||
this.$refs.flip.flipToNext()
|
||||
},
|
||||
flipToPrev () {
|
||||
this.$refs.flip.flipToPrev()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#刷新组件
|
||||
```html
|
||||
<yingbing-flip ref="flip" :data="list" style="height: 100vh;">
|
||||
<!-- #ifndef MP -->
|
||||
<template v-slot="{item, index}">
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP -->
|
||||
<template v-for="(item, index) in list" :slot="index">
|
||||
<!-- #endif -->
|
||||
<view style="height: 100%">
|
||||
<text style="font-size: 50px;font-weight: bold;color: #fff;">{{item}}</text>
|
||||
</view>
|
||||
</template>
|
||||
</yingbing-flip>
|
||||
<button @tap="refresh">刷新</button>
|
||||
```
|
||||
```javascript
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
list: [1,2,3,5,6]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
refresh () {
|
||||
this.list = [7,8,9,10,11]
|
||||
this.$refs.flip.refresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
2718
unpackage/dist/dev/app-plus/app-service.js
vendored
2718
unpackage/dist/dev/app-plus/app-service.js
vendored
File diff suppressed because one or more lines are too long
2952
unpackage/dist/dev/app-plus/app-view.js
vendored
2952
unpackage/dist/dev/app-plus/app-view.js
vendored
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user