效果图:
第一页:
第二页:
实现思路: 1、列表横向排列可以使用flex布局解决,主要逻辑在点击左右按钮时操作
-----看懂这个很关键----
如上图,蓝色为外层div,红色为内层div; 内层div装有列表的各项item,所以它的宽度可能会大于外层div的宽度。外层div采用定宽,同时设置overflow: hidden,使内层div突出的部分隐藏起来。通过设置内层div的transform:translateX来左右移动。
上代码:
<div class="top">//class="top"为可视宽度
//左箭头
<div class="left" @click="navPrev">
<img src="@/assets/images/equipment/default.png" alt="">
</div>
//内容
<div class="center" ref="devInsall">
<div :class="item.isChoose==true?'active_item':'item'"
:style="{transform:'translateX(-'+state.move+'px)'}"
v-for="(item,index) in state.installList" :key="index"
@click="handlerDeviceInstall(item)">
<img :src="item.productUrl" alt="">
<p style="color: #FFFFFF;">{{item.productName}}</p>
<p style="color: #CFD5DF;">{{item.installDeviceTotal}}</p>
</div>
</div>
//右箭头
<div class="right" @click="navNext" v-if="state.installList.length>15">
<img src="@/assets/images/equipment/right.png" alt="">
</div>
</div>
js部分:
//vue3.0 写法
<script setup>
import { reactive, ref, onMounted, nextTick } from "vue";
const state = reactive({
//定义三个参数
move: 0,//移动位置
realWidth: 0,//实际宽度
viewWidth: 0,//可视宽度
installList:[]//列表
})
//获取宽度
const rollTemp = () => {
nextTick(() => {
//获取整个菜单实际宽度、state.installList是后端返回的,118是代表每一个的宽度
state.realWidth = state.installList.length * 118
console.log('内容总宽度-----', state.realWidth)
// 获取菜单在当前页面可视宽度
state.viewWidth = devInsall.value.clientWidth
console.log('可视宽度', state.viewWidth)
// 窗口大小变化时触发。实时更新可视宽度
window.onresize = () => {
return (() => {
state.viewWidth = devInsall.value.clientWidth
if (state.move > state.realWidth - state.viewWidth - 118) {
state.move = state.realWidth - state.viewWidth;
console.log('窗口变化时move', state.move)
}
})()
}
})
}
const navPrev = () => {//点击左箭头
if (state.move > 118) {
state.move = state.move - state.viewWidth
console.log('向左边移动===>', state.move)
} else {//停止
state.move = 0
}
}
const navNext = () => {//点击右箭头
if (state.realWidth < state.viewWidth) {//内容少于可视宽度时,不需要移动
return false
} else {
//如果偏移量+可视宽度+118大于内容总长度;表示已经到底了
if ((state.move + state.viewWidth + 118) > state.realWidth) {
console.log('到底啦')
state.move = state.move
} else {
//移动一屏
state.move = state.move + state.viewWidth
console.log('我还要move', state.move)
}
}
}
</script>
css代码:
.top {
display: flex;
justify-content: space-between;
width: 100%;
height: 100px;
background-color: #0f315f;
.left {
position: relative;
width: 44px;
height: 100%;
background-color: #1d528f;
img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 26px;
height: 32px;
}
}
.right {
position: relative;
width: 44px;
height: 100%;
background-color: #1d528f;
cursor: pointer;
img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 16px;
height: 32px;
}
}
.center {
display: flex;
justify-content: flex-start;
width: calc(100% - 98px);
overflow: hidden;
white-space: nowrap;
.item {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
min-width: 88px;
height: 98px;
transition: transform 0.2s;
margin-left: 30px;
cursor: pointer;
img {
width: 40px;
height: 40px;
}
p {
font-size: 12px;
}
}
.active_item {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
background: linear-gradient(180deg, #0f315f 0%, #409eff 100%);
min-width: 88px;
height: 98px;
margin-left: 30px;
cursor: pointer;
img {
width: 40px;
height: 40px;
}
p {
font-size: 12px;
}
}
}
}