可移动的选中效果的tag下划线
先看效果
首先把tag样式和点击事件写好
<script setup>
import { ref } from "vue";
const tagList = [
"123123",
"15135",
"5435413541",
"354354135",
"534354135",
"564564564656465",
"4564564564",
"564564564654654654564",
]; // tag数据
const activeTag = ref(null); // 当前选中的tag下标
</script>
<template>
<!-- tag的盒子 -->
<view class="tag-box">
<!-- 每一个tag -->
<view
class="tag"
v-for="(item, index) in tagList"
:key="index"
:class="activeTag == index ? 'tag--active' : ''"
@click="activeTag = index"
>{{ item }}</view
>
</view>
</template>
<style scoped lang="scss">
.tag-box {
width: 750rpx;
height: 100rpx;
background-color: #777676;
display: flex;
align-items: center;
overflow: scroll; // 超出滚动
.tag {
margin: 0 10rpx;
// 这样写也可以
// &--active {
// color: brown;
// }
}
.tag--active {
color: brown;
}
}
</style>
此时效果
前置工作准备完成,接下来先把下划线写出来
<template>
<!-- tag的盒子 -->
<view class="tag-box">
<!-- 每一个tag -->
<!-- ..... -->
<!-- 下滑线 -->
<view class="xian"></view>
</view>
</template>
<style scoped lang="scss">
.tag-box {
width: 750rpx;
height: 100rpx;
background-color: #777676;
display: flex;
align-items: center;
overflow: scroll; // 超出滚动
position: relative; // 相对定位
.tag {
margin: 0 10rpx;
}
.tag--active {
color: brown;
}
// 下划线的样式
.xian {
background-color: #f5b501;
width: 50rpx;
height: 10rpx;
border-radius: 9999rpx;
position: absolute;
left: 0;
bottom: 15rpx;
}
}
</style>
现在的效果
现在就会想到下划线的宽度以及定位的left需要动态改变,
- 宽度为当前选中tag的宽度
- left为当前选中tag在页面中的left
那么就需要获取节点的位置信息,
- 打开uniapp的官网
- 搜索这个API uni.createSelectorQuery
- 直接复制示例代码
然后再稍稍修改一下
import { ref, getCurrentInstance } from "vue";
import { onReady } from "@dcloudio/uni-app";
const tagXYList = ref([]); // 所有tag节点位置信息的数组
onReady(() => {
const instance = getCurrentInstance();
const query = uni.createSelectorQuery().in(instance.proxy);
query
// .select("#id") // 选中id='id'节点
.selectAll(".tag") // 选中所有class='tag'节点
.boundingClientRect((data) => {
console.log(data); // 这里就是所有节点的坐标信息数组
tagXYList.value = data; // 保存起来
})
.exec();
activeTag.value = 0;
});
这个时候每个tag元素的宽度以及left已经被保存起来了 接下来只需要把当前选中的tag的宽度以及left给下划线赋值上就可以了(所有位置信息的单位都是px)
<view
class="xian"
v-if="tagXYList.length"
:style="{ width: tagXYList[activeTag].width + 'px', left: tagXYList[activeTag].left + 'px' }"
></view>
现在下划线的宽度和left就是当前选中tag的宽度和left了。 实现的核心就是使用uni.createSelectorQuery()获取节点的位置信息
完整代码
<script setup>
import { ref, getCurrentInstance } from "vue";
import { onReady } from "@dcloudio/uni-app";
const tagList = [
"123123",
"15135",
"5435413541",
"354354135",
"534354135",
"564564564656465",
"4564564564",
"564564564654654654564",
];
const tagXYList = ref([]);
const activeTag = ref(null);
onReady(() => {
const instance = getCurrentInstance();
const query = uni.createSelectorQuery().in(instance.proxy);
query
// .select("#id") // 选中id='id'节点
.selectAll(".tag") // 选中所有class='tag'节点
.boundingClientRect((data) => {
console.log(data); // 这里就是所有节点的坐标信息数组
tagXYList.value = data;
})
.exec();
activeTag.value = 0; // 把下划线的初始位置设置到第一个
});
</script>
<template>
<!-- tag的盒子 -->
<view class="tag-box">
<!-- 每一个tag -->
<view
class="tag"
v-for="(item, index) in tagList"
:key="index"
:class="activeTag == index ? 'tag--active' : ''"
@click="activeTag = index"
>{{ item }}</view
>
<!-- 下滑线 -->
<view
class="xian"
v-if="tagXYList.length"
:style="{ width: tagXYList[activeTag].width + 'px', left: tagXYList[activeTag].left + 'px' }"
></view>
</view>
</template>
<style scoped lang="scss">
.tag-box {
width: 750rpx;
height: 100rpx;
background-color: #777676;
display: flex;
align-items: center;
overflow: scroll; // 超出滚动
position: relative;
.tag {
margin: 0 10rpx;
// 这样写也可以
// &--active {
// color: brown;
// }
}
.tag--active {
color: brown;
}
.xian {
background-color: #f5b501;
width: 50rpx;
height: 10rpx;
border-radius: 9999rpx;
position: absolute;
left: 0;
bottom: 15rpx;
transition: all 0.3s; // 加上过度效果
}
}
</style>