属性
- list: @Array 内容数组
- width: @Number 滑块宽度
- height: @Number 滑块高度
- topBottom: @Number 上下间距
- leftRight: @Number 左右间距
- color: @String文字颜色
- activeColor: @String选中文字颜色
- bgColor: @String背景颜色
- activeBgColor: @String滑块背景颜色
- transitionTime: @Number 动画时间
展示
完整代码
<template>
<div class="switch" :style="switchStyles">
<ul class="switch__item" :style="switchItemStyles">
<li class="switch__item__text"
v-for="(item, index) in list" :key="index"
:style="{
...switchItemTextStyles,
...{color: current == index ? activeColor : color}
}"
@click="change(index)"
>{{ item.name }}</li>
</ul>
<div class="switch__action" :style="switchActionStyles"></div>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
name: 'slider-button',
props: {
list: {
type: Array,
default() {
return [
{
name: '固定模式',
value: 0
},
{
name: '缩放模式',
value: 1
}
]
}
},
width: {
type: Number,
default: 114
},
height: {
type: Number,
default: 34
},
topBottom: {
type: Number,
default: 3
},
leftRight: {
type: Number,
default: 3
},
color: {
type: String,
default: '#858585'
},
activeColor: {
type: String,
default: '#FFFFFF'
},
bgColor: {
type: String,
default: '#EDEDED'
},
activeBgColor: {
type: String,
default: '#F4A221'
},
transitionTime: {
type: [Number, String],
default: .5
}
},
data() {
return {
current: 0
}
},
computed: {
...mapState('map', ['mapType']),
switchStyles() {
return {
width: `${this.width * this.list.length + this.leftRight * 2}px`,
height: `${this.height + this.topBottom * 2}px`,
borderRadius: `${this.height + this.topBottom * 2 / 2}px`,
background: this.bgColor,
padding: `${this.topBottom} ${this.leftRight}px`
}
},
switchItemStyles() {
return {
width: `${this.width * this.list.length}px`,
top: `${this.topBottom}px`,
bottom: `${this.topBottom}px`,
left: `${this.leftRight}px`,
right: `${this.leftRight}px`
}
},
switchItemTextStyles() {
return {
width: `${this.width}px`,
height: `${this.height}px`,
transition: `color ${this.transitionTime}s`
}
},
switchActionStyles() {
return {
width: `${this.width}px`,
height: `${this.height}px`,
borderRadius: `${this.height / 2}px`,
background: this.activeBgColor,
marginLeft: `${this.width * this.current}px`,
transition: `margin-left ${this.transitionTime}s`,
top: `${this.topBottom}px`,
bottom: `${this.topBottom}px`,
left: `${this.leftRight}px`
}
}
},
methods: {
change(index) {
if (this.current == index) return
this.current = index
this.$emit('change', this.list[index])
}
}
}
</script>
<style lang="scss" scoped>
.switch{
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0px 0px 50px 0px #e4e6f0 inset;
position: relative;
&__item{
user-select: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: space-between
font-size: 16px;
font-weight: 500;
white-space: nowrap;
position: absolute;
z-index: 9;
&__text{
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
}
&__action{
user-select: none;
cursor: pointer;
pointer-events: none;
position: absolute;
z-index: 2;
}
}
</style>