Files

235 lines
5.4 KiB
Vue
Raw Normal View History

2023-11-14 17:21:03 +08:00
<!--
@name: LiveCards
@author: kahu4
@date: 2023-11-01 17:04
@descriptionLiveCards
@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>