多级互斥按钮的实现
本案例自定义了一个按钮组件, 按钮主要提供了多级点击效果, 按钮组间的按钮是互斥关系.
实现功能:
- 按钮互斥效果, 只有一个按钮处于激活状态
- 当功能按钮处于未选中时, 默认选中按钮(
default-checked
)处于激活状态 - 按钮可以设置多级点击, 并派发出 1, 2, 3...
- 可以设置快捷键,本例为
ESC
,f1
... - 本文的按钮样式也可参考, 渐变圆角边框以及斜切实现
按钮组件采用 typescript
编写
按钮组件
<template>
<div class="grade-button-component" :class="{'active-class': curGrade !== 0}" :style="{width,height}" @click="onClick">
<div class="content">
<div class="text">
<slot>按钮</slot>
<span>
{{ shortcut.toUpperCase() }}
</span>
</div>
<div v-if="gradeNum > 1" class="grade">
<div v-for="n in gradeNum" :key="n" :style="{background: curGrade >= n ? backGroundArr[(n-1)%backGroundArr.length]: null}" class="grade-item" />
</div>
</div>
</div>
</template>
<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator'
/* eslint-disable*/
enum KeyMap {
esc = 27,
f1 = 112,
f2 = 113,
f3 = 114,
f4 = 115,
f5 = 116,
f6 = 117,
f7 = 118,
f8 = 119,
f9 = 120,
}
/* eslint-enable */
@Component
export default class GradeButtonComponent extends Vue {
@Prop({ default: '120px' }) readonly width: string
@Prop({ default: '40px' }) readonly height: string
@Prop({ default: 1 }) readonly gradeNum: number
@Prop() readonly shortcut:string
private backGroundArr = ['#f3aa35', '#ff5507', '#e62242']
private curGrade = 0
onClick() {
this.curGrade++
if (this.curGrade > this.gradeNum) this.curGrade = 0
this.$emit('clickEvent', this.curGrade)
this.$parent.$children.forEach(cur => {
if (cur instanceof GradeButtonComponent) { // instanceof 类型保护
cur !== this && cur.reset()
if (this.curGrade === 0 && 'default-checked' in cur.$attrs) cur.curGrade = 1
}
})
}
reset() {
this.curGrade = 0
}
keyUpHandle(e) {
if (KeyMap[e.keyCode] === this.shortcut) {
e.preventDefault()
this.onClick()
return false
}
}
created() {
if ('default-checked' in this.$attrs) this.curGrade = 1
}
mounted() {
document.addEventListener('keydown', this.keyUpHandle, true)
}
beforeDestroy() {
document.removeEventListener('keydown', this.keyUpHandle)
}
}
</script>
<style lang="scss">
.grade-button-component {
display: flex;
align-items: center;
justify-content: center;
// border: 2px solid #DCDFE6;
background: linear-gradient(to right, #0d90c3, #0358ad);
border-radius: 5px;
overflow: hidden;
cursor: pointer;
transform: skew(-20deg);
.content {
display: flex;
width: calc(100% - 4px);
height: calc(100% - 4px);
background: #0E1829;
border-radius: 8px;
box-shadow: 0 0 25px rgba(7,117,188,0.8) inset;
// overflow: hidden;
.text {
transform: skew(20deg);
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
color: #ffffff;
font-size: 14px;
letter-spacing: 1px;
text-align: center;
span {
color: #28e3ff;
letter-spacing: 0;
}
}
.grade {
width: 8%;
height: 100%;
display: flex;
flex-direction: column-reverse;
&-item {
height: 100%;
border-left: 1px solid #0d92cb;
border-top: 1px solid #0d92cb;
&:first-of-type() {
border-bottom: none
}
&:last-of-type {
border-top: none
}
}
}
}
}
.active-class {
// border: 1px solid rgb(37, 64, 132);
// background: rgba(37, 64, 132, 0.2);
background: linear-gradient(to right, #ffbb38, #713b0c);
.content {
box-shadow: 0 0 20px rgba(255,187,56,.7) inset;
.text {
span {
color: #ffb849;
}
}
.grade {
&-item {
border-left: 1px solid #eeac34;
border-top: 1px solid #eeac34;
}
}
}
}
</style>
应用
在按钮组中,即按钮的父组件中
代码中省略了组件引入的相关代码
// 当然这里可以定义一个数组,使用v-for循环, 可以更加方便的配置快捷键
<div class="filter-nav">
<gardeButton default-checked :grade-num="1" shortcut="esc" @clickEvent="filterHandle('esc',$event)">重置</gardeButton>
<gardeButton :grade-num="3" shortcut="f1" @clickEvent="filterHandle('f1',$event)">边缘增强</gardeButton>
<gardeButton :grade-num="1" shortcut="f2" @clickEvent="filterHandle('f2',$event)">平滑处理</gardeButton>
<gardeButton :grade-num="1" shortcut="f3" @clickEvent="filterHandle('f3',$event)">有机物剔除</gardeButton>
<gardeButton :grade-num="1" shortcut="f4" @clickEvent="filterHandle('f4',$event)">无机物剔除</gardeButton>
<gardeButton :grade-num="1" shortcut="f5" @clickEvent="filterHandle('f5',$event)">黑白</gardeButton>
<gardeButton :grade-num="1" shortcut="f6" @clickEvent="filterHandle('f6',$event)">反色</gardeButton>
<gardeButton :grade-num="3" shortcut="f7" @clickEvent="filterHandle('f7',$event)">超级增强</gardeButton>
<gardeButton :grade-num="2" shortcut="f8" @clickEvent="filterHandle('f8',$event)">高能穿透</gardeButton>
<gardeButton :grade-num="1" shortcut="f9" @clickEvent="filterHandle('f9',$event)">低能穿透</gardeButton>
</div>
以上几个按钮是互斥关系, 并且实现了多级点击效果
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。