You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
5.5 KiB
Vue

8 months ago
<template>
<view class="g_flex_column_center" :class="text ? 'u-switch-text' : 'e-switch'">
<view class="u-switch" :class="[value == true ? 'u-switch--on' : '', disabled ? 'u-switch--disabled' : '']" @tap="onClick"
:style="[switchStyle]">
<view class="u-switch__node node-class"
:style="{
'left':cusLeft + 'px',
'width':cusSize + 'px',
'height':cusSize + 'px',
'top':cusTop + 'px',
}"
>
<u-loading :show="loading" class="u-switch__loading" :size="size * 0.6" :color="loadingColor" />
</view>
<view class="g_flex_column_center"
style="font-size: 14px;height: 100%;line-height: 28px;color: #f5f5f5;zoom: 0.9;"
:style="{
'padding-right': value ? '0' : '7px',
'padding-left': value ? '7px' : '0px',
'text-align': value ? 'left' : 'right',
}"
>{{text}}</view>
</view>
</view>
</template>
<script>
/**
* switch 开关选择器
* @description 选择开关一般用于只有两个选择且只能选其一的场景
* @tutorial https://www.uviewui.com/components/switch.html
* @property {Boolean} loading 是否处于加载中默认false
* @property {Boolean} disabled 是否禁用默认false
* @property {String Number} size 开关尺寸单位rpx默认50
* @property {String} active-color 打开时的背景色默认#2979ff
* @property {Boolean} inactive-color 关闭时的背景色默认#ffffff
* @property {Boolean | Number | String} active-value 打开选择器时通过change事件发出的值默认true
* @property {Boolean | Number | String} inactive-value 关闭选择器时通过change事件发出的值默认false
* @event {Function} change 在switch打开或关闭时触发
* @example <u-switch v-model="checked" active-color="red" inactive-color="#eee"></u-switch>
*/
export default {
name: "u-switch",
props: {
cusTop:{
default: 1
},
cusLeft:{
default: 1
},
cusSize:{
default: 26
},
// 是否为加载中状态
loading: {
type: Boolean,
default: false
},
// 是否为禁用装填
disabled: {
type: Boolean,
default: false
},
// 开关尺寸单位rpx
size: {
type: [Number, String],
default: 50
},
// 打开时的背景颜色
activeColor: {
type: String,
default: '#2979ff'
},
// 关闭时的背景颜色
inactiveColor: {
type: String,
default: '#e5e5e5'
},
// 通过v-model双向绑定的值
value: {
type: Boolean,
default: false
},
// 是否使手机发生短促震动目前只在iOS的微信小程序有效(2020-05-06)
vibrateShort: {
type: Boolean,
default: false
},
// 打开选择器时的值
activeValue: {
type: [Number, String, Boolean],
default: true
},
// 关闭选择器时的值
inactiveValue: {
type: [Number, String, Boolean],
default: false
},
text:{
type: String,
default: ""
}
},
data() {
return {
}
},
computed: {
switchStyle() {
let style = {};
style.fontSize = this.size + 'rpx';
style.backgroundColor = this.value ? this.activeColor : this.inactiveColor;
return style;
},
loadingColor() {
return this.value ? this.activeColor : null;
}
},
methods: {
onClick() {
if (!this.disabled && !this.loading) {
// 使手机产生短促震动微信小程序有效APP(HX 2.6.8)和H5无效
if(this.vibrateShort) uni.vibrateShort();
this.$emit('input', !this.value);
// 放到下一个生命周期因为双向绑定的value修改父组件状态需要时间且是异步的
this.$nextTick(() => {
this.$emit('change', this.value ? this.activeValue : this.inactiveValue);
})
}
}
}
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.g_flex_column_center{
display: flex;
display: -webkit-flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: center;
}
.u-switch {
position: relative;
/* #ifndef APP-NVUE */
display: inline-block;
/* #endif */
box-sizing: initial;
width: 49px;
height: 28px;
background-color: #f5f5f5;
// border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 1em;
transition: background-color 0.3s;
font-size: 50rpx;
}
.u-switch__node {
@include vue-flex;
align-items: center;
justify-content: center;
position: absolute;
top: 1px;
left: 3rpx;
border-radius: 100%;
z-index: 1;
background-color: #fff;
// box-shadow: 0 3px 1px 0 rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.1), 0 3px 3px 0 rgba(0, 0, 0, 0.05);
// box-shadow: 0 3px 1px 0 rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.1), 0 3px 3px 0 rgba(0, 0, 0, 0.05);
transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05), -webkit-transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: transform cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05)
}
.u-switch--on .u-switch__node{
left:1px;
}
.u-switch__loading {
@include vue-flex;
align-items: center;
justify-content: center;
}
.u-switch--on {
background-color: #1989fa;
}
.u-switch--on .u-switch__node {
transform: translateX(80%);
}
.u-switch--disabled {
opacity: 0.4;
}
.u-switch-text{
.u-switch__node{
left: 1px;
}
.u-switch{
width: 60px;
// height: 1em;
height: 28px;
background-color: #fff;
border: 1px solid transparent;
}
.u-switch--on .u-switch__node {
transform: translateX(115%);
left:3px;
}
}
</style>