Browse Source

Merge branch 'dev_pig' into dev_des

# Conflicts:
#	pages.json
#	uni_modules/uni-transition/components/uni-transition/uni-transition.vue
dev_des
1054425342@qq.com 3 months ago
parent
commit
5a5380710e
  1. 968
      pages.json
  2. 330
      pig/chapter1/chapter1.vue
  3. 369
      pig/chapter2/chapter2.vue
  4. 83
      pig/chapter3/art.vue
  5. 84
      pig/chapter3/brave.vue
  6. 426
      pig/chapter3/chapter3.vue
  7. 83
      pig/chapter3/humble.vue
  8. 84
      pig/chapter3/sacred.vue
  9. 83
      pig/chapter3/smart.vue
  10. 83
      pig/chapter3/stupid.vue
  11. 644
      pig/chapter4/chapter4.vue
  12. 109
      pig/chapter4/first.vue
  13. 109
      pig/chapter4/fourth.vue
  14. 155
      pig/chapter4/secBuy.vue
  15. 109
      pig/chapter4/second.vue
  16. 109
      pig/chapter4/third.vue
  17. 1005
      pig/home/home.vue
  18. 24
      uni_modules/uni-transition/components/uni-transition/createAnimation.js
  19. 597
      uni_modules/uni-transition/components/uni-transition/uni-transition.vue
  20. 373
      uni_modules/uni-transition/components/uni-transition/uni-transition_BACKUP_472.vue
  21. 277
      uni_modules/uni-transition/components/uni-transition/uni-transition_BASE_472.vue
  22. 319
      uni_modules/uni-transition/components/uni-transition/uni-transition_LOCAL_472.vue
  23. 310
      uni_modules/uni-transition/components/uni-transition/uni-transition_REMOTE_472.vue

968
pages.json

@ -1,442 +1,576 @@
{
"pages": [
"pages": [
{
"path": "pages/stratIndex",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/index/index",
"style": {
"navigationStyle": "custom"
// "navigationBarTitleText": "CGC-ICH"
}
},
{
"path": "pages/index/readingBody",
"style": {
"navigationStyle": "custom"
// "navigationBarTitleText": "阅读体"
}
},
{
"path": "pages/index/sensoryStore",
"style": {
"navigationStyle": "custom"
// "navigationBarTitleText": "有感商店"
}
},
{
"path": "pages/index/intelligentAgent",
"style": {
"navigationStyle": "custom"
// "navigationBarTitleText": "智能体"
}
},
{
"path": "pages/index/iSoul",
"style": {
"navigationStyle": "custom"
// "navigationBarTitleText": "iSoul"
}
},
{
"path": "pages/login/login",
"style": {
"navigationBarTitleText": "登录",
"navigationStyle": "custom"
}
},
{
"path": "pages/index/timeShopBank",
"style": {
"navigationBarTitleText": "时间银行",
"navigationStyle": "custom"
}
}
],
"subPackages": [
{
"root": "subPackages",
"pages": [
{
"path": "pages/stratIndex",
"style": {
"navigationStyle": "custom"
}
"path": "order/trades",
"style": {
"navigationBarTitleText": "全部订单"
}
},
{
"path": "pages/index/index",
"style": {
"navigationStyle": "custom"
// "navigationBarTitleText": "CGC-ICH"
}
"path": "order/detail",
"style": {
"navigationBarTitleText": "订单详情",
"navigationStyle": "custom"
}
},
{
"path": "pages/index/readingBody",
"style": {
"navigationStyle": "custom"
// "navigationBarTitleText": "阅读体"
}
"path": "techan/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "pages/index/sensoryStore",
"style": {
// "navigationStyle": "custom"
"navigationBarTitleText": "有感商店"
}
"path": "techan/detail",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/index/intelligentAgent",
"style": {
"navigationStyle": "custom"
// "navigationBarTitleText": "智能体"
}
"path": "techan/order",
"style": {
"navigationBarTitleText": "确认订单"
}
},
{
"path": "pages/index/iSoul",
"style": {
"navigationStyle": "custom",
"navigationBarTextStyle":"white"
// "navigationBarTitleText": "iSoul"
}
"path": "webPage/webPage",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/login/login",
"style": {
"navigationBarTitleText": "登录",
"navigationStyle": "custom"
}
"path": "video/video",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/index/timeShopBank",
"style": {
"navigationBarTitleText": "时间银行",
"navigationStyle": "custom"
}
}
{
"path": "readingBody/index",
"style": {
"navigationBarTitleText": "阅读体",
"navigationStyle": "custom"
}
},
{
"path": "haveFeeling/shopDetail",
"style": {
"navigationBarTitleText": "有感商店详情页",
"navigationStyle": "custom"
}
},
{
"path": "haveFeeling/detailXiang",
"style": {
"navigationBarTitleText": "有感商店"
}
},
{
"path": "letter/detail",
"style": {
"navigationBarTitleText": "文章详情"
}
},
{
"path": "user/privacy",
"style": {
"navigationBarTitleText": "详情"
}
},
{
"path": "user/privacyInfo",
"style": {
"navigationBarTitleText": "详情"
}
},
{
"path": "user/travelerList",
"style": {
"navigationBarTitleText": "收货地址"
}
},
{
"path": "user/myAddressAdd",
"style": {
"navigationBarTitleText": "收货地址"
}
},
{
"path": "user/gwc",
"style": {
"navigationBarTitleText": "购物车"
}
},
{
"path": "order/gwcOrder",
"style": {
"navigationBarTitleText": "下单"
}
},
{
"path": "user/profile",
"style": {
"navigationBarTitleText": "个人信息"
}
},
{
"path": "user/changeNickname",
"style": {
"navigationBarTitleText": "修改昵称"
}
},
{
"path": "search/search",
"style": {
"navigationBarTitleText": "搜索"
}
},
{
"path": "equityGoods/index",
"style": {
"navigationBarTitleText": "权益商品"
}
},
{
"path": "equityGoods/list",
"style": {
"navigationBarTitleText": "权益商品"
}
},
{
"path": "equityGoods/detail",
"style": {
"navigationBarTitleText": "权益商品"
}
}
]
},
{
"root": "xxdf",
"pages": [
{
"path": "home/home",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/cover1",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/detail1",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/detail2",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/detail3",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/detail4",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/detail5",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter2/cover",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter3/cover",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter3/randomImage",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter4/cover",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"enableShareAppMessage": true,
"enableShareTimeline": true
}
}
]
},
{
"root": "taozi",
"pages": [
{
"path": "home/home",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/chapter1",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter2/chapter2",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter3/chapter3",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter4/chapter4",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
}
]
},
{
"root": "bmzm",
"pages": [
{
"path": "home/home",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter2/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter3/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter4/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter5/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter6/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter7/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
}
]
},
{
"root": "pig",
"pages": [
{
"path": "home/home",
"style": {
"navigationBarTitleText": "",
"navigationBarTextStyle": "white",
],
"subPackages": [
{
"root": "subPackages",
"pages": [
{
"path": "order/trades",
"style": {
"navigationBarTitleText": "全部订单"
}
},
{
"path": "order/detail",
"style": {
"navigationBarTitleText": "订单详情",
"navigationStyle": "custom"
}
},
{
"path": "techan/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "techan/detail",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "techan/order",
"style": {
"navigationBarTitleText": "确认订单"
}
},
{
"path": "webPage/webPage",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "video/video",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "readingBody/index",
"style": {
"navigationBarTitleText": "阅读体",
"navigationStyle": "custom"
}
},
{
"path": "haveFeeling/shopDetail",
"style": {
"navigationBarTitleText": "有感商店详情页",
"navigationStyle": "custom"
}
},
{
"path": "haveFeeling/detailXiang",
"style": {
"navigationBarTitleText": "有感商店"
}
},
{
"path": "letter/detail",
"style": {
"navigationBarTitleText": "文章详情"
}
},
{
"path": "user/privacy",
"style": {
"navigationBarTitleText": "详情"
}
},
{
"path": "user/privacyInfo",
"style": {
"navigationBarTitleText": "详情"
}
},
{
"path": "user/travelerList",
"style": {
"navigationBarTitleText": "收货地址"
}
},
{
"path": "user/myAddressAdd",
"style": {
"navigationBarTitleText": "收货地址"
}
},
{
"path": "user/gwc",
"style": {
"navigationBarTitleText": "购物车"
}
},
{
"path" : "order/gwcOrder",
"style" : {
"navigationBarTitleText" : "下单"
}
},
{
"path": "user/profile",
"style": {
"navigationBarTitleText": "个人信息"
}
},
{
"path": "user/changeNickname",
"style": {
"navigationBarTitleText": "修改昵称"
}
},
{
"path": "search/search",
"style": {
"navigationBarTitleText": "搜索"
}
},
{
"path": "equityGoods/index",
"style": {
"navigationBarTitleText": "权益商品"
}
},
{
"path": "equityGoods/list",
"style": {
"navigationBarTitleText": "权益商品"
}
},
{
"path": "equityGoods/detail",
"style": {
"navigationBarTitleText": "权益商品"
}
}
"navigationStyle": "custom"
}
},
{
"path": "chapter1/chapter1",
"style": {
"navigationBarTitleText": "",
"navigationBarTextStyle": "white",
"navigationStyle": "custom"
}
},
{
"path": "chapter2/chapter2",
"style": {
"navigationBarTitleText": "",
"navigationBarTextStyle": "white",
]
},
{
"root": "xxdf",
"pages": [
{
"path": "home/home",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/cover1",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/detail1",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/detail2",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/detail3",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/detail4",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/detail5",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter2/cover",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter3/cover",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter3/randomImage",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter4/cover",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"enableShareAppMessage": true,
"enableShareTimeline": true
}
}
]
"navigationStyle": "custom"
}
},
{
"path": "chapter3/chapter3",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter3/brave",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter3/sacred",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter3/humble",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter3/art",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter3/smart",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter3/stupid",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/chapter4",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/secBuy",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"root": "taozi",
"pages": [
{
"path": "home/home",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/chapter1",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter2/chapter2",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter3/chapter3",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter4/chapter4",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
}
]
"path": "chapter4/first",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"root": "bmzm",
"pages": [
{
"path": "home/home",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter1/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter2/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter3/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter4/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter5/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter6/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "chapter7/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
}
]
"path": "chapter4/second",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/third",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{
"path": "chapter4/fourth",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
}
],
"tabBar": {
"custom": true,
"color": "#333333",
"selectedColor": "#6CA5AA",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"fontSize": "24rpx",
"height": "123rpx",
"iconWidth": "40rpx",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"visible": false
},
{
"pagePath": "pages/index/readingBody",
"text": "阅读体",
"visible": false
},
{
"pagePath": "pages/index/timeShopBank",
"text": "时间银行",
"visible": false
},
{
"pagePath": "pages/index/intelligentAgent",
"text": "智能体",
"visible": false
},
{
"pagePath": "pages/index/iSoul",
"text": "iSoul",
"visible": false
}
]
},
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "Epic Soul",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"uniIdRouter": {}
]
}
],
"tabBar": {
"custom": true,
"color": "#333333",
"selectedColor": "#6CA5AA",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"fontSize": "24rpx",
"height": "123rpx",
"iconWidth": "40rpx",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"visible": false
},
{
"pagePath": "pages/index/readingBody",
"text": "阅读体",
"visible": false
},
{
"pagePath": "pages/index/timeShopBank",
"text": "时间银行",
"visible": false
},
{
"pagePath": "pages/index/intelligentAgent",
"text": "智能体",
"visible": false
},
{
"pagePath": "pages/index/iSoul",
"text": "iSoul",
"visible": false
}
]
},
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"uniIdRouter": {}
}

330
pig/chapter1/chapter1.vue

@ -0,0 +1,330 @@
<template>
<view>
<swiper
class="main-swiper"
:vertical="true"
:current="currentIndex"
@change="handleSwiperChange"
:duration="300"
:style="{ height: '100vh' }"
>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[0]">
<image
v-show="shouldShowContent(0)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/e2e3e00841d713937d938ae45835d016.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[1]">
<image
v-show="shouldShowContent(1)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/8cab90fe198b18b85637e21f726e75c2.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[2]">
<image
v-show="shouldShowContent(2)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/2946a97006765d53d3d74cedf0999b3c.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
<view class="content-layer" v-show="shouldShowContent(2)">
<image
class="layer-img3"
:class="{
hidden: !animationStates[2],
blink: animationStates[2],
}"
:src="
showImg(
'/uploads/20250802/ff96e22b3da7d3eb558552227edb24a5.png'
)
"
:lazy-load="true"
mode="widthFix"
></image>
</view>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<image
style="width: 100%; height: 100%"
:src="
showImg('/uploads/20250802/dee49f1aa510d85c368aafc889e24cc0.png')
"
mode="aspectFill"
></image>
<image
@click="goChapter"
style="
width: 137rpx;
height: 108rpx;
position: absolute;
bottom: 125rpx;
left: 307rpx;
"
:src="
showImg('/uploads/20250802/165e072a1537b0fab14c6ec2f42e7974.png')
"
mode="aspectFill"
></image>
</view>
</swiper-item>
</swiper>
</view>
</template>
<script>
import TitleHeader from "@/components/TitleHeader.vue";
export default {
components: {
TitleHeader,
},
data() {
return {
currentIndex: 0,
loadedPages: {
0: false,
1: false,
2: false,
3: false,
4: false,
5: false,
6: false,
},
animationStates: {
0: false,
1: false,
2: false,
3: false,
4: false,
5: false,
6: false,
},
preloadBuffer: 1,
titleHeight: 0,
};
},
watch: {
currentIndex(newIndex) {
for (
let i = Math.max(0, newIndex - this.preloadBuffer);
i <= Math.min(9, newIndex + this.preloadBuffer);
i++
) {
this.loadedPages[i] = true;
}
},
},
mounted() {
this.titleHeight = uni.getStorageSync("titleHeight");
for (let i = 0; i <= Math.min(1 + this.preloadBuffer, 9); i++) {
this.loadedPages[i] = true;
}
setTimeout(() => {
this.animationStates[this.currentIndex] = true;
}, 50);
},
methods: {
goChapter() {
uni.navigateTo({
url: "/pig/chapter2/chapter2",
});
},
handleSwiperChange(e) {
const newIndex = e.detail.current;
this.currentIndex = newIndex;
this.animationStates[newIndex] = false;
setTimeout(() => {
this.animationStates[newIndex] = true;
}, 50);
},
shouldShowContent(index) {
return Math.abs(index - this.currentIndex) <= this.preloadBuffer;
},
goBack() {
uni.navigateTo({
url: "/taozi/home/home?targetIndex=5",
});
},
},
};
</script>
<style lang="scss" scoped>
.main-swiper {
width: 100%;
height: 100vh;
}
.page-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
position: relative;
overflow: hidden;
width: 100%;
}
.bg-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.layer-img1 {
width: 500rpx;
z-index: 2;
margin-right: 180rpx;
margin-top: 50rpx;
}
.layer-img2 {
z-index: 2;
position: absolute;
bottom: 18%;
left: 0;
width: 100%;
height: 350rpx;
}
.content-layer {
margin: 130rpx 0;
width: 100%;
height: 100%;
display: flex;
justify-content: flex-end;
}
.layer-img3 {
width: 118rpx;
height: 69rpx;
z-index: 2;
position: absolute;
top: 238rpx;
right: 58rpx;
}
.layer-img4 {
z-index: 2;
width: 400rpx;
height: 400rpx;
margin-top: 400rpx;
margin-left: 80rpx;
}
.layer-img5 {
z-index: 2;
position: absolute;
bottom: 90rpx;
right: 30rpx;
width: 320rpx;
height: 500rpx;
}
.back-btn {
position: absolute;
top: 50rpx;
left: 50rpx;
z-index: 2;
background-color: rgb(0 0 0 / 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.hidden {
opacity: 0;
}
.slide-in-from-left {
animation: slideInLeft 1.2s ease-out forwards;
}
@keyframes slideInLeft {
0% {
opacity: 0;
transform: translateX(-100px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
.slide-in-from-right {
animation: slideInRight 1.2s ease-out forwards;
}
.blink {
animation: blink 1.5s infinite;
}
@keyframes slideInRight {
0% {
opacity: 0;
transform: translateX(100px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
@keyframes blink {
0%,
50% {
opacity: 1;
}
25%,
75% {
opacity: 0.3;
}
}
</style>

369
pig/chapter2/chapter2.vue

@ -0,0 +1,369 @@
<template>
<view>
<swiper
class="main-swiper"
:vertical="true"
:current="currentIndex"
@change="handleSwiperChange"
:duration="300"
:style="{ height: '100vh' }"
>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[0]">
<image
v-show="shouldShowContent(0)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/1b7efb30e20fc563d82b6b5c9c2ee3d1.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[1]">
<image
v-show="shouldShowContent(1)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/d2d830cd1171e194e427c0782fb77c1b.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
<view class="content-layer" v-show="shouldShowContent(1)">
<image
class="layer-img2"
:class="{
hidden: !animationStates[1],
'fade-in': animationStates[1],
}"
:src="
showImg(
'/uploads/20250802/70cb6f2efde536bdde781ae387529a5c.png'
)
"
:lazy-load="true"
mode="widthFix"
></image>
</view>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[2]">
<image
v-show="shouldShowContent(2)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/6f74f39c254998394f11b081220b60bc.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[3]">
<image
v-show="shouldShowContent(3)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/a85fad872bcdb3c1312ef9e799eb7863.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<image
style="width: 100%; height: 100%"
:src="
showImg('/uploads/20250802/c25deec8a6e4f84c8229718312c6ff02.png')
"
mode="aspectFill"
></image>
<image
@click="goChapter"
style="
width: 137rpx;
height: 108rpx;
position: absolute;
bottom: 125rpx;
left: 307rpx;
"
:src="
showImg('/uploads/20250802/165e072a1537b0fab14c6ec2f42e7974.png')
"
mode="aspectFill"
></image>
</view>
</swiper-item>
</swiper>
</view>
</template>
<script>
import TitleHeader from "@/components/TitleHeader.vue";
export default {
components: {
TitleHeader,
},
data() {
return {
currentIndex: 0,
loadedPages: {
0: false,
1: false,
2: false,
3: false,
4: false,
5: false,
6: false,
},
animationStates: {
0: false,
1: false,
2: false,
3: false,
4: false,
5: false,
6: false,
},
preloadBuffer: 1,
titleHeight: 0,
};
},
watch: {
currentIndex(newIndex) {
for (
let i = Math.max(0, newIndex - this.preloadBuffer);
i <= Math.min(9, newIndex + this.preloadBuffer);
i++
) {
this.loadedPages[i] = true;
}
},
},
mounted() {
this.titleHeight = uni.getStorageSync("titleHeight");
for (let i = 0; i <= Math.min(1 + this.preloadBuffer, 9); i++) {
this.loadedPages[i] = true;
}
setTimeout(() => {
this.animationStates[this.currentIndex] = true;
}, 50);
},
methods: {
goChapter() {
uni.navigateTo({
url: "/pig/chapter3/chapter3",
});
},
handleSwiperChange(e) {
const newIndex = e.detail.current;
this.currentIndex = newIndex;
this.animationStates[newIndex] = false;
setTimeout(() => {
this.animationStates[newIndex] = true;
}, 50);
},
shouldShowContent(index) {
return Math.abs(index - this.currentIndex) <= this.preloadBuffer;
},
goBack() {
uni.navigateTo({
url: "/taozi/home/home?targetIndex=5",
});
},
},
};
</script>
<style lang="scss" scoped>
.main-swiper {
width: 100%;
height: 100vh;
}
.page-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
position: relative;
overflow: hidden;
width: 100%;
}
.bg-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.layer-img1 {
width: 500rpx;
z-index: 2;
margin-right: 180rpx;
margin-top: 50rpx;
}
.layer-img2 {
z-index: 2;
position: absolute;
bottom: 18%;
left: 0;
width: 100%;
height: 350rpx;
}
.content-layer {
margin: 130rpx 0;
width: 100%;
height: 100%;
display: flex;
justify-content: flex-end;
}
.layer-img3 {
width: 118rpx;
height: 69rpx;
z-index: 2;
position: absolute;
top: 238rpx;
right: 58rpx;
}
.layer-img2 {
width: 696rpx;
height: 302rpx;
z-index: 2;
position: absolute;
top: 200rpx;
left: 35rpx;
}
.layer-img4 {
z-index: 2;
width: 400rpx;
height: 400rpx;
margin-top: 400rpx;
margin-left: 80rpx;
}
.layer-img5 {
z-index: 2;
position: absolute;
bottom: 90rpx;
right: 30rpx;
width: 320rpx;
height: 500rpx;
}
.back-btn {
position: absolute;
top: 50rpx;
left: 50rpx;
z-index: 2;
background-color: rgb(0 0 0 / 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.hidden {
opacity: 0;
}
.slide-in-from-left {
animation: slideInLeft 1.2s ease-out forwards;
}
@keyframes slideInLeft {
0% {
opacity: 0;
transform: translateX(-100px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
.slide-in-from-right {
animation: slideInRight 1.2s ease-out forwards;
}
.blink {
animation: blink 1.5s infinite;
}
@keyframes slideInRight {
0% {
opacity: 0;
transform: translateX(100px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
@keyframes blink {
0%,
50% {
opacity: 1;
}
25%,
75% {
opacity: 0.3;
}
}
.fade-in {
animation: fadeIn 1s ease-in forwards;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
</style>

83
pig/chapter3/art.vue

@ -0,0 +1,83 @@
<template>
<view class="page-container">
<view class="header">
<view @click="goBack" class="back-btn">
<image
class="back-icon"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png"
mode="aspectFill"
></image>
</view>
</view>
<image
class="tag-image"
:src="showImg('/uploads/20250802/1f89c03f361dbcfe3f195f1cb14a92d3.png')"
mode="aspectFill"
></image>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
goBack() {
uni.navigateBack()
}
}
}
</script>
<style lang="scss" scoped>
.header {
display: flex;
align-items: center;
padding: 50rpx 30rpx 30rpx;
position: relative;
}
.back-btn {
background-color: rgba(255, 255, 255, 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.title {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 48rpx;
font-weight: bold;
color: white;
}
.tag-image {
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
top: 0;
}
.description {
text-align: center;
}
.desc-text {
font-size: 36rpx;
color: white;
line-height: 1.6;
}
</style>

84
pig/chapter3/brave.vue

@ -0,0 +1,84 @@
<template>
<view class="page-container">
<view class="header">
<view @click="goBack" class="back-btn">
<image
class="back-icon"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png"
mode="aspectFill"
></image>
</view>
</view>
<image
class="tag-image"
:src="showImg('/uploads/20250802/aa1669fbcb9177b4be1c8eed12fb4de0.png')"
mode="aspectFill"
></image>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
goBack() {
uni.navigateBack()
}
}
}
</script>
<style lang="scss" scoped>
.header {
display: flex;
align-items: center;
padding: 50rpx 30rpx 30rpx;
position: relative;
}
.back-btn {
background-color: rgba(255, 255, 255, 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.title {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 48rpx;
font-weight: bold;
color: white;
}
.tag-image {
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
top: 0;
}
.description {
text-align: center;
}
.desc-text {
font-size: 36rpx;
color: white;
line-height: 1.6;
}
</style>

426
pig/chapter3/chapter3.vue

@ -0,0 +1,426 @@
<template>
<view>
<swiper
class="main-swiper"
:vertical="true"
:current="currentIndex"
@change="handleSwiperChange"
:duration="300"
:style="{ height: '100vh' }"
>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[0]">
<image
v-show="shouldShowContent(0)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/62434ca7ee6b6457ea158b1860527085.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
<!-- 勇敢 -->
<view class="content-layer" v-show="shouldShowContent(0)">
<image
@click="navigateToTag('brave')"
:class="{
hidden: !animationStates[0],
'fade-in': animationStates[0],
breathe: animationStates[0],
}"
style="width: 84rpx;height: 125rpx;"
:src="
showImg(
'/uploads/20250802/053baeec3ce0c8e9908571b0fc890348.png'
)
"
:lazy-load="true"
mode="widthFix"
></image>
<!-- 神圣 -->
<image
@click="navigateToTag('sacred')"
:class="{
hidden: !animationStates[0],
'fade-in': animationStates[0],
breathe: animationStates[0],
}"
style="width: 84rpx;height: 125rpx;position: absolute;top: 70rpx;left: 400rpx;"
:src="
showImg(
'/uploads/20250802/39ce1cd11557c7e66ffa840fbc985d54.png'
)
"
:lazy-load="true"
mode="widthFix"
></image>
<!-- 卑微 -->
<image
@click="navigateToTag('humble')"
:class="{
hidden: !animationStates[0],
'fade-in': animationStates[0],
breathe: animationStates[0],
}"
style="width: 84rpx;height: 125rpx;position: absolute;top: 230rpx;left: 200rpx;"
:src="
showImg(
'/uploads/20250802/ab5045d22d549c688e084096c85b9d05.png'
)
"
:lazy-load="true"
mode="widthFix"
></image>
<!-- 艺术 -->
<image
@click="navigateToTag('art')"
:class="{
hidden: !animationStates[0],
'fade-in': animationStates[0],
breathe: animationStates[0],
}"
style="width: 84rpx;height: 125rpx;position: absolute;top: 430rpx;left: 420rpx;"
:src="
showImg(
'/uploads/20250802/a77fd06f3d03fa1254321b9549922875.png'
)
"
:lazy-load="true"
mode="widthFix"
></image>
<!-- 聪明 -->
<image
@click="navigateToTag('smart')"
:class="{
hidden: !animationStates[0],
'fade-in': animationStates[0],
breathe: animationStates[0],
}"
style="width: 84rpx;height: 125rpx;position: absolute;top: 630rpx;left: -20rpx;"
:src="
showImg(
'/uploads/20250802/d6e520506579d431daebccd8563c8750.png'
)
"
:lazy-load="true"
mode="widthFix"
></image>
<!-- -->
<image
@click="navigateToTag('stupid')"
:class="{
hidden: !animationStates[0],
'fade-in': animationStates[0],
breathe: animationStates[0],
}"
style="width: 84rpx;height: 125rpx;position: absolute;top: 760rpx;left: 220rpx;"
:src="
showImg(
'/uploads/20250802/2ee7e6be3e5115fa0da7eb66fbcb54c8.png'
)
"
:lazy-load="true"
mode="widthFix"
></image>
</view>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<image
style="width: 100%; height: 100%"
:src="
showImg('/uploads/20250802/c21b01fea9610f8069a768f03a173b66.png')
"
mode="aspectFill"
></image>
<image
@click="goChapter"
style="
width: 137rpx;
height: 108rpx;
position: absolute;
bottom: 125rpx;
left: 307rpx;
"
:src="
showImg('/uploads/20250802/165e072a1537b0fab14c6ec2f42e7974.png')
"
mode="aspectFill"
></image>
</view>
</swiper-item>
</swiper>
</view>
</template>
<script>
import TitleHeader from "@/components/TitleHeader.vue";
export default {
components: {
TitleHeader,
},
data() {
return {
currentIndex: 0,
loadedPages: {
0: false,
1: false,
2: false,
3: false,
4: false,
5: false,
6: false,
},
animationStates: {
0: false,
1: false,
2: false,
3: false,
4: false,
5: false,
6: false,
},
preloadBuffer: 1,
titleHeight: 0,
};
},
watch: {
currentIndex(newIndex) {
for (
let i = Math.max(0, newIndex - this.preloadBuffer);
i <= Math.min(9, newIndex + this.preloadBuffer);
i++
) {
this.loadedPages[i] = true;
}
},
},
mounted() {
this.titleHeight = uni.getStorageSync("titleHeight");
for (let i = 0; i <= Math.min(1 + this.preloadBuffer, 9); i++) {
this.loadedPages[i] = true;
}
setTimeout(() => {
this.animationStates[this.currentIndex] = true;
}, 50);
},
methods: {
goChapter() {
uni.navigateTo({
url: "/pig/chapter4/chapter4",
});
},
handleSwiperChange(e) {
const newIndex = e.detail.current;
this.currentIndex = newIndex;
this.animationStates[newIndex] = false;
setTimeout(() => {
this.animationStates[newIndex] = true;
}, 50);
},
shouldShowContent(index) {
return Math.abs(index - this.currentIndex) <= this.preloadBuffer;
},
goBack() {
uni.navigateTo({
url: "/taozi/home/home?targetIndex=5",
});
},
navigateToTag(tagName) {
uni.navigateTo({
url: `/pig/chapter3/${tagName}`,
});
},
},
};
</script>
<style lang="scss" scoped>
.main-swiper {
width: 100%;
height: 100vh;
}
.page-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
position: relative;
overflow: hidden;
width: 100%;
}
.bg-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.layer-img1 {
width: 500rpx;
z-index: 2;
margin-right: 180rpx;
margin-top: 50rpx;
}
.layer-img2 {
z-index: 2;
position: absolute;
bottom: 18%;
left: 0;
width: 100%;
height: 350rpx;
}
.content-layer {
position: absolute;
top: 245rpx;
left: 115rpx;
z-index: 9;
}
.layer-img3 {
width: 118rpx;
height: 69rpx;
z-index: 2;
position: absolute;
top: 238rpx;
right: 58rpx;
}
.layer-img2 {
width: 696rpx;
height: 302rpx;
z-index: 2;
position: absolute;
top: 200rpx;
left: 35rpx;
}
.layer-img4 {
z-index: 2;
width: 400rpx;
height: 400rpx;
margin-top: 400rpx;
margin-left: 80rpx;
}
.layer-img5 {
z-index: 2;
position: absolute;
bottom: 90rpx;
right: 30rpx;
width: 320rpx;
height: 500rpx;
}
.back-btn {
position: absolute;
top: 50rpx;
left: 50rpx;
z-index: 2;
background-color: rgb(0 0 0 / 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.hidden {
opacity: 0;
}
.slide-in-from-left {
animation: slideInLeft 1.2s ease-out forwards;
}
@keyframes slideInLeft {
0% {
opacity: 0;
transform: translateX(-100px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
.slide-in-from-right {
animation: slideInRight 1.2s ease-out forwards;
}
.blink {
animation: blink 1.5s infinite;
}
@keyframes slideInRight {
0% {
opacity: 0;
transform: translateX(100px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
@keyframes blink {
0%,
50% {
opacity: 1;
}
25%,
75% {
opacity: 0.3;
}
}
.fade-in {
animation: fadeIn 1s ease-in forwards;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.breathe {
animation: breathe 3s ease-in-out infinite;
}
@keyframes breathe {
0%, 100% {
transform: scale(1);
opacity: 0.8;
}
50% {
transform: scale(1.1);
opacity: 1;
}
}
</style>

83
pig/chapter3/humble.vue

@ -0,0 +1,83 @@
<template>
<view class="page-container">
<view class="header">
<view @click="goBack" class="back-btn">
<image
class="back-icon"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png"
mode="aspectFill"
></image>
</view>
</view>
<image
class="tag-image"
:src="showImg('/uploads/20250802/4acd9c894c2a464100ef21dae4d85652.png')"
mode="aspectFill"
></image>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
goBack() {
uni.navigateBack()
}
}
}
</script>
<style lang="scss" scoped>
.header {
display: flex;
align-items: center;
padding: 50rpx 30rpx 30rpx;
position: relative;
}
.back-btn {
background-color: rgba(255, 255, 255, 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.title {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 48rpx;
font-weight: bold;
color: white;
}
.tag-image {
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
top: 0;
}
.description {
text-align: center;
}
.desc-text {
font-size: 36rpx;
color: white;
line-height: 1.6;
}
</style>

84
pig/chapter3/sacred.vue

@ -0,0 +1,84 @@
<template>
<view class="page-container">
<view class="header">
<view @click="goBack" class="back-btn">
<image
class="back-icon"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png"
mode="aspectFill"
></image>
</view>
</view>
<image
class="tag-image"
:src="showImg('/uploads/20250802/590d1fc5594c8c2700eaf9e901af2cad.png')"
mode="aspectFill"
></image>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
goBack() {
uni.navigateBack()
}
}
}
</script>
<style lang="scss" scoped>
.header {
display: flex;
align-items: center;
padding: 50rpx 30rpx 30rpx;
position: relative;
}
.back-btn {
background-color: rgba(255, 255, 255, 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.title {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 48rpx;
font-weight: bold;
color: white;
}
.tag-image {
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
top: 0;
}
.description {
text-align: center;
}
.desc-text {
font-size: 36rpx;
color: white;
line-height: 1.6;
}
</style>

83
pig/chapter3/smart.vue

@ -0,0 +1,83 @@
<template>
<view class="page-container">
<view class="header">
<view @click="goBack" class="back-btn">
<image
class="back-icon"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png"
mode="aspectFill"
></image>
</view>
</view>
<image
class="tag-image"
:src="showImg('/uploads/20250802/1459fab5f195fa3ed6b17be8591a592d.png')"
mode="aspectFill"
></image>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
goBack() {
uni.navigateBack()
}
}
}
</script>
<style lang="scss" scoped>
.header {
display: flex;
align-items: center;
padding: 50rpx 30rpx 30rpx;
position: relative;
}
.back-btn {
background-color: rgba(255, 255, 255, 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.title {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 48rpx;
font-weight: bold;
color: white;
}
.tag-image {
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
top: 0;
}
.description {
text-align: center;
}
.desc-text {
font-size: 36rpx;
color: white;
line-height: 1.6;
}
</style>

83
pig/chapter3/stupid.vue

@ -0,0 +1,83 @@
<template>
<view class="page-container">
<view class="header">
<view @click="goBack" class="back-btn">
<image
class="back-icon"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png"
mode="aspectFill"
></image>
</view>
</view>
<image
class="tag-image"
:src="showImg('/uploads/20250802/c3d19d8a0b35d6acbcfd0a9748806951.png')"
mode="aspectFill"
></image>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
goBack() {
uni.navigateBack()
}
}
}
</script>
<style lang="scss" scoped>
.header {
display: flex;
align-items: center;
padding: 50rpx 30rpx 30rpx;
position: relative;
}
.back-btn {
background-color: rgba(255, 255, 255, 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.title {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 48rpx;
font-weight: bold;
color: white;
}
.tag-image {
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
top: 0;
}
.description {
text-align: center;
}
.desc-text {
font-size: 36rpx;
color: white;
line-height: 1.6;
}
</style>

644
pig/chapter4/chapter4.vue

@ -0,0 +1,644 @@
<template>
<view>
<swiper
class="main-swiper"
:vertical="true"
:current="currentIndex"
@change="handleSwiperChange"
:duration="300"
:style="{ height: '100vh' }"
>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[0]">
<image
v-show="shouldShowContent(0)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/85bba0ce5a8113fe6331f335a4cfd7f7.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[1]">
<image
v-show="shouldShowContent(1)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/0bd899a27fdbaf8a2c314faaefd7c320.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
<view class="content-layer" v-show="shouldShowContent(1)">
<image
class="layer-img2"
:class="{
hidden: !animationStates[1],
'fade-in': animationStates[1],
}"
:src="
showImg(
'/uploads/20250802/70cb6f2efde536bdde781ae387529a5c.png'
)
"
:lazy-load="true"
mode="widthFix"
></image>
</view>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[2]">
<image
v-show="shouldShowContent(2)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/cbe3db0c55a871383f86e34b781b5d33.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[3]">
<image
v-show="shouldShowContent(3)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/8499c31b1ed10693debd6e3eba37a841.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[4]">
<image
v-show="shouldShowContent(4)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/23fc62e1cd91bc373dbf7eb9e741721e.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[5]">
<image
v-show="shouldShowContent(5)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/863382a549c2d4e029c93eba5d040e96.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[6]">
<image
v-show="shouldShowContent(6)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/7a6bbf6e4d9cd869b94502bf9025caf1.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[7]">
<image
v-show="shouldShowContent(7)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/6f865d358eb9faf565bb0e63dd252a94.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
<view class="content-layer" v-show="shouldShowContent(7)">
<image
class="layer-img3"
:class="{
hidden: !animationStates[7],
'fade-in': animationStates[7],
}"
:src="
showImg(
'/uploads/20250802/13d7d6ad68f7171d48ef271c699fa333.png'
)
"
:lazy-load="true"
mode="widthFix"
></image>
<image
class="layer-img4"
:class="{
hidden: !animationStates[7],
'fade-in': animationStates[7],
}"
:src="
showImg(
'/uploads/20250802/dd49237235965bc83759e54ec895ce34.png'
)
"
:lazy-load="true"
mode="widthFix"
></image>
</view>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[8]">
<image
v-show="shouldShowContent(8)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/c4ef978fd763848b01c5dec92c032bdb.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
<view class="content-layer" v-show="shouldShowContent(8)">
<image
class="layer-img5"
:class="{
hidden: !animationStates[8],
'fade-in': animationStates[8],
}"
:src="
showImg(
'/uploads/20250802/c3a669862cca14212b130d6eb90380d6.png'
)
"
:lazy-load="true"
mode="widthFix"
></image>
<image
class="layer-img6"
:class="{
hidden: !animationStates[8],
'fade-in': animationStates[8],
}"
:src="
showImg(
'/uploads/20250802/afbc088293603b16fa99b2c0c10ff275.png'
)
"
:lazy-load="true"
mode="widthFix"
></image>
</view>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template v-if="loadedPages[9]">
<image
v-show="shouldShowContent(9)"
class="bg-image"
:src="
showImg(
'/uploads/20250802/4b2090a566500b5d633448d8607b464c.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template>
<image
class="bg-image"
:src="
showImg(
'/uploads/20250802/703df90d52ea3461b0e9743f1ca2c942.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template>
<image
class="bg-image"
:src="
showImg(
'/uploads/20250802/8448d3d99435377157000780017a9540.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</template>
</view>
</swiper-item>
<swiper-item>
<view class="page-container">
<template>
<view
class=""
style="width: 750rpx; height: 1400rpx; position: relative"
>
<image
class="bg-image"
:src="
showImg(
'/uploads/20250802/c6cec7ca05b3804d0d26b701b40ff9d6.png'
)
"
:lazy-load="true"
mode="aspectFit"
></image>
<view
class=""
style="
position: absolute;
bottom: 120rpx;
width: 546rpx;
left: 104rpx;
z-index: 9;
"
>
<image
@click="navigateToPage('first')"
style="width: 260rpx; height: 50rpx"
:src="
showImg(
'/uploads/20250802/22d4d2a0b442aa8269b3c393cc1bc0fd.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
<image
@click="navigateToPage('second')"
style="width: 260rpx; height: 50rpx; margin-left: 26rpx"
:src="
showImg(
'/uploads/20250802/6579d29fbfc61c355bfee74775d9404f.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
<image
@click="navigateToPage('third')"
style="width: 260rpx; height: 50rpx; margin-top: 30rpx"
:src="
showImg(
'/uploads/20250802/19946ac0a0c6bdeae627d0d3a6fb3dbc.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
<image
@click="navigateToPage('fourth')"
style="
width: 260rpx;
height: 50rpx;
margin-left: 26rpx;
margin-top: 30rpx;
"
:src="
showImg(
'/uploads/20250802/7e0ce35e13fa118deaf70240357faf14.png'
)
"
:lazy-load="true"
mode="aspectFill"
></image>
</view>
</view>
</template>
</view>
</swiper-item>
</swiper>
</view>
</template>
<script>
import TitleHeader from "@/components/TitleHeader.vue";
export default {
components: {
TitleHeader,
},
data() {
return {
currentIndex: 0,
loadedPages: {
0: false,
1: false,
2: false,
3: false,
4: false,
5: false,
6: false,
7: false,
8: false,
9: false,
10: false,
},
animationStates: {
0: false,
1: false,
2: false,
3: false,
4: false,
5: false,
6: false,
7: false,
8: false,
9: false,
10: false,
},
preloadBuffer: 1,
titleHeight: 0,
};
},
watch: {
currentIndex(newIndex) {
for (
let i = Math.max(0, newIndex - this.preloadBuffer);
i <= Math.min(9, newIndex + this.preloadBuffer);
i++
) {
this.loadedPages[i] = true;
}
},
},
mounted() {
this.titleHeight = uni.getStorageSync("titleHeight");
for (let i = 0; i <= Math.min(1 + this.preloadBuffer, 9); i++) {
this.loadedPages[i] = true;
}
setTimeout(() => {
this.animationStates[this.currentIndex] = true;
}, 50);
},
methods: {
goChapter() {
uni.navigateTo({
url: "/pig/chapter3/chapter3",
});
},
handleSwiperChange(e) {
const newIndex = e.detail.current;
this.currentIndex = newIndex;
this.animationStates[newIndex] = false;
setTimeout(() => {
this.animationStates[newIndex] = true;
}, 50);
},
shouldShowContent(index) {
return Math.abs(index - this.currentIndex) <= this.preloadBuffer;
},
goBack() {
uni.navigateTo({
url: "/taozi/home/home?targetIndex=5",
});
},
navigateToPage(pageName) {
uni.navigateTo({
url: `/pig/chapter4/${pageName}`,
});
},
},
};
</script>
<style lang="scss" scoped>
.main-swiper {
width: 100%;
height: 100vh;
}
.page-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
position: relative;
overflow: hidden;
width: 100%;
background-color: #efefef;
}
.bg-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.layer-img1 {
width: 500rpx;
z-index: 2;
margin-right: 180rpx;
margin-top: 50rpx;
}
.layer-img2 {
z-index: 2;
position: absolute;
bottom: 18%;
left: 0;
width: 100%;
height: 350rpx;
}
.content-layer {
margin: 130rpx 0;
width: 100%;
height: 100%;
display: flex;
justify-content: flex-end;
}
.layer-img3 {
width: 327rpx;
height: 270rpx;
z-index: 2;
position: absolute;
top: 114rpx;
left: 82rpx;
}
.layer-img2 {
width: 696rpx;
height: 302rpx;
z-index: 2;
position: absolute;
top: 200rpx;
left: 35rpx;
}
.layer-img4 {
z-index: 2;
width: 530rpx;
height: 409rpx;
bottom: 130rpx;
left: 91rpx;
position: absolute;
}
.layer-img5 {
z-index: 2;
position: absolute;
top: 151rpx;
left: 95rpx;
width: 382rpx;
height: 452rpx;
}
.layer-img6 {
z-index: 2;
position: absolute;
bottom: 163rpx;
left: 95rpx;
width: 261rpx;
height: 268rpx;
}
.back-btn {
position: absolute;
top: 50rpx;
left: 50rpx;
z-index: 2;
background-color: rgb(0 0 0 / 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.hidden {
opacity: 0;
}
.slide-in-from-left {
animation: slideInLeft 1.2s ease-out forwards;
}
@keyframes slideInLeft {
0% {
opacity: 0;
transform: translateX(-100px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
.slide-in-from-right {
animation: slideInRight 1.2s ease-out forwards;
}
.blink {
animation: blink 1.5s infinite;
}
@keyframes slideInRight {
0% {
opacity: 0;
transform: translateX(100px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
@keyframes blink {
0%,
50% {
opacity: 1;
}
25%,
75% {
opacity: 0.3;
}
}
.fade-in {
animation: fadeIn 1s ease-in forwards;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
</style>

109
pig/chapter4/first.vue

@ -0,0 +1,109 @@
<template>
<view class="page-container">
<view class="header">
<view @click="goBack" class="back-btn">
<image
class="back-icon"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png"
mode="aspectFill"
></image>
</view>
</view>
<image
class="tag-image"
:src="showImg('/uploads/20250802/4855b66aeecba79f1f404a015c727955.png')"
mode="aspectFill"
></image>
<image
style="
width: 361rpx;
position: absolute;
z-index: 2;
top: 355rpx;
left: 190rpx;
"
:src="showImg('/uploads/20250802/88de82efaf2c8f886b831a0766236ffa.png')"
mode="widthFix"
></image>
<image
@click="toBuy"
style="
position: absolute;
bottom: 217rpx;
width: 456rpx;
left: 146rpx;
z-index: 9;
"
:src="showImg('/uploads/20250802/bc8c6d0f121669388d93ccf5494c7f47.png')"
mode="widthFix"
></image>
</view>
</template>
<script>
export default {
data() {
return {};
},
methods: {
toBuy() {
uni.navigateTo({
url: "./secBuy?type=1",
});
},
goBack() {
uni.navigateBack();
},
},
};
</script>
<style lang="scss" scoped>
.header {
display: flex;
align-items: center;
padding: 50rpx 30rpx 30rpx;
position: relative;
}
.back-btn {
background-color: rgba(255, 255, 255, 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.title {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 48rpx;
font-weight: bold;
color: white;
}
.tag-image {
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
top: 0;
}
.description {
text-align: center;
}
.desc-text {
font-size: 36rpx;
color: white;
line-height: 1.6;
}
</style>

109
pig/chapter4/fourth.vue

@ -0,0 +1,109 @@
<template>
<view class="page-container">
<view class="header">
<view @click="goBack" class="back-btn">
<image
class="back-icon"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png"
mode="aspectFill"
></image>
</view>
</view>
<image
class="tag-image"
:src="showImg('/uploads/20250802/7ae3b8496972e4786109ea94c8495458.png')"
mode="aspectFill"
></image>
<image
style="
width: 361rpx;
position: absolute;
z-index: 2;
top: 355rpx;
left: 190rpx;
"
:src="showImg('/uploads/20250802/43e0745f7aa490c80dee88d6394ef35b.png')"
mode="widthFix"
></image>
<image
@click="toBuy"
style="
position: absolute;
bottom: 217rpx;
width: 456rpx;
left: 146rpx;
z-index: 9;
"
:src="showImg('/uploads/20250802/a0c7c45de62ec0d5bd6163b30932e1e3.png')"
mode="widthFix"
></image>
</view>
</template>
<script>
export default {
data() {
return {};
},
methods: {
toBuy() {
uni.navigateTo({
url: "./secBuy?type=4",
});
},
goBack() {
uni.navigateBack();
},
},
};
</script>
<style lang="scss" scoped>
.header {
display: flex;
align-items: center;
padding: 50rpx 30rpx 30rpx;
position: relative;
}
.back-btn {
background-color: rgba(255, 255, 255, 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.title {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 48rpx;
font-weight: bold;
color: white;
}
.tag-image {
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
top: 0;
}
.description {
text-align: center;
}
.desc-text {
font-size: 36rpx;
color: white;
line-height: 1.6;
}
</style>

155
pig/chapter4/secBuy.vue

@ -0,0 +1,155 @@
<template>
<view class="page-container">
<view class="header">
<view @click="goBack" class="back-btn">
<image
class="back-icon"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png"
mode="aspectFill"
></image>
</view>
</view>
<image
v-if="type"
class="tag-image"
:src="showImg(imgMap[type].bg)"
mode="aspectFill"
></image>
<image
v-if="type"
style="position: absolute; z-index: 9; bottom: 521rpx"
:style="{
width: imgMap[type].width,
left: imgMap[type].left,
}"
:src="showImg(imgMap[type].title)"
mode="widthFix"
></image>
<image
style="
position: absolute;
z-index: 9;
left: 72rpx;
bottom: 178rpx;
width: 605rpx;
height: 66rpx;
"
:src="showImg('/uploads/20250802/1b853d1f8d147368ef9d0ba35df9e5c3.png')"
mode="aspectFill"
></image>
<image
@click="goBackChange"
style="
position: absolute;
z-index: 9;
left: 72rpx;
bottom: 84rpx;
width: 605rpx;
height: 66rpx;
"
:src="showImg('/uploads/20250802/b458d05790345ec9ae9a3bea23495b46.png')"
mode="aspectFill"
></image>
</view>
</template>
<script>
export default {
data() {
return {
type: 1,
imgMap: {
1: {
bg: "/uploads/20250802/7ff759d15338ba690573602be45a72d2.png",
title: "/uploads/20250802/152dc5b77ad0af50f92c4cb0dbd7aef5.png",
width: "467rpx",
left: "140rpx",
},
2: {
bg: "/uploads/20250802/98cf261fb1e09be491e084a67b939dbe.png",
title: "/uploads/20250802/798a5053842969643caee2f482ce6c09.png",
width: "511rpx",
left: "119rpx",
},
3: {
bg: "/uploads/20250802/b04ffee53c537e35aa5f7ad98d21b297.png",
title: "/uploads/20250802/0a90c67dc32bf30caaca5e85039df174.png",
width: "441rpx",
left: "154rpx",
},
4: {
bg: "/uploads/20250802/b7ce92c7d9d7d1349fa82ac81625d2cf.png",
title: "/uploads/20250802/e66ab85e23d2d9a03efc5d9cdd0735ba.png",
width: "597rpx",
left: "77rpx",
},
},
};
},
onLoad(options) {
this.type = Number(options.type);
console.log(this.imgMap[this.type], "---");
},
methods: {
goBack() {
uni.navigateBack();
},
goBackChange() {
uni.navigateBack({
delta: 2,
});
},
},
};
</script>
<style lang="scss" scoped>
.header {
display: flex;
align-items: center;
padding: 50rpx 30rpx 30rpx;
position: relative;
}
.back-btn {
background-color: rgba(255, 255, 255, 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.title {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 48rpx;
font-weight: bold;
color: white;
}
.tag-image {
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
top: 0;
}
.description {
text-align: center;
}
.desc-text {
font-size: 36rpx;
color: white;
line-height: 1.6;
}
</style>

109
pig/chapter4/second.vue

@ -0,0 +1,109 @@
<template>
<view class="page-container">
<view class="header">
<view @click="goBack" class="back-btn">
<image
class="back-icon"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png"
mode="aspectFill"
></image>
</view>
</view>
<image
class="tag-image"
:src="showImg('/uploads/20250802/7f125fdb8a2c2ab9c881d6f8fc6f2041.png')"
mode="aspectFill"
></image>
<image
style="
width: 361rpx;
position: absolute;
z-index: 2;
top: 355rpx;
left: 190rpx;
"
:src="showImg('/uploads/20250802/928796306484f1fa101ec113f7e94453.png')"
mode="widthFix"
></image>
<image
@click="toBuy"
style="
position: absolute;
bottom: 217rpx;
width: 456rpx;
left: 146rpx;
z-index: 9;
"
:src="showImg('/uploads/20250802/92779fd82f7c0c0358ca453fd3071e7b.png')"
mode="widthFix"
></image>
</view>
</template>
<script>
export default {
data() {
return {};
},
methods: {
toBuy() {
uni.navigateTo({
url: "./secBuy?type=2",
});
},
goBack() {
uni.navigateBack();
},
},
};
</script>
<style lang="scss" scoped>
.header {
display: flex;
align-items: center;
padding: 50rpx 30rpx 30rpx;
position: relative;
}
.back-btn {
background-color: rgba(255, 255, 255, 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.title {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 48rpx;
font-weight: bold;
color: white;
}
.tag-image {
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
top: 0;
}
.description {
text-align: center;
}
.desc-text {
font-size: 36rpx;
color: white;
line-height: 1.6;
}
</style>

109
pig/chapter4/third.vue

@ -0,0 +1,109 @@
<template>
<view class="page-container">
<view class="header">
<view @click="goBack" class="back-btn">
<image
class="back-icon"
src="https://static.ticket.sz-trip.com/epicSoul/taozi/back.png"
mode="aspectFill"
></image>
</view>
</view>
<image
class="tag-image"
:src="showImg('/uploads/20250802/4ebbbcdd49f7ee5add822d22e4071b1c.png')"
mode="aspectFill"
></image>
<image
style="
width: 561rpx;
position: absolute;
z-index: 2;
bottom: 463rpx;
left: 97rpx;
"
:src="showImg('/uploads/20250802/74e49ad04e83921783fcc2072677da88.png')"
mode="widthFix"
></image>
<image
@click="toBuy"
style="
position: absolute;
bottom: 217rpx;
width: 456rpx;
left: 146rpx;
z-index: 9;
"
:src="showImg('/uploads/20250802/bc5905a9ddebeb3833429c95b9b0d967.png')"
mode="widthFix"
></image>
</view>
</template>
<script>
export default {
data() {
return {};
},
methods: {
toBuy() {
uni.navigateTo({
url: "./secBuy?type=3",
});
},
goBack() {
uni.navigateBack();
},
},
};
</script>
<style lang="scss" scoped>
.header {
display: flex;
align-items: center;
padding: 50rpx 30rpx 30rpx;
position: relative;
}
.back-btn {
background-color: rgba(255, 255, 255, 0.3);
border-radius: 50%;
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
width: 50rpx;
height: 50rpx;
}
.title {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 48rpx;
font-weight: bold;
color: white;
}
.tag-image {
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
top: 0;
}
.description {
text-align: center;
}
.desc-text {
font-size: 36rpx;
color: white;
line-height: 1.6;
}
</style>

1005
pig/home/home.vue

File diff suppressed because it is too large

24
uni_modules/uni-transition/components/uni-transition/createAnimation.js

@ -124,7 +124,29 @@ animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
})
export function createAnimation(option, _this) {
if(!_this) return
if(!_this) {
console.warn('uni-transition: _this parameter is undefined, returning empty animation object')
// 创建一个完整的空动画对象,确保所有方法都返回自身以支持链式调用
const emptyAnimation = {}
// 添加step和run方法
emptyAnimation.step = function(config = {}) {
return emptyAnimation
}
emptyAnimation.run = function(fn) {
typeof fn === 'function' && fn()
return emptyAnimation
}
// 添加所有动画类型方法
const allAnimateTypes = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
'translateZ', 'opacity', 'backgroundColor', 'width', 'height', 'left', 'right', 'top', 'bottom']
allAnimateTypes.forEach(type => {
emptyAnimation[type] = function(...args) {
return emptyAnimation
}
})
return emptyAnimation
}
clearTimeout(_this.timer)
return new MPAnimation(option, _this)
}

597
uni_modules/uni-transition/components/uni-transition/uni-transition.vue

@ -1,13 +1,21 @@
<template>
<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
<view
v-if="isShow"
ref="ani"
:animation="animationData"
:class="customClass"
:style="transformStyles"
@click="onClick"
><slot></slot
></view>
</template>
<script>
// #ifndef MP-WEIXIN
import { createAnimation } from './createAnimation'
import { createAnimation } from "./createAnimation";
// #endif
// #ifdef MP-WEIXIN
const createAnimation = require('./createAnimation.js').createAnimation
const createAnimation = require("./createAnimation.js").createAnimation;
// #endif
/**
@ -27,293 +35,304 @@ const createAnimation = require('./createAnimation.js').createAnimation
* @property {Object} styles 组件样式 css 样式注意带-连接符的属性需要使用小驼峰写法如`backgroundColor:red`
*/
export default {
name: 'uniTransition',
emits:['click','change'],
props: {
show: {
type: Boolean,
default: false
},
modeClass: {
type: [Array, String],
default() {
return 'fade'
}
},
duration: {
type: Number,
default: 300
},
styles: {
type: Object,
default() {
return {}
}
},
customClass:{
type: String,
default: ''
}
},
data() {
return {
isShow: false,
transform: '',
opacity: 1,
animationData: {},
durationTime: 300,
config: {}
}
},
watch: {
show: {
handler(newVal) {
if (newVal) {
this.open()
} else {
// close,
if (this.isShow) {
this.close()
}
}
},
immediate: true
}
},
computed: {
//
stylesObject() {
let styles = {
...this.styles,
'transition-duration': this.duration / 1000 + 's'
}
let transform = ''
for (let i in styles) {
let line = this.toLine(i)
transform += line + ':' + styles[i] + ';'
}
return transform
},
//
transformStyles() {
return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
}
},
created() {
//
this.config = {
duration: this.duration,
timingFunction: 'ease',
transformOrigin: '50% 50%',
delay: 0
}
this.durationTime = this.duration
},
methods: {
/**
* ref 触发 初始化动画
*/
init(obj = {}) {
if (obj.duration) {
this.durationTime = obj.duration
}
this.animation = createAnimation(Object.assign(this.config, obj),this)
},
/**
* 点击组件触发回调
*/
onClick() {
this.$emit('click', {
detail: this.isShow
})
},
/**
* ref 触发 动画分组
* @param {Object} obj
*/
step(obj, config = {}) {
if (!this.animation) return this
for (let i in obj) {
try {
if (this.animation && typeof this.animation[i] === 'function') {
if(typeof obj[i] === 'object'){
this.animation[i](...obj[i])
}else{
this.animation[i](obj[i])
}
}
} catch (e) {
console.error(`方法 ${i} 不存在:`, e)
}
}
try {
if (this.animation && typeof this.animation.step === 'function') {
this.animation.step(config)
}
} catch (e) {
console.error('动画step执行错误:', e)
}
return this
},
/**
* ref 触发 执行动画
*/
run(fn) {
if (!this.animation) return
try {
if (this.animation && typeof this.animation.run === 'function') {
this.animation.run(fn)
}
} catch (e) {
console.error('动画执行错误:', e)
}
},
//
open() {
clearTimeout(this.timer)
this.transform = ''
this.isShow = true
let { opacity, transform } = this.styleInit(false)
if (typeof opacity !== 'undefined') {
this.opacity = opacity
}
this.transform = transform
// nextTick wx
this.$nextTick(() => {
// TODO
this.timer = setTimeout(() => {
try {
this.animation = createAnimation(this.config, this)
if (this.animation) {
let result = this.tranfromInit(false)
if (result && typeof result.step === 'function') {
result.step()
if (typeof result.run === 'function') {
result.run()
}
}
}
} catch (e) {
console.error('动画初始化错误:', e)
}
this.$emit('change', {
detail: this.isShow
})
}, 20)
})
},
//
close(type) {
if (!this.animation) return
try {
let result = this.tranfromInit(true)
if (result && typeof result.step === 'function') {
result.step()
if (typeof result.run === 'function') {
result.run(() => {
this.isShow = false
this.animationData = null
this.animation = null
let { opacity, transform } = this.styleInit(false)
this.opacity = opacity || 1
this.transform = transform
this.$emit('change', {
detail: this.isShow
})
})
}
}
} catch (e) {
console.error('动画关闭错误:', e)
}
},
//
styleInit(type) {
let styles = {
transform: ''
}
let buildStyle = (type, mode) => {
if (mode === 'fade') {
styles.opacity = this.animationType(type)[mode]
} else {
styles.transform += this.animationType(type)[mode] + ' '
}
}
if (typeof this.modeClass === 'string') {
buildStyle(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildStyle(type, mode)
})
}
return styles
},
//
tranfromInit(type) {
if (!this.animation) return this
let buildTranfrom = (type, mode) => {
let aniNum = null
if (mode === 'fade') {
aniNum = type ? 0 : 1
} else {
aniNum = type ? '-100%' : '0'
if (mode === 'zoom-in') {
aniNum = type ? 0.8 : 1
}
if (mode === 'zoom-out') {
aniNum = type ? 1.2 : 1
}
if (mode === 'slide-right') {
aniNum = type ? '100%' : '0'
}
if (mode === 'slide-bottom') {
aniNum = type ? '100%' : '0'
}
}
let methodName = this.animationMode()[mode]
if (this.animation && typeof this.animation[methodName] === 'function') {
this.animation[methodName](aniNum)
}
}
if (typeof this.modeClass === 'string') {
buildTranfrom(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildTranfrom(type, mode)
})
}
name: "uniTransition",
emits: ["click", "change"],
props: {
show: {
type: Boolean,
default: false,
},
modeClass: {
type: [Array, String],
default() {
return "fade";
},
},
duration: {
type: Number,
default: 300,
},
styles: {
type: Object,
default() {
return {};
},
},
customClass: {
type: String,
default: "",
},
},
data() {
return {
isShow: false,
transform: "",
opacity: 1,
animationData: {},
durationTime: 300,
config: {},
};
},
watch: {
show: {
handler(newVal) {
if (newVal) {
this.open();
} else {
// close,
if (this.isShow) {
this.close();
}
}
},
immediate: true,
},
},
computed: {
//
stylesObject() {
let styles = {
...this.styles,
"transition-duration": this.duration / 1000 + "s",
};
let transform = "";
for (let i in styles) {
let line = this.toLine(i);
transform += line + ":" + styles[i] + ";";
}
return transform;
},
//
transformStyles() {
return (
"transform:" +
this.transform +
";" +
"opacity:" +
this.opacity +
";" +
this.stylesObject
);
},
},
created() {
//
this.config = {
duration: this.duration,
timingFunction: "ease",
transformOrigin: "50% 50%",
delay: 0,
};
this.durationTime = this.duration;
},
methods: {
/**
* ref 触发 初始化动画
*/
init(obj = {}) {
if (obj.duration) {
this.durationTime = obj.duration;
}
this.animation = createAnimation(Object.assign(this.config, obj), this);
},
/**
* 点击组件触发回调
*/
onClick() {
this.$emit("click", {
detail: this.isShow,
});
},
/**
* ref 触发 动画分组
* @param {Object} obj
*/
step(obj, config = {}) {
if (!this.animation) return this;
for (let i in obj) {
try {
if (this.animation && typeof this.animation[i] === "function") {
if (typeof obj[i] === "object") {
this.animation[i](...obj[i]);
} else {
this.animation[i](obj[i]);
}
}
} catch (e) {
console.error(`方法 ${i} 不存在:`, e);
}
}
try {
if (this.animation && typeof this.animation.step === "function") {
this.animation.step(config);
}
} catch (e) {
console.error("动画step执行错误:", e);
}
return this;
},
/**
* ref 触发 执行动画
*/
run(fn) {
if (!this.animation) return;
try {
if (this.animation && typeof this.animation.run === "function") {
this.animation.run(fn);
}
} catch (e) {
console.error("动画执行错误:", e);
}
},
//
open() {
clearTimeout(this.timer);
this.transform = "";
this.isShow = true;
let { opacity, transform } = this.styleInit(false);
if (typeof opacity !== "undefined") {
this.opacity = opacity;
}
this.transform = transform;
// nextTick wx
this.$nextTick(() => {
// TODO
this.timer = setTimeout(() => {
try {
this.animation = createAnimation(this.config, this);
if (this.animation) {
let result = this.tranfromInit(false);
if (result && typeof result.step === "function") {
result.step();
if (typeof result.run === "function") {
result.run();
}
}
}
} catch (e) {
console.error("动画初始化错误:", e);
}
this.$emit("change", {
detail: this.isShow,
});
}, 20);
});
},
//
close(type) {
if (!this.animation) return;
try {
let result = this.tranfromInit(true);
if (result && typeof result.step === "function") {
result.step();
if (typeof result.run === "function") {
result.run(() => {
this.isShow = false;
this.animationData = null;
this.animation = null;
let { opacity, transform } = this.styleInit(false);
this.opacity = opacity || 1;
this.transform = transform;
this.$emit("change", {
detail: this.isShow,
});
});
}
}
} catch (e) {
console.error("动画关闭错误:", e);
}
},
//
styleInit(type) {
let styles = {
transform: "",
};
let buildStyle = (type, mode) => {
if (mode === "fade") {
styles.opacity = this.animationType(type)[mode];
} else {
styles.transform += this.animationType(type)[mode] + " ";
}
};
if (typeof this.modeClass === "string") {
buildStyle(type, this.modeClass);
} else {
this.modeClass.forEach((mode) => {
buildStyle(type, mode);
});
}
return styles;
},
//
tranfromInit(type) {
if (!this.animation) return this;
let buildTranfrom = (type, mode) => {
let aniNum = null;
if (mode === "fade") {
aniNum = type ? 0 : 1;
} else {
aniNum = type ? "-100%" : "0";
if (mode === "zoom-in") {
aniNum = type ? 0.8 : 1;
}
if (mode === "zoom-out") {
aniNum = type ? 1.2 : 1;
}
if (mode === "slide-right") {
aniNum = type ? "100%" : "0";
}
if (mode === "slide-bottom") {
aniNum = type ? "100%" : "0";
}
}
let methodName = this.animationMode()[mode];
if (
this.animation &&
typeof this.animation[methodName] === "function"
) {
this.animation[methodName](aniNum);
}
};
if (typeof this.modeClass === "string") {
buildTranfrom(type, this.modeClass);
} else {
this.modeClass.forEach((mode) => {
buildTranfrom(type, mode);
});
}
return this.animation
},
animationType(type) {
return {
fade: type ? 1 : 0,
'slide-top': `translateY(${type ? '0' : '-100%'})`,
'slide-right': `translateX(${type ? '0' : '100%'})`,
'slide-bottom': `translateY(${type ? '0' : '100%'})`,
'slide-left': `translateX(${type ? '0' : '-100%'})`,
'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
}
},
//
animationMode() {
return {
fade: 'opacity',
'slide-top': 'translateY',
'slide-right': 'translateX',
'slide-bottom': 'translateY',
'slide-left': 'translateX',
'zoom-in': 'scale',
'zoom-out': 'scale'
}
},
// 线
toLine(name) {
return name.replace(/([A-Z])/g, '-$1').toLowerCase()
}
}
}
return this.animation;
},
animationType(type) {
return {
fade: type ? 1 : 0,
"slide-top": `translateY(${type ? "0" : "-100%"})`,
"slide-right": `translateX(${type ? "0" : "100%"})`,
"slide-bottom": `translateY(${type ? "0" : "100%"})`,
"slide-left": `translateX(${type ? "0" : "-100%"})`,
"zoom-in": `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
"zoom-out": `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`,
};
},
//
animationMode() {
return {
fade: "opacity",
"slide-top": "translateY",
"slide-right": "translateX",
"slide-bottom": "translateY",
"slide-left": "translateX",
"zoom-in": "scale",
"zoom-out": "scale",
};
},
// 线
toLine(name) {
return name.replace(/([A-Z])/g, "-$1").toLowerCase();
},
},
};
</script>
<style></style>

373
uni_modules/uni-transition/components/uni-transition/uni-transition_BACKUP_472.vue

@ -0,0 +1,373 @@
<template>
<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
</template>
<script>
// #ifndef MP-WEIXIN
import { createAnimation } from './createAnimation'
// #endif
// #ifdef MP-WEIXIN
const createAnimation = require('./createAnimation.js').createAnimation
// #endif
/**
* Transition 过渡动画
* @description 简单过渡动画组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
* @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
* @value fade 渐隐渐出过渡
* @value slide-top 由上至下过渡
* @value slide-right 由右至左过渡
* @value slide-bottom 由下至上过渡
* @value slide-left 由左至右过渡
* @value zoom-in 由小到大过渡
* @value zoom-out 由大到小过渡
* @property {Number} duration 过渡动画持续时间
* @property {Object} styles 组件样式 css 样式注意带-连接符的属性需要使用小驼峰写法如`backgroundColor:red`
*/
export default {
name: 'uniTransition',
emits:['click','change'],
props: {
show: {
type: Boolean,
default: false
},
modeClass: {
type: [Array, String],
default() {
return 'fade'
}
},
duration: {
type: Number,
default: 300
},
styles: {
type: Object,
default() {
return {}
}
},
customClass:{
type: String,
default: ''
}
},
data() {
return {
isShow: false,
transform: '',
opacity: 1,
animationData: {},
durationTime: 300,
config: {}
}
},
watch: {
show: {
handler(newVal) {
if (newVal) {
this.open()
} else {
// close,
if (this.isShow) {
this.close()
}
}
},
immediate: true
}
},
computed: {
//
stylesObject() {
let styles = {
...this.styles,
'transition-duration': this.duration / 1000 + 's'
}
let transform = ''
for (let i in styles) {
let line = this.toLine(i)
transform += line + ':' + styles[i] + ';'
}
return transform
},
//
transformStyles() {
return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
}
},
created() {
//
this.config = {
duration: this.duration,
timingFunction: 'ease',
transformOrigin: '50% 50%',
delay: 0
}
this.durationTime = this.duration
},
methods: {
/**
* ref 触发 初始化动画
*/
init(obj = {}) {
if (obj.duration) {
this.durationTime = obj.duration
}
this.animation = createAnimation(Object.assign(this.config, obj),this)
},
/**
* 点击组件触发回调
*/
onClick() {
this.$emit('click', {
detail: this.isShow
})
},
/**
* ref 触发 动画分组
* @param {Object} obj
*/
step(obj, config = {}) {
<<<<<<< HEAD
if (!this.animation) return this
=======
if (!this.animation || typeof this.animation.step !== 'function') return this
>>>>>>> dev_pig
for (let i in obj) {
try {
if (this.animation && typeof this.animation[i] === 'function') {
if(typeof obj[i] === 'object'){
this.animation[i](...obj[i])
}else{
this.animation[i](obj[i])
}
}
} catch (e) {
console.error(`方法 ${i} 不存在:`, e)
}
}
try {
if (this.animation && typeof this.animation.step === 'function') {
this.animation.step(config)
}
} catch (e) {
console.error('动画step执行错误:', e)
}
return this
},
/**
* ref 触发 执行动画
*/
run(fn) {
<<<<<<< HEAD
if (!this.animation) return
try {
if (this.animation && typeof this.animation.run === 'function') {
this.animation.run(fn)
}
} catch (e) {
console.error('动画执行错误:', e)
}
=======
if (!this.animation || typeof this.animation.run !== 'function') return
this.animation.run(fn)
>>>>>>> dev_pig
},
//
open() {
clearTimeout(this.timer)
this.transform = ''
this.isShow = true
let { opacity, transform } = this.styleInit(false)
if (typeof opacity !== 'undefined') {
this.opacity = opacity
}
this.transform = transform
// nextTick wx
this.$nextTick(() => {
// TODO
this.timer = setTimeout(() => {
try {
this.animation = createAnimation(this.config, this)
<<<<<<< HEAD
if (this.animation) {
let result = this.tranfromInit(false)
if (result && typeof result.step === 'function') {
result.step()
if (typeof result.run === 'function') {
result.run()
}
}
}
} catch (e) {
console.error('动画初始化错误:', e)
=======
if (this.animation && typeof this.animation.step === 'function' && typeof this.animation.run === 'function') {
const result = this.tranfromInit(false)
if (result && typeof result.step === 'function') {
result.step()
if (typeof this.animation.run === 'function') {
this.animation.run()
}
}
}
} catch (error) {
console.error('uni-transition animation error:', error)
>>>>>>> dev_pig
}
this.$emit('change', {
detail: this.isShow
})
}, 20)
})
},
//
close(type) {
<<<<<<< HEAD
if (!this.animation) return
try {
let result = this.tranfromInit(true)
=======
if (!this.animation || typeof this.animation.step !== 'function' || typeof this.animation.run !== 'function') return
try {
const result = this.tranfromInit(true)
>>>>>>> dev_pig
if (result && typeof result.step === 'function') {
result.step()
if (typeof result.run === 'function') {
result.run(() => {
this.isShow = false
this.animationData = null
this.animation = null
let { opacity, transform } = this.styleInit(false)
this.opacity = opacity || 1
this.transform = transform
this.$emit('change', {
detail: this.isShow
})
})
}
}
<<<<<<< HEAD
} catch (e) {
console.error('动画关闭错误:', e)
=======
} catch (error) {
console.error('uni-transition close animation error:', error)
//
this.isShow = false
this.animationData = null
this.animation = null
this.$emit('change', {
detail: this.isShow
})
>>>>>>> dev_pig
}
},
//
styleInit(type) {
let styles = {
transform: ''
}
let buildStyle = (type, mode) => {
if (mode === 'fade') {
styles.opacity = this.animationType(type)[mode]
} else {
styles.transform += this.animationType(type)[mode] + ' '
}
}
if (typeof this.modeClass === 'string') {
buildStyle(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildStyle(type, mode)
})
}
return styles
},
//
tranfromInit(type) {
<<<<<<< HEAD
if (!this.animation) return this
=======
if (!this.animation) {
console.warn('uni-transition: animation object is not initialized')
return this.animation
}
>>>>>>> dev_pig
let buildTranfrom = (type, mode) => {
let aniNum = null
if (mode === 'fade') {
aniNum = type ? 0 : 1
} else {
aniNum = type ? '-100%' : '0'
if (mode === 'zoom-in') {
aniNum = type ? 0.8 : 1
}
if (mode === 'zoom-out') {
aniNum = type ? 1.2 : 1
}
if (mode === 'slide-right') {
aniNum = type ? '100%' : '0'
}
if (mode === 'slide-bottom') {
aniNum = type ? '100%' : '0'
}
}
<<<<<<< HEAD
let methodName = this.animationMode()[mode]
if (this.animation && typeof this.animation[methodName] === 'function') {
this.animation[methodName](aniNum)
=======
const animationMethod = this.animationMode()[mode]
if (this.animation && typeof this.animation[animationMethod] === 'function') {
this.animation[animationMethod](aniNum)
>>>>>>> dev_pig
}
}
if (typeof this.modeClass === 'string') {
buildTranfrom(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildTranfrom(type, mode)
})
}
return this.animation
},
animationType(type) {
return {
fade: type ? 1 : 0,
'slide-top': `translateY(${type ? '0' : '-100%'})`,
'slide-right': `translateX(${type ? '0' : '100%'})`,
'slide-bottom': `translateY(${type ? '0' : '100%'})`,
'slide-left': `translateX(${type ? '0' : '-100%'})`,
'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
}
},
//
animationMode() {
return {
fade: 'opacity',
'slide-top': 'translateY',
'slide-right': 'translateX',
'slide-bottom': 'translateY',
'slide-left': 'translateX',
'zoom-in': 'scale',
'zoom-out': 'scale'
}
},
// 线
toLine(name) {
return name.replace(/([A-Z])/g, '-$1').toLowerCase()
}
}
}
</script>
<style></style>

277
uni_modules/uni-transition/components/uni-transition/uni-transition_BASE_472.vue

@ -0,0 +1,277 @@
<template>
<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
</template>
<script>
import { createAnimation } from './createAnimation'
/**
* Transition 过渡动画
* @description 简单过渡动画组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
* @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
* @value fade 渐隐渐出过渡
* @value slide-top 由上至下过渡
* @value slide-right 由右至左过渡
* @value slide-bottom 由下至上过渡
* @value slide-left 由左至右过渡
* @value zoom-in 由小到大过渡
* @value zoom-out 由大到小过渡
* @property {Number} duration 过渡动画持续时间
* @property {Object} styles 组件样式 css 样式注意带-连接符的属性需要使用小驼峰写法如`backgroundColor:red`
*/
export default {
name: 'uniTransition',
emits:['click','change'],
props: {
show: {
type: Boolean,
default: false
},
modeClass: {
type: [Array, String],
default() {
return 'fade'
}
},
duration: {
type: Number,
default: 300
},
styles: {
type: Object,
default() {
return {}
}
},
customClass:{
type: String,
default: ''
}
},
data() {
return {
isShow: false,
transform: '',
opacity: 1,
animationData: {},
durationTime: 300,
config: {}
}
},
watch: {
show: {
handler(newVal) {
if (newVal) {
this.open()
} else {
// close,
if (this.isShow) {
this.close()
}
}
},
immediate: true
}
},
computed: {
//
stylesObject() {
let styles = {
...this.styles,
'transition-duration': this.duration / 1000 + 's'
}
let transform = ''
for (let i in styles) {
let line = this.toLine(i)
transform += line + ':' + styles[i] + ';'
}
return transform
},
//
transformStyles() {
return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
}
},
created() {
//
this.config = {
duration: this.duration,
timingFunction: 'ease',
transformOrigin: '50% 50%',
delay: 0
}
this.durationTime = this.duration
},
methods: {
/**
* ref 触发 初始化动画
*/
init(obj = {}) {
if (obj.duration) {
this.durationTime = obj.duration
}
this.animation = createAnimation(Object.assign(this.config, obj),this)
},
/**
* 点击组件触发回调
*/
onClick() {
this.$emit('click', {
detail: this.isShow
})
},
/**
* ref 触发 动画分组
* @param {Object} obj
*/
step(obj, config = {}) {
if (!this.animation) return
for (let i in obj) {
try {
if(typeof obj[i] === 'object'){
this.animation[i](...obj[i])
}else{
this.animation[i](obj[i])
}
} catch (e) {
console.error(`方法 ${i} 不存在`)
}
}
this.animation.step(config)
return this
},
/**
* ref 触发 执行动画
*/
run(fn) {
if (!this.animation) return
this.animation.run(fn)
},
//
open() {
clearTimeout(this.timer)
this.transform = ''
this.isShow = true
let { opacity, transform } = this.styleInit(false)
if (typeof opacity !== 'undefined') {
this.opacity = opacity
}
this.transform = transform
// nextTick wx
this.$nextTick(() => {
// TODO
this.timer = setTimeout(() => {
this.animation = createAnimation(this.config, this)
this.tranfromInit(false).step()
this.animation.run()
this.$emit('change', {
detail: this.isShow
})
}, 20)
})
},
//
close(type) {
if (!this.animation) return
this.tranfromInit(true)
.step()
.run(() => {
this.isShow = false
this.animationData = null
this.animation = null
let { opacity, transform } = this.styleInit(false)
this.opacity = opacity || 1
this.transform = transform
this.$emit('change', {
detail: this.isShow
})
})
},
//
styleInit(type) {
let styles = {
transform: ''
}
let buildStyle = (type, mode) => {
if (mode === 'fade') {
styles.opacity = this.animationType(type)[mode]
} else {
styles.transform += this.animationType(type)[mode] + ' '
}
}
if (typeof this.modeClass === 'string') {
buildStyle(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildStyle(type, mode)
})
}
return styles
},
//
tranfromInit(type) {
let buildTranfrom = (type, mode) => {
let aniNum = null
if (mode === 'fade') {
aniNum = type ? 0 : 1
} else {
aniNum = type ? '-100%' : '0'
if (mode === 'zoom-in') {
aniNum = type ? 0.8 : 1
}
if (mode === 'zoom-out') {
aniNum = type ? 1.2 : 1
}
if (mode === 'slide-right') {
aniNum = type ? '100%' : '0'
}
if (mode === 'slide-bottom') {
aniNum = type ? '100%' : '0'
}
}
this.animation[this.animationMode()[mode]](aniNum)
}
if (typeof this.modeClass === 'string') {
buildTranfrom(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildTranfrom(type, mode)
})
}
return this.animation
},
animationType(type) {
return {
fade: type ? 1 : 0,
'slide-top': `translateY(${type ? '0' : '-100%'})`,
'slide-right': `translateX(${type ? '0' : '100%'})`,
'slide-bottom': `translateY(${type ? '0' : '100%'})`,
'slide-left': `translateX(${type ? '0' : '-100%'})`,
'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
}
},
//
animationMode() {
return {
fade: 'opacity',
'slide-top': 'translateY',
'slide-right': 'translateX',
'slide-bottom': 'translateY',
'slide-left': 'translateX',
'zoom-in': 'scale',
'zoom-out': 'scale'
}
},
// 线
toLine(name) {
return name.replace(/([A-Z])/g, '-$1').toLowerCase()
}
}
}
</script>
<style></style>

319
uni_modules/uni-transition/components/uni-transition/uni-transition_LOCAL_472.vue

@ -0,0 +1,319 @@
<template>
<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
</template>
<script>
// #ifndef MP-WEIXIN
import { createAnimation } from './createAnimation'
// #endif
// #ifdef MP-WEIXIN
const createAnimation = require('./createAnimation.js').createAnimation
// #endif
/**
* Transition 过渡动画
* @description 简单过渡动画组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
* @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
* @value fade 渐隐渐出过渡
* @value slide-top 由上至下过渡
* @value slide-right 由右至左过渡
* @value slide-bottom 由下至上过渡
* @value slide-left 由左至右过渡
* @value zoom-in 由小到大过渡
* @value zoom-out 由大到小过渡
* @property {Number} duration 过渡动画持续时间
* @property {Object} styles 组件样式 css 样式注意带-连接符的属性需要使用小驼峰写法如`backgroundColor:red`
*/
export default {
name: 'uniTransition',
emits:['click','change'],
props: {
show: {
type: Boolean,
default: false
},
modeClass: {
type: [Array, String],
default() {
return 'fade'
}
},
duration: {
type: Number,
default: 300
},
styles: {
type: Object,
default() {
return {}
}
},
customClass:{
type: String,
default: ''
}
},
data() {
return {
isShow: false,
transform: '',
opacity: 1,
animationData: {},
durationTime: 300,
config: {}
}
},
watch: {
show: {
handler(newVal) {
if (newVal) {
this.open()
} else {
// close,
if (this.isShow) {
this.close()
}
}
},
immediate: true
}
},
computed: {
//
stylesObject() {
let styles = {
...this.styles,
'transition-duration': this.duration / 1000 + 's'
}
let transform = ''
for (let i in styles) {
let line = this.toLine(i)
transform += line + ':' + styles[i] + ';'
}
return transform
},
//
transformStyles() {
return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
}
},
created() {
//
this.config = {
duration: this.duration,
timingFunction: 'ease',
transformOrigin: '50% 50%',
delay: 0
}
this.durationTime = this.duration
},
methods: {
/**
* ref 触发 初始化动画
*/
init(obj = {}) {
if (obj.duration) {
this.durationTime = obj.duration
}
this.animation = createAnimation(Object.assign(this.config, obj),this)
},
/**
* 点击组件触发回调
*/
onClick() {
this.$emit('click', {
detail: this.isShow
})
},
/**
* ref 触发 动画分组
* @param {Object} obj
*/
step(obj, config = {}) {
if (!this.animation) return this
for (let i in obj) {
try {
if (this.animation && typeof this.animation[i] === 'function') {
if(typeof obj[i] === 'object'){
this.animation[i](...obj[i])
}else{
this.animation[i](obj[i])
}
}
} catch (e) {
console.error(`方法 ${i} 不存在:`, e)
}
}
try {
if (this.animation && typeof this.animation.step === 'function') {
this.animation.step(config)
}
} catch (e) {
console.error('动画step执行错误:', e)
}
return this
},
/**
* ref 触发 执行动画
*/
run(fn) {
if (!this.animation) return
try {
if (this.animation && typeof this.animation.run === 'function') {
this.animation.run(fn)
}
} catch (e) {
console.error('动画执行错误:', e)
}
},
//
open() {
clearTimeout(this.timer)
this.transform = ''
this.isShow = true
let { opacity, transform } = this.styleInit(false)
if (typeof opacity !== 'undefined') {
this.opacity = opacity
}
this.transform = transform
// nextTick wx
this.$nextTick(() => {
// TODO
this.timer = setTimeout(() => {
try {
this.animation = createAnimation(this.config, this)
if (this.animation) {
let result = this.tranfromInit(false)
if (result && typeof result.step === 'function') {
result.step()
if (typeof result.run === 'function') {
result.run()
}
}
}
} catch (e) {
console.error('动画初始化错误:', e)
}
this.$emit('change', {
detail: this.isShow
})
}, 20)
})
},
//
close(type) {
if (!this.animation) return
try {
let result = this.tranfromInit(true)
if (result && typeof result.step === 'function') {
result.step()
if (typeof result.run === 'function') {
result.run(() => {
this.isShow = false
this.animationData = null
this.animation = null
let { opacity, transform } = this.styleInit(false)
this.opacity = opacity || 1
this.transform = transform
this.$emit('change', {
detail: this.isShow
})
})
}
}
} catch (e) {
console.error('动画关闭错误:', e)
}
},
//
styleInit(type) {
let styles = {
transform: ''
}
let buildStyle = (type, mode) => {
if (mode === 'fade') {
styles.opacity = this.animationType(type)[mode]
} else {
styles.transform += this.animationType(type)[mode] + ' '
}
}
if (typeof this.modeClass === 'string') {
buildStyle(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildStyle(type, mode)
})
}
return styles
},
//
tranfromInit(type) {
if (!this.animation) return this
let buildTranfrom = (type, mode) => {
let aniNum = null
if (mode === 'fade') {
aniNum = type ? 0 : 1
} else {
aniNum = type ? '-100%' : '0'
if (mode === 'zoom-in') {
aniNum = type ? 0.8 : 1
}
if (mode === 'zoom-out') {
aniNum = type ? 1.2 : 1
}
if (mode === 'slide-right') {
aniNum = type ? '100%' : '0'
}
if (mode === 'slide-bottom') {
aniNum = type ? '100%' : '0'
}
}
let methodName = this.animationMode()[mode]
if (this.animation && typeof this.animation[methodName] === 'function') {
this.animation[methodName](aniNum)
}
}
if (typeof this.modeClass === 'string') {
buildTranfrom(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildTranfrom(type, mode)
})
}
return this.animation
},
animationType(type) {
return {
fade: type ? 1 : 0,
'slide-top': `translateY(${type ? '0' : '-100%'})`,
'slide-right': `translateX(${type ? '0' : '100%'})`,
'slide-bottom': `translateY(${type ? '0' : '100%'})`,
'slide-left': `translateX(${type ? '0' : '-100%'})`,
'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
}
},
//
animationMode() {
return {
fade: 'opacity',
'slide-top': 'translateY',
'slide-right': 'translateX',
'slide-bottom': 'translateY',
'slide-left': 'translateX',
'zoom-in': 'scale',
'zoom-out': 'scale'
}
},
// 线
toLine(name) {
return name.replace(/([A-Z])/g, '-$1').toLowerCase()
}
}
}
</script>
<style></style>

310
uni_modules/uni-transition/components/uni-transition/uni-transition_REMOTE_472.vue

@ -0,0 +1,310 @@
<template>
<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
</template>
<script>
import { createAnimation } from './createAnimation'
/**
* Transition 过渡动画
* @description 简单过渡动画组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
* @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
* @value fade 渐隐渐出过渡
* @value slide-top 由上至下过渡
* @value slide-right 由右至左过渡
* @value slide-bottom 由下至上过渡
* @value slide-left 由左至右过渡
* @value zoom-in 由小到大过渡
* @value zoom-out 由大到小过渡
* @property {Number} duration 过渡动画持续时间
* @property {Object} styles 组件样式 css 样式注意带-连接符的属性需要使用小驼峰写法如`backgroundColor:red`
*/
export default {
name: 'uniTransition',
emits:['click','change'],
props: {
show: {
type: Boolean,
default: false
},
modeClass: {
type: [Array, String],
default() {
return 'fade'
}
},
duration: {
type: Number,
default: 300
},
styles: {
type: Object,
default() {
return {}
}
},
customClass:{
type: String,
default: ''
}
},
data() {
return {
isShow: false,
transform: '',
opacity: 1,
animationData: {},
durationTime: 300,
config: {}
}
},
watch: {
show: {
handler(newVal) {
if (newVal) {
this.open()
} else {
// close,
if (this.isShow) {
this.close()
}
}
},
immediate: true
}
},
computed: {
//
stylesObject() {
let styles = {
...this.styles,
'transition-duration': this.duration / 1000 + 's'
}
let transform = ''
for (let i in styles) {
let line = this.toLine(i)
transform += line + ':' + styles[i] + ';'
}
return transform
},
//
transformStyles() {
return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
}
},
created() {
//
this.config = {
duration: this.duration,
timingFunction: 'ease',
transformOrigin: '50% 50%',
delay: 0
}
this.durationTime = this.duration
},
methods: {
/**
* ref 触发 初始化动画
*/
init(obj = {}) {
if (obj.duration) {
this.durationTime = obj.duration
}
this.animation = createAnimation(Object.assign(this.config, obj),this)
},
/**
* 点击组件触发回调
*/
onClick() {
this.$emit('click', {
detail: this.isShow
})
},
/**
* ref 触发 动画分组
* @param {Object} obj
*/
step(obj, config = {}) {
if (!this.animation || typeof this.animation.step !== 'function') return this
for (let i in obj) {
try {
if(typeof obj[i] === 'object'){
this.animation[i](...obj[i])
}else{
this.animation[i](obj[i])
}
} catch (e) {
console.error(`方法 ${i} 不存在`)
}
}
this.animation.step(config)
return this
},
/**
* ref 触发 执行动画
*/
run(fn) {
if (!this.animation || typeof this.animation.run !== 'function') return
this.animation.run(fn)
},
//
open() {
clearTimeout(this.timer)
this.transform = ''
this.isShow = true
let { opacity, transform } = this.styleInit(false)
if (typeof opacity !== 'undefined') {
this.opacity = opacity
}
this.transform = transform
// nextTick wx
this.$nextTick(() => {
// TODO
this.timer = setTimeout(() => {
try {
this.animation = createAnimation(this.config, this)
if (this.animation && typeof this.animation.step === 'function' && typeof this.animation.run === 'function') {
const result = this.tranfromInit(false)
if (result && typeof result.step === 'function') {
result.step()
if (typeof this.animation.run === 'function') {
this.animation.run()
}
}
}
} catch (error) {
console.error('uni-transition animation error:', error)
}
this.$emit('change', {
detail: this.isShow
})
}, 20)
})
},
//
close(type) {
if (!this.animation || typeof this.animation.step !== 'function' || typeof this.animation.run !== 'function') return
try {
const result = this.tranfromInit(true)
if (result && typeof result.step === 'function') {
result.step()
if (typeof result.run === 'function') {
result.run(() => {
this.isShow = false
this.animationData = null
this.animation = null
let { opacity, transform } = this.styleInit(false)
this.opacity = opacity || 1
this.transform = transform
this.$emit('change', {
detail: this.isShow
})
})
}
}
} catch (error) {
console.error('uni-transition close animation error:', error)
//
this.isShow = false
this.animationData = null
this.animation = null
this.$emit('change', {
detail: this.isShow
})
}
},
//
styleInit(type) {
let styles = {
transform: ''
}
let buildStyle = (type, mode) => {
if (mode === 'fade') {
styles.opacity = this.animationType(type)[mode]
} else {
styles.transform += this.animationType(type)[mode] + ' '
}
}
if (typeof this.modeClass === 'string') {
buildStyle(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildStyle(type, mode)
})
}
return styles
},
//
tranfromInit(type) {
if (!this.animation) {
console.warn('uni-transition: animation object is not initialized')
return this.animation
}
let buildTranfrom = (type, mode) => {
let aniNum = null
if (mode === 'fade') {
aniNum = type ? 0 : 1
} else {
aniNum = type ? '-100%' : '0'
if (mode === 'zoom-in') {
aniNum = type ? 0.8 : 1
}
if (mode === 'zoom-out') {
aniNum = type ? 1.2 : 1
}
if (mode === 'slide-right') {
aniNum = type ? '100%' : '0'
}
if (mode === 'slide-bottom') {
aniNum = type ? '100%' : '0'
}
}
const animationMethod = this.animationMode()[mode]
if (this.animation && typeof this.animation[animationMethod] === 'function') {
this.animation[animationMethod](aniNum)
}
}
if (typeof this.modeClass === 'string') {
buildTranfrom(type, this.modeClass)
} else {
this.modeClass.forEach(mode => {
buildTranfrom(type, mode)
})
}
return this.animation
},
animationType(type) {
return {
fade: type ? 1 : 0,
'slide-top': `translateY(${type ? '0' : '-100%'})`,
'slide-right': `translateX(${type ? '0' : '100%'})`,
'slide-bottom': `translateY(${type ? '0' : '100%'})`,
'slide-left': `translateX(${type ? '0' : '-100%'})`,
'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
}
},
//
animationMode() {
return {
fade: 'opacity',
'slide-top': 'translateY',
'slide-right': 'translateX',
'slide-bottom': 'translateY',
'slide-left': 'translateX',
'zoom-in': 'scale',
'zoom-out': 'scale'
}
},
// 线
toLine(name) {
return name.replace(/([A-Z])/g, '-$1').toLowerCase()
}
}
}
</script>
<style></style>
Loading…
Cancel
Save