235 lines
5.4 KiB
Vue
235 lines
5.4 KiB
Vue
![]() |
<!--
|
|||
|
@name: LiveCards
|
|||
|
@author: kahu4
|
|||
|
@date: 2023-11-01 17:04
|
|||
|
@description:LiveCards
|
|||
|
@update: 2023-11-01 17:04
|
|||
|
-->
|
|||
|
<script setup>
|
|||
|
import { computed, onMounted, ref, unref } from "vue";
|
|||
|
import { useSystem } from "@/hooks/useSystem";
|
|||
|
|
|||
|
const liveCardList = [
|
|||
|
{
|
|||
|
id: 1,
|
|||
|
isLive: true,
|
|||
|
title: '买一送一',
|
|||
|
background: 'https://alipic.lanhuapp.com/XDSlicePNGMAXc18a81ef73fc74664ef83df1de77da21f12619ff86653931ed809710b31c2e82.png',
|
|||
|
peopleNum: 168
|
|||
|
},
|
|||
|
{
|
|||
|
id: 2,
|
|||
|
isLive: false,
|
|||
|
title: '买一送二',
|
|||
|
background: 'https://alipic.lanhuapp.com/XDSlicePNGMAXc18a81ef73fc74664ef83df1de77da21f12619ff86653931ed809710b31c2e82.png',
|
|||
|
peopleNum: 16858
|
|||
|
},
|
|||
|
{
|
|||
|
id: 3,
|
|||
|
isLive: true,
|
|||
|
title: '买一送三',
|
|||
|
background: 'https://alipic.lanhuapp.com/XDSlicePNGMAXc18a81ef73fc74664ef83df1de77da21f12619ff86653931ed809710b31c2e82.png',
|
|||
|
peopleNum: 22343
|
|||
|
},
|
|||
|
{
|
|||
|
id: 4,
|
|||
|
isLive: true,
|
|||
|
title: '买一送三',
|
|||
|
background: 'https://alipic.lanhuapp.com/XDSlicePNGMAXc18a81ef73fc74664ef83df1de77da21f12619ff86653931ed809710b31c2e82.png',
|
|||
|
peopleNum: 22343
|
|||
|
},
|
|||
|
{
|
|||
|
id: 4,
|
|||
|
isLive: true,
|
|||
|
title: '买一送三',
|
|||
|
background: 'https://alipic.lanhuapp.com/XDSlicePNGMAXc18a81ef73fc74664ef83df1de77da21f12619ff86653931ed809710b31c2e82.png',
|
|||
|
peopleNum: 22343
|
|||
|
},
|
|||
|
{
|
|||
|
id: 4,
|
|||
|
isLive: true,
|
|||
|
title: '买一送三',
|
|||
|
background: 'https://alipic.lanhuapp.com/XDSlicePNGMAXc18a81ef73fc74664ef83df1de77da21f12619ff86653931ed809710b31c2e82.png',
|
|||
|
peopleNum: 22343
|
|||
|
}
|
|||
|
]
|
|||
|
|
|||
|
const {getSystemInfo} = useSystem();
|
|||
|
|
|||
|
// ============================== 设置card选中相关 ================================
|
|||
|
const current = ref(1) // 当前选中的索引
|
|||
|
const systemInfo = ref({windowWidth: 0}) // 系统信息
|
|||
|
const scrollLeft = ref(0) // 当前滑动到的位置
|
|||
|
const scrollWidth = ref(0) // 滑轨总大小
|
|||
|
// 计算单张宽度
|
|||
|
const cardWidth = computed(() => {
|
|||
|
if (unref(systemInfo).windowWidth <= 0) return 0
|
|||
|
return Math.floor((unref(systemInfo).windowWidth) / 3) - 25
|
|||
|
})
|
|||
|
|
|||
|
/**
|
|||
|
* 滑动
|
|||
|
* @param e
|
|||
|
*/
|
|||
|
function handleScroll(e) {
|
|||
|
scrollLeft.value = e.detail.scrollLeft
|
|||
|
scrollWidth.value = e.detail.scrollWidth
|
|||
|
setCurrent()
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 设置选中card
|
|||
|
* @returns {number}
|
|||
|
*/
|
|||
|
function setCurrent() {
|
|||
|
// 小于单张宽度直接设置1选中第2张
|
|||
|
if (scrollLeft.value <= cardWidth.value) return current.value = 1
|
|||
|
// 否则 current = (当前位置 / 单张宽度)= 当前屏幕左侧顶到图片的索引
|
|||
|
// +1选中后一张
|
|||
|
current.value = Math.floor(scrollLeft.value / cardWidth.value) + 1
|
|||
|
}
|
|||
|
|
|||
|
function clickCard() {
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
onMounted(async () => {
|
|||
|
systemInfo.value = await getSystemInfo()
|
|||
|
})
|
|||
|
</script>
|
|||
|
|
|||
|
<template>
|
|||
|
<view class="live-cards">
|
|||
|
<scroll-view
|
|||
|
class="live-cards__inner"
|
|||
|
scroll-x
|
|||
|
@scroll="handleScroll"
|
|||
|
>
|
|||
|
<view class="track">
|
|||
|
<view
|
|||
|
:class="{'card-item':true,'current':index===current}"
|
|||
|
v-for="(item,index) in liveCardList"
|
|||
|
:key="item.id"
|
|||
|
@click="clickCard"
|
|||
|
>
|
|||
|
<image
|
|||
|
class="live-img"
|
|||
|
:src="item.background"
|
|||
|
mode="aspectFill"
|
|||
|
/>
|
|||
|
<view class="mask">
|
|||
|
<view :class="{'status-box':true}">
|
|||
|
<view :class="{status:true,close:item.isLive===false}">
|
|||
|
{{ item.isLive ? '直播中' : '暂未开始' }}
|
|||
|
</view>
|
|||
|
<view class="number">
|
|||
|
{{ item.isLive ? item.peopleNum : 0 }}人
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
<view class="title">
|
|||
|
{{ item.title }}
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</scroll-view>
|
|||
|
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
|
|||
|
<style
|
|||
|
scoped
|
|||
|
lang="scss"
|
|||
|
>
|
|||
|
.live-cards {
|
|||
|
width: 100%;
|
|||
|
padding: 70rpx 0;
|
|||
|
aspect-ratio: 750/480;
|
|||
|
|
|||
|
&__inner {
|
|||
|
width: 100%;
|
|||
|
height: 100%;
|
|||
|
|
|||
|
.track {
|
|||
|
height: 100%;
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
|
|||
|
|
|||
|
.card-item {
|
|||
|
flex-shrink: 0;
|
|||
|
width: calc(100% / 3);
|
|||
|
height: 80%;
|
|||
|
background: #fff;
|
|||
|
border-radius: 15rpx;
|
|||
|
overflow: hidden;
|
|||
|
position: relative;
|
|||
|
transition: all .3s;
|
|||
|
scale: 1;
|
|||
|
z-index: 1;
|
|||
|
|
|||
|
.live-img {
|
|||
|
width: 100%;
|
|||
|
height: 100%;
|
|||
|
}
|
|||
|
|
|||
|
.mask {
|
|||
|
position: absolute;
|
|||
|
top: 0;
|
|||
|
left: 0;
|
|||
|
z-index: 10;
|
|||
|
width: 100%;
|
|||
|
height: 100%;
|
|||
|
padding: 35rpx 20rpx;
|
|||
|
box-sizing: border-box;
|
|||
|
color: #fff;
|
|||
|
font-size: 18rpx;
|
|||
|
|
|||
|
|
|||
|
.status-box {
|
|||
|
position: absolute;
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
top: 18rpx;
|
|||
|
left: 20rpx;
|
|||
|
height: 33rpx;
|
|||
|
line-height: 33rpx;
|
|||
|
border-radius: 33rpx;
|
|||
|
background: rgba(0, 0, 0, 0.6);
|
|||
|
|
|||
|
.status {
|
|||
|
background: #ee6d46;
|
|||
|
border-radius: 33rpx;
|
|||
|
padding: 0 10rpx;
|
|||
|
}
|
|||
|
|
|||
|
.close {
|
|||
|
background: grey;
|
|||
|
}
|
|||
|
|
|||
|
.number {
|
|||
|
padding: 0 1rpx;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
.title {
|
|||
|
font-size: 28rpx;
|
|||
|
position: absolute;
|
|||
|
width: 100%;
|
|||
|
color: #fff;
|
|||
|
left: 20rpx;
|
|||
|
bottom: 20rpx;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
.current {
|
|||
|
scale: 1.2 1.2;
|
|||
|
z-index: 11;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
</style>
|