Browse Source

no message

BF-202210271038\Administrator 2 years ago
parent
commit
bd38c11801

+ 3 - 0
.gitignore

@@ -2,3 +2,6 @@ unpackage/
 .idea/
 node_modules/
 .hbuilderx/
+static/.DS_Store
+components/.DS_Store
+components/dgex-tantan/.DS_Store

+ 325 - 0
components/dgex-tantan/dgex-tantan.vue

@@ -0,0 +1,325 @@
+<template>
+	<view class="tantan-slide" :style="{
+		width: winWidth + 'px',
+		height: winHeigh + 'px',
+	}">
+
+		<view @touchstart.capture="touchStart($event,currentIndex)"
+			@touchmove.stop.capture="touchMove($event,currentIndex)"
+			@touchend.capture="touchEnd(currentIndex)" class="tantan-slide-box">
+			<template v-for="(item, index) in list">
+				<view class="tantan-slide-box-item"
+					:key="index"
+					v-if="currentIndex + visible >= index"
+					 @click.stop="clickImage"
+					:style="[cardTransform(item, index), {
+						'zIndex': list.length - index,
+						'opacity': currentIndex + visible - 1 >= index && currentIndex <= index ? 1 : 0,
+						'transform': 'rotate(' + ((item.x || 0) / 30 ) +  'deg) translate3d(' + (item.x || 0) + 'px,' + (item.y || 0) + 'px, '+  0  +'px)'
+					}]">
+					 <!-- 加载图片会闪屏 双if避免 -->
+					<template v-if="currentIndex + visible >= index && currentIndex <= index">
+
+						<image class="tantan-slide-img" mode="aspectFill" :src="item.image" ></image>
+						<view class="tantan-slide-box-item-bg">
+							<view class="tantan-slide-box-info">
+								<view class="title" v-if="item.title" v-text="item.title"></view>
+								<view class="desc" v-if="item.desc" v-text="item.desc"></view>
+								<view class="tags" v-if="item.tags && item.tags.length > 0" >
+									<text class="tag" v-for="(item1, index1) in item.tags" :key="index1" v-text="item1"></text>
+								</view>
+							</view>
+						</view>
+						<view v-if="index === currentIndex">
+							<view class="tantan-slide-box-icon tantan-slide-box-dislike"
+								:style="{
+									opacity: dislike * 1.5,
+									transform: 'scale('+ (dislike + 1 > 2 ? 2 : dislike + 1 )  +')',
+								}">
+								<image style="width: 30rpx;height: 30rpx;" src="/static/dgex-tantan/close.png"></image>
+							</view>
+							<view class="tantan-slide-box-icon tantan-slide-box-love" :style="{
+									opacity: love * 1.5,
+									transform: 'scale('+ (love + 1 > 2 ? 2 : love + 1 )  +')',
+								}">
+								<image style="width: 30rpx;height: 30rpx;" src="/static/dgex-tantan/like.png"></image>
+							</view>
+						</view>
+					</template>
+				</view>
+			</template>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "slide",
+		props: {
+			list: {
+				type: Array,
+				default: () => []
+			}
+		},
+		data() {
+			return {
+				winWidth: 0,
+				winHeigh: 0,
+				/*记录x y轴*/
+				x: {
+					start: 0,
+					move: 0,
+					end: 0
+				},
+				y: {
+					start: 0,
+					move: 0,
+					end: 0
+				},
+				visible: 3,
+				/*下标*/
+				currentIndex: 0,
+				/*滑动*/
+				swipering: false,
+				/*滑动中*/
+				slideing: false,
+				love: 0,
+				dislike: 0,
+			}
+		},
+		mounted() {
+			const res = uni.getSystemInfoSync()
+			this.winWidth = res.windowWidth
+			this.winHeigh = res.windowHeight
+		},
+		methods: {
+			cardTransform(item, index) {
+				let css = {};
+				if (index === this.currentIndex) {
+					if (this.slideing) {
+						css["transitionDuration"] = `${!this.swipering ? 1000 : 0}ms`;
+					} else {
+						css["transitionDuration"] = `${!this.swipering ? 300 : 0}ms`;
+					}
+				}
+				return css
+			},
+			touchStart(e, index) {
+				if (this.slideing) return;
+				if (typeof this.list[index].x === 'undefined' && typeof this.list[index].y === 'undefined') {
+					this.$set(this.list[index], 'y', 0)
+					this.$set(this.list[index], 'x', 0)
+				}
+				this.swipering = true;
+				this.x.start = e.touches[0].pageX;
+				this.y.start = e.touches[0].pageY;
+			},
+			touchMove(e, index) {
+				if (this.slideing) return
+				// 滑动状态/最后一个就不滑动
+				if (this.list.length == index + 1) {
+					return;
+				}
+				this.x.move = e.touches[0].pageX;
+				this.y.move = e.touches[0].pageY;
+
+				this.list[index].x = this.x.move - this.x.start
+				this.list[index].y = this.y.move - this.y.start
+				if (Number.parseInt(this.list[index].x) > 0) {
+					this.love = Number.parseInt(this.list[index].x) / (100 * 2)
+				} else {
+					this.dislike = Math.abs(Number.parseInt(this.list[index].x) / (100 * 2))
+				}
+			},
+			touchEnd(index) {
+				if (this.slideing) return
+				this.swipering = false;
+				if (this.list.length == index + 1) {
+					return;
+				}
+				if (
+					this.list[index].x > 0 &&
+					this.list[index].x > this.winWidth / 2 - this.winWidth / 5
+				) {
+					this.touchEndNext(index);
+				} else if (
+					this.list[index].x < 0 &&
+					this.list[index].x < -this.winWidth / 2 + this.winWidth / 5
+				) {
+					this.touchEndNext(index);
+				} else {
+					this.list[index].x = 0;
+					this.list[index].y = 0;
+					this.slideing = false;
+					this.love = 0;
+					this.dislike = 0;
+				}
+			},
+			touchEndNext(index) {
+				this.slideing = true;
+				this.list[index].x = this.list[index].x * 5;
+				this.list[index].y = this.list[index].y * 5;
+				this.touchEndDone()
+			},
+			touchEndDone() {
+				return new Promise((resolve) => {
+					setTimeout(() => {
+						this.slideing = false
+						this.$emit('onChange', {
+							currentIndex: this.currentIndex,
+							currentItem: this.list[this.currentIndex],
+							type: this.love !== 0 ? 'love' : 'dislike'
+						})
+						this.currentIndex++
+						this.x.move = 0
+						this.y.move = 0
+						this.slideing = false
+						this.btnClickType = false
+						this.love = 0
+						this.dislike = 0
+						resolve()
+					}, 300);
+				})
+			},
+			footerBtnClick(type) {
+				if (this.btnClickType) {
+					return
+				}
+				this.btnClickType = true
+				let w = 0
+				if (type === 'love') {
+					w = this.winWidth * 1.5
+					this.love = 1
+				} else if (type === 'dislike') {
+					w = -this.winWidth * 1.5
+					this.dislike = 1
+				}
+				this.$set(this.list[this.currentIndex], 'x', w)
+				this.touchEndDone()
+			},
+			clickImage() {
+				this.$emit('onClickImage', {
+					type: 'click',
+					currentIndex: this.currentIndex,
+					currentItem: this.list[this.currentIndex],
+				})
+			}
+		}
+	};
+</script>
+<style>
+	/* fa547c f8ba35 */
+	.tantan-slide {
+		/* background-color: #2196f3; */
+		width: 100%;
+		height: 100%;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		overflow: hidden;
+	}
+
+	.tantan-slide-box {
+		position: relative;
+		width: 95%;
+		height: 90%;
+		perspective: 2100rpx;
+		perspective-origin: 50% -30%;
+		transform-style: preserve-3d;
+		margin: auto;
+	}
+
+	.tantan-slide-box-item {
+		transform-style: preserve-3d;
+		display: flex;
+		width: 100%;
+		height: 100%;
+		border-radius: 24rpx;
+		position: absolute;
+		opacity: 0;
+		transform: translate3d(0px, 0px, 0px) rotate(0deg);
+		transition: 300ms;
+		color: #fff;
+		/* display: none; */
+	}
+
+	.tantan-slide-box-item.on {
+		/* opacity: 1; */
+		display: block;
+	}
+
+	.tantan-slide-box-item-bg {
+		height: 380rpx;
+		background-image: linear-gradient(to bottom, transparent, #000000 70%);
+		position: absolute;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		margin: auto;
+		z-index: 1;
+		border-bottom-right-radius: 40rpx;
+		border-bottom-left-radius: 40rpx;
+	}
+
+	.tantan-slide-box-icon {
+		position: absolute;
+		width: 70rpx;
+		height: 70rpx;
+		top: 45rpx;
+		border-radius: 100%;
+		background-color: #fff;
+		z-index: 1;
+		opacity: 0;
+		transition: 100ms;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.tantan-slide-box-love {
+		left: 50rpx;
+	}
+
+	.tantan-slide-box-dislike {
+		right: 50rpx;
+	}
+
+	.tantan-slide-img {
+		position: relative;
+		will-change: transform;
+		width: 100%;
+		height: 100%;
+		border-radius: 40rpx;
+	}
+	.tantan-slide-img.on{
+		transform: scale(1);
+		width: 50rpx;
+		height: 50rpx;
+	}
+	.tantan-slide-box-info{
+		padding: 0 32rpx;
+		color: #ffffff;
+	}
+	.tantan-slide-box-info .title{
+		font-size: 64rpx;
+		line-height: 1.2;
+		text-shadow: 0 0 10rpx rgb(0, 0, 0, 0.5);
+	}
+	.tantan-slide-box-info .desc{
+		font-size: 32rpx;
+		line-height: 1.2;
+		margin-top: 30rpx;
+		text-shadow: 0 0 10rpx rgb(0, 0, 0, 0.5);
+	}
+	.tantan-slide-box-info .tags{
+		margin-top: 24rpx;
+	}
+	.tantan-slide-box-info .tag{
+		height: 48rpx;
+		font-size: 24rpx;
+		padding: 0 16rpx;
+		line-height: 48rpx;
+		background-color: rgba(255, 255,255,0.3);
+		border-radius: 10rpx;
+	}
+</style>

+ 7 - 0
pages.json

@@ -92,6 +92,13 @@
         "navigationBarTitleText": "",
         "enablePullDownRefresh": false
       }
+    },
+    {
+      "path": "pages/text/tantan",
+      "style": {
+        "navigationBarTitleText": "",
+        "enablePullDownRefresh": false
+      }
     }
   ],
   "globalStyle": {

+ 3 - 2
pages/index/index.vue

@@ -3,7 +3,7 @@
     <index-nav @setTabNum="setTabNum"></index-nav>
     <view class="list-box">
       <view class="box-one" v-if="tabNum===0">
-        <attachment-list></attachment-list>
+        <slide-item></slide-item>
       </view>
       <view class="box-two" v-else-if="tabNum===1">
         <attachment-list></attachment-list>
@@ -18,8 +18,9 @@
 <script>
 import IndexNav from "@/pages/index/model/index-nav";
 import AttachmentList from "@/pages/index/model/attachment-list";
+import SlideItem from "@/pages/index/model/slide-item";
 export default {
-  components: {AttachmentList, IndexNav},
+  components: {SlideItem, AttachmentList, IndexNav},
   data() {
     return {
       tabNum:0

+ 1 - 0
pages/index/model/attachment-list.vue

@@ -60,6 +60,7 @@ export default {
     font-size: 44rpx;
     height: 44rpx;
     line-height: 44rpx;
+    -webkit-background-clip: text;
   }
   .attachment-text{
     text-align: center;

+ 28 - 0
pages/index/model/slide-item.vue

@@ -0,0 +1,28 @@
+<template>
+  <view class="slide-box">
+
+  </view>
+</template>
+
+<script>
+export default {
+  name: "slide-item",
+  components: {},
+  props: {},
+  data() {
+    return {}
+  },
+  watch: {},
+  mounted() {
+
+  },
+  methods: {}
+}
+</script>
+
+<style scoped lang="scss">
+.slide-box{
+
+}
+
+</style>

+ 68 - 0
pages/text/tantan.vue

@@ -0,0 +1,68 @@
+<template>
+  <view>
+    <tantan :list="list" @onChange="change" @onClickImage="clickImage"></tantan>
+  </view>
+</template>
+
+<script>
+import tantan from '@/components/dgex-tantan/dgex-tantan.vue'
+export default {
+  components: {
+    tantan
+  },
+  data() {
+    return {
+      list: []
+    }
+  },
+  mounted() {
+    const arr = []
+    /* 测试数据*/
+    const tu = [
+      'https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2021%2F0704%2Fc7a27a1ej00qvpu700019c000hs00vlc.jpg&thumbnail=660x2147483647&quality=80&type=jpg',
+      'https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2021%2F0704%2F9f81e6aaj00qvpu70001xc000hs00vmc.jpg&thumbnail=660x2147483647&quality=80&type=jpg',
+      'https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2021%2F0704%2F55bf2cb3j00qvpu70002cc000hs012jc.jpg&thumbnail=660x2147483647&quality=80&type=jpg',
+      'https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2021%2F0704%2F2017725bj00qvpu70001jc000hs00zxc.jpg&thumbnail=660x2147483647&quality=80&type=jpg'
+    ]
+    for (let index = 0; index < 10; index++) {
+      const n = Math.floor(Math.random() * (tu.length - 1))
+      let data = {
+        image: tu[n],
+        title: '你好',
+        desc: n + 500 + 'm ' + '30分钟前活跃',
+        tags: ['射手座']
+      }
+      arr.push(data)
+    }
+    this.list = arr
+  },
+  methods: {
+    change(data) {
+      // 判断倒数
+      if (data.currentIndex > this.list.length - 5) {
+        // 模拟一下最加数据
+        const tu = [
+          'https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2021%2F0704%2Fc7a27a1ej00qvpu700019c000hs00vlc.jpg&thumbnail=660x2147483647&quality=80&type=jpg',
+          'https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2021%2F0704%2F9f81e6aaj00qvpu70001xc000hs00vmc.jpg&thumbnail=660x2147483647&quality=80&type=jpg',
+          'https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2021%2F0704%2F55bf2cb3j00qvpu70002cc000hs012jc.jpg&thumbnail=660x2147483647&quality=80&type=jpg',
+          'https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2021%2F0704%2F2017725bj00qvpu70001jc000hs00zxc.jpg&thumbnail=660x2147483647&quality=80&type=jpg'
+        ]
+        for (let index = 0; index < 10; index++) {
+          const n = Math.floor(Math.random() * (tu.length - 1))
+          let newdata = {
+            image: tu[n],
+            title: '你好',
+            desc: n + 500 + 'm ' + '30分钟前活跃',
+            tags: ['射手座']
+          }
+          this.list.push(newdata)
+        }
+      }
+      // console.log(data);
+    },
+    clickImage(data) {
+      console.log(data);
+    }
+  }
+}
+</script>

BIN
static/dgex-tantan/close.png


BIN
static/dgex-tantan/close_white.png


BIN
static/dgex-tantan/like.png


BIN
static/dgex-tantan/like_white.png