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.

253 lines
5.6 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!-- 开关 -->
<template>
<view @click="onclick" class="d-inline-block tm-switch " >
<view class="tm-switch-wk relative " :style="[{width:width+'rpx',height:(height+4)+'rpx'}]">
<view class="tm-switch-bg round-l-24 round-r-24 flex-between"
:class="[bgColorCusjs,loaddingState?'opacity-7':'']"
>
<view class="text-size-xs tm-switch-txt text-align-center flex-center" style="width:50%">
<text>{{text[0]?text[0]:''}}</text>
</view>
<view class="text-size-xs tm-switch-txt text-align-center flex-center" style="width:50%">
<text class="pr-8">{{text[1]?text[1]:''}}</text>
</view>
</view>
<!-- bar -->
<view class="tm-switch-wk-bar absolute round-24 white flex-center "
:style="[
{transform:changValue?`translateX(${(width-(width/2+4))}rpx)`:`translateX(2rpx)`},
{width:(width/2-4)+'rpx',height:(height-4)+'rpx'}
]"
:class="[changValue?'shadow-'+color+'-10':'',changValue?'on aniOn':'aniOff']">
<text v-if="loaddingState" class="iconfont icon-loading" :class="[loaddingState?'load':'',`text-${color_tmeme}`]"></text>
</view>
</view>
</view>
</template>
<script>
/**
* 开关
* @property {String|Boolean} value = [true|false] 同v-model一样的值如果需要双向绑定需要value.sync推荐使用v-model
* @property {String|Number|Boolean|Object} name = [] 自定义数据change时携带。
* @property {Function} change {checked,value:携带的name数据}
* @property {Boolean} disabled = [true|false] 默认false, 禁用
* @property {String} color = [] 默认primary, 主题色
* @property {Boolean} black = [true|false] 默认false, 暗黑模式
* @property {Boolean} loadding = [true|false] 默认false, 是否加载中
* @property {Array} text = [true|false] 默认: ['开','关'], 左右两边的字符
* @property {Number} width = [] 默认100,单位rpx宽度
* @property {Number} height = [] 默认50,单位rpx高度
* @property {String} offBgcolor = [] 默认:'grey-lighten-2 text-grey', 主题色可以是文字色组合来改变文字和背景色.
* @example <tm-switch v-model="checked"></tm-switch>
*
*/
export default {
name: 'tm-switch',
model: {
prop: 'value',
event: 'input'
},
props:{
value:{
type:String|Boolean,
default:false
},
name:{
type:String|Number|Boolean|Object,
default:''
},
// 禁用。
disabled: {
type:Boolean|String,
default:false
},
loadding: {
type:Boolean|String,
default:false
},
color:{
type:String,
default:'primary'
},
// 暗黑
black: {
type:Boolean|String,
default:null
},
// 左右两边的字符。
text:{
type:Array,
default:()=>{
return ['开','关']
}
},
width:{
type:String|Number,
default:100
},
height:{
type:String|Number,
default:50
},
offBgcolor:{
type:String,
default:'grey-lighten-2 text-grey'
},
// 跟随主题色的改变而改变。
fllowTheme:{
type:Boolean|String,
default:true
}
},
watch: {
value: function(newval, oldval) {
if (newval !== oldval) {
if (!this.jiancMax()) {
this.changValue = false;
return;
}
}
}
},
computed: {
black_tmeme: function() {
if (this.black !== null) return this.black;
return this.$tm.vx.state().tmVuetify.black;
},
color_tmeme:function(){
if(this.$tm.vx.state().tmVuetify.color!==null&&this.$tm.vx.state().tmVuetify.color && this.fllowTheme){
return this.$tm.vx.state().tmVuetify.color;
}
return this.color;
},
changValue: {
get: function() {
return this.value;
},
set: function(newValue) {
this.$emit('input', newValue)
// 如果不想用v-model. 直接使用value,需要:value.sync
this.$emit('update:value', newValue);
}
},
loaddingState:function(){
return this.loadding;
},
bgColorCusjs(){
if(this.disabled) {
if(this.black_tmeme){
return 'grey-darken-4 bk';
}else{
return this.color_tmeme+' opacity-5';
}
}
if(this.black_tmeme){
if(this.changValue) return this.color_tmeme + ' bk ';
if(!this.changValue) return 'grey-darken-1 bk ';
}else{
if(this.changValue) return this.color_tmeme + ' text-white ';
if(!this.changValue) return this.offBgcolor;
}
}
},
data() {
return {
animationOn:null,
animationOff:null,
aniData:null,
};
},
mounted() {
},
methods: {
// 检查是否超过了最大选择。
jiancMax() {
if(this.disabled) return false;
return true;
},
onclick(e) {
if (this.disabled||this.loaddingState) return;
if (!this.jiancMax()) {
return;
}
this.changValue = !this.changValue;
this.change();
},
change() {
this.$nextTick(function(){
this.$emit('change', {
checked: this.changValue,
value: this.name
});
})
}
},
}
</script>
<style lang="scss" scoped>
.tm-switch{
vertical-align: middle;
.tm-switch-wk{
// width: 100rpx;
// height: 52rpx;
}
.tm-switch-bg{
width: 100%;
height: 100%;
transition: all 0.5s;
.tm-switch-txt{
// width: 50upx;
height: 100%;
// line-height: 48upx;
}
}
.tm-switch-wk-bar{
left: 4rpx;
top: 4rpx;
// width:40rpx;
// height: 46rpx;
transition: all 0.35s ease-in-out;
.load{
animation: xhRote 0.8s infinite linear;
}
}
}
.aniOn{
left: inherit;
}
.aniOff{
right: inherit;
}
@keyframes xhRote{
0%{
transform: rotate(0deg);
}
100%{
transform: rotate(360deg);
}
}
</style>