效果图
开发思路
小球就是一个伪类即可实现;左右滑动效果、背景渐变等,实际就是一个动画,css实现;父组件提供一个change事件,可以理解为在值发生改变时的回调函数;
html
<div
class="app-inputswitch"
(click
)="inClick()"
[ngClass
]="{'app-inputswitch-checked': value}">
<span
class="app-inputswitch-slider"></span
>
<span
class="app-inputswitch-text checked"
[hidden
]="!value">开
</span
>
<span
class="app-inputswitch-text"
[hidden
]="value">关
</span
>
</div
>
css
.app-inputswitch {
position: relative
;
display: inline-block
;
width: 3.5em
;
height: 1.75em
;
box-sizing: border-box
;
.app-inputswitch-slider {
position: absolute
;
cursor: pointer
;
left: 0
;
right: 0
;
top: 0
;
bottom: 0
;
border-radius: 30px
;
background-color: #ccc
;
transition: background-color .3s
;
&::before {
position: absolute
;
content: '';
height: 1.25em
;
width: 1.25em
;
left: .25em
;
bottom: .25em
;
background-color: #fff
;
border-radius: 50%
;
transition: .3s
;
}
}
&.app-inputswitch-checked {
.app-inputswitch-slider{
background-color: #007ad9
;
&::before{
transform: translateX(1.75em
);
}
}
}
.app-inputswitch-text {
position: absolute
;
cursor: pointer
;
font-size: 1em
;
right: .75em
;
color: #fff
;
top: 50%
;
user-select: none
;
transform: translateY(-50%
);
&.checked {
right: inherit
;
left: .75em
;
}
}
}
绝对定位的布局; 伪类实现圆球; transition,transform 实现动画效果;
布局小技巧,垂直对齐: top: 50%; transform: translateY(-50%);
ts
import { Component
, Input
, Output
, EventEmitter
} from '@angular/core';
@
Component({
selector
: 'app-input-switch',
templateUrl
: './input-switch.component.html',
styleUrls
: ['./input-switch.component.scss']
})
export class InputSwitchComponent {
@
Input() value
: boolean
;
@
Output() valueChange
= new EventEmitter<any
>();
@
Output() change
= new EventEmitter<any
>();
constructor() {
this.value
= false;
}
inClick() {
this.value
= !this.value
;
this.valueChange
.emit(this.value
);
this.change
.emit(this.value
);
}
}
@
Input() value
: boolean
;
@
Output() valueChange
= new EventEmitter<any
>();
this.valueChange
.emit(this.value
);
双向数据绑定要点: @Output输出属性的名称,是对应的@Input输入属性的名称加Change, 此处即为, value - - - valueChange
@
Output() change
= new EventEmitter<any
>();
this.change
.emit(this.value
);
这里就类似于vue的父子组件通信,on和emit,写法不一样而已;
测试示例
<div>
<h3>app-input-switch
</h3>
<h4>value - {{checked}}
</h4>
<app-input-switch (change)="btnChange($event)" [(value)]="checked"></app-input-switch>
</div>
双向绑定的写法; [()], 即为 双向的从视图到数据源再到视图。 事件写法,(change)事件,子通知父组件的事件通信,参数是 < $event >
btnChange(value
: boolean
) {
console
.log('btnChange-click: ' + value
);
}
控制台输出
有任何问题,留言或私信交流,共同进步。