效果图
开发思路
- 小球就是一个伪类即可实现;
- 左右滑动效果、背景渐变等,实际就是一个动画,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>(); // emit到父组件的监听事件
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>(); // emit到父组件的监听事件
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);
}
控制台输出
有任何问题,留言或私信交流,共同进步。