¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view |
| | | class="u-switch" |
| | | :class="[disabled && 'u-switch--disabled']" |
| | | :style="[switchStyle, $u.addStyle(customStyle)]" |
| | | @tap="clickHandler" |
| | | > |
| | | <view |
| | | class="u-switch__bg" |
| | | :style="[bgStyle]" |
| | | > |
| | | </view> |
| | | <view |
| | | class="u-switch__node" |
| | | :class="[value && 'u-switch__node--on']" |
| | | :style="[nodeStyle]" |
| | | ref="u-switch__node" |
| | | > |
| | | <u-loading-icon |
| | | :show="loading" |
| | | mode="circle" |
| | | timingFunction='linear' |
| | | :color="value ? activeColor : '#AAABAD'" |
| | | :size="size * 0.6" |
| | | /> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import props from './props.js'; |
| | | /** |
| | | * switch å¼å
³éæ©å¨ |
| | | * @description éæ©å¼å
³ä¸è¬ç¨äºåªæä¸¤ä¸ªéæ©ï¼ä¸åªè½éå
¶ä¸çåºæ¯ã |
| | | * @tutorial https://www.uviewui.com/components/switch.html |
| | | * @property {Boolean} loading æ¯å¦å¤äºå è½½ä¸ï¼é»è®¤ false ï¼ |
| | | * @property {Boolean} disabled æ¯å¦ç¦ç¨ï¼é»è®¤ false ï¼ |
| | | * @property {String | Number} size å¼å
³å°ºå¯¸ï¼åä½px ï¼é»è®¤ 25 ï¼ |
| | | * @property {String} activeColor æå¼æ¶çèæ¯è² ï¼é»è®¤ '#2979ff' ï¼ |
| | | * @property {String} inactiveColor å
³éæ¶çèæ¯è² ï¼é»è®¤ '#ffffff' ï¼ |
| | | * @property {Boolean | String | Number} value éè¿v-modelååç»å®çå¼ ï¼é»è®¤ false ï¼ |
| | | * @property {Boolean | String | Number} activeValue æå¼éæ©å¨æ¶éè¿changeäºä»¶ååºçå¼ ï¼é»è®¤ true ï¼ |
| | | * @property {Boolean | String | Number} inactiveValue å
³é鿩卿¶éè¿changeäºä»¶ååºçå¼ ï¼é»è®¤ false ï¼ |
| | | * @property {Boolean} asyncChange æ¯å¦å¼å¯å¼æ¥åæ´ï¼å¼å¯åéè¦æå¨æ§å¶è¾å
¥å¼ ï¼é»è®¤ false ï¼ |
| | | * @property {String | Number} space åç¹ä¸å¤è¾¹æ¡çè·ç¦» ï¼é»è®¤ 0 ï¼ |
| | | * @property {Object} customStyle å®ä¹éè¦ç¨å°çå¤é¨æ ·å¼ |
| | | * |
| | | * @event {Function} change å¨switchæå¼æå
³éæ¶è§¦å |
| | | * @example <u-switch v-model="checked" active-color="red" inactive-color="#eee"></u-switch> |
| | | */ |
| | | export default { |
| | | name: "u-switch", |
| | | mixins: [uni.$u.mpMixin, uni.$u.mixin,props], |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(n) { |
| | | if(n !== this.inactiveValue && n !== this.activeValue) { |
| | | uni.$u.error('v-modelç»å®çå¼å¿
须为inactiveValueãactiveValueäºè
ä¹ä¸') |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | bgColor: '#ffffff' |
| | | } |
| | | }, |
| | | computed: { |
| | | isActive(){ |
| | | return this.value === this.activeValue; |
| | | }, |
| | | switchStyle() { |
| | | let style = {} |
| | | // è¿ééè¦å 2ï¼æ¯ä¸ºäºè
¾åºè¾¹æ¡çè·ç¦»ï¼å¦ååç¹nodeä¼åå¤è¾¹æ¡ç´§è´´å¨ä¸èµ· |
| | | style.width = uni.$u.addUnit(this.size * 2 + 2) |
| | | style.height = uni.$u.addUnit(Number(this.size) + 2) |
| | | // style.borderColor = this.value ? 'rgba(0, 0, 0, 0)' : 'rgba(0, 0, 0, 0.12)' |
| | | // 妿èªå®ä¹äºâéæ¿æ´»âæ¼ç¤ºï¼nameè¾¹æ¡é¢è²è®¾ç½®ä¸ºéæ(è·éæ¿æ´»é¢è²ä¸è´) |
| | | // è¿éä¸è½ç®åçè®¾ç½®ä¸ºéæ¿æ´»çé¢è²ï¼å¦åæå¼ç¶ææ¶ï¼ä¼æè¾¹æ¡ï¼æä»¥éè¦éæ |
| | | if(this.customInactiveColor) { |
| | | style.borderColor = 'rgba(0, 0, 0, 0)' |
| | | } |
| | | style.backgroundColor = this.isActive ? this.activeColor : this.inactiveColor |
| | | return style; |
| | | }, |
| | | nodeStyle() { |
| | | let style = {} |
| | | // 妿èªå®ä¹éæ¿æ´»é¢è²ï¼å°nodeåç¹ç尺寸åå°ä¸¤ä¸ªåç´ ï¼è®©å
¶ä¸å¤è¾¹æ¡è·ç¦»æ´å¤§ä¸ç¹ |
| | | style.width = uni.$u.addUnit(this.size - this.space) |
| | | style.height = uni.$u.addUnit(this.size - this.space) |
| | | const translateX = this.isActive ? uni.$u.addUnit(this.space) : uni.$u.addUnit(this.size); |
| | | style.transform = `translateX(-${translateX})` |
| | | return style |
| | | }, |
| | | bgStyle() { |
| | | let style = {} |
| | | // è¿éé
ç½®ä¸ä¸ªå¤ä½çå
ç´ å¨HTMLä¸ï¼æ¯ä¸ºäºè®©switch忢æ¶ï¼ææ´è¯å¥½çèæ¯è²æ©å
ä½éª(è§å®é
ææ) |
| | | style.width = uni.$u.addUnit(Number(this.size) * 2 - this.size / 2) |
| | | style.height = uni.$u.addUnit(this.size) |
| | | style.backgroundColor = this.inactiveColor |
| | | // æå¼æ¶ï¼è®©æ¤å
ç´ æ¶ç¼©ï¼å¦ååä¹ |
| | | style.transform = `scale(${this.isActive ? 0 : 1})` |
| | | return style |
| | | }, |
| | | customInactiveColor() { |
| | | // 乿以éè¦å¤ææ¯å¦èªå®ä¹äºâéæ¿æ´»âé¢è²ï¼æ¯ä¸ºäºè®©nodeåç¹ç¦»å¤è¾¹æ¡æ´å®½ä¸ç¹çè·ç¦» |
| | | return this.inactiveColor !== '#fff' && this.inactiveColor !== '#ffffff' |
| | | } |
| | | }, |
| | | methods: { |
| | | clickHandler() { |
| | | if (!this.disabled && !this.loading) { |
| | | const oldValue = this.isActive ? this.inactiveValue : this.activeValue |
| | | if(!this.asyncChange) { |
| | | this.$emit('input', oldValue) |
| | | } |
| | | // æ¾å°ä¸ä¸ä¸ªçå½å¨æï¼å 为ååç»å®çvalueä¿®æ¹ç¶ç»ä»¶ç¶æéè¦æ¶é´ï¼ä¸æ¯å¼æ¥ç |
| | | this.$nextTick(() => { |
| | | this.$emit('change', oldValue) |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | @import "../../libs/css/components.scss"; |
| | | |
| | | .u-switch { |
| | | @include flex(row); |
| | | /* #ifndef APP-NVUE */ |
| | | box-sizing: border-box; |
| | | /* #endif */ |
| | | position: relative; |
| | | background-color: #fff; |
| | | border-width: 1px; |
| | | border-radius: 100px; |
| | | transition: background-color 0.4s; |
| | | border-color: rgba(0, 0, 0, 0.12); |
| | | border-style: solid; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | // ç±äºweex为é¿ééçç©çKPI项ç®ï¼å¯¼è´bugå¥å¤ï¼è¿å¿
é¡»è¦åè¿ä¸è¡ï¼ |
| | | // å¦åå¨iOSä¸ï¼ç¹å»é¡µé¢ä»»æå°æ¹ï¼é½ä¼è§¦åswitchçç¹å»äºä»¶ |
| | | overflow: hidden; |
| | | |
| | | &__node { |
| | | @include flex(row); |
| | | align-items: center; |
| | | justify-content: center; |
| | | border-radius: 100px; |
| | | background-color: #fff; |
| | | border-radius: 100px; |
| | | box-shadow: 1px 1px 1px 0 rgba(0, 0, 0, 0.25); |
| | | transition-property: transform; |
| | | transition-duration: 0.4s; |
| | | transition-timing-function: cubic-bezier(0.3, 1.05, 0.4, 1.05); |
| | | } |
| | | |
| | | &__bg { |
| | | position: absolute; |
| | | border-radius: 100px; |
| | | background-color: #FFFFFF; |
| | | transition-property: transform; |
| | | transition-duration: 0.4s; |
| | | border-top-left-radius: 0; |
| | | border-bottom-left-radius: 0; |
| | | transition-timing-function: ease; |
| | | } |
| | | |
| | | &--disabled { |
| | | opacity: 0.6; |
| | | } |
| | | } |
| | | </style> |