TASK: #111576 按键解锁组件化完成
This commit is contained in:
parent
aa1cc92678
commit
a53ca1ae9c
|
@ -0,0 +1,14 @@
|
|||
# 数字密码-digicipher
|
||||
|
||||
工作职责:
|
||||
|
||||
- 由0-9数字组成的数字密码
|
||||
- 默认密码为 `123456`
|
||||
- 点击数字反馈,输入成功上滑,输入错误抖动反馈
|
||||
|
||||
## 使用
|
||||
|
||||
```
|
||||
<star-digicipher></star-digicipher>
|
||||
```
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
import {css, CSSResult} from 'lit'
|
||||
export const sharedStyles: CSSResult = css`
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
user-select: none;
|
||||
}
|
||||
p,
|
||||
button,
|
||||
i,
|
||||
h2,
|
||||
.cancel,
|
||||
.delete {
|
||||
font-family: 'OPPOSans';
|
||||
margin-top: 0;
|
||||
color: #292929;
|
||||
}
|
||||
span {
|
||||
position: relative;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
margin-right: 20px;
|
||||
background: #000000;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
p {
|
||||
position: absolute;
|
||||
font-family: 'OPPOSans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
color: #292929;
|
||||
}
|
||||
|
||||
#zero {
|
||||
position: absolute;
|
||||
left: 44.15%;
|
||||
top: 70%;
|
||||
}
|
||||
button {
|
||||
position: relative;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
/*button背景无色*/
|
||||
background: rgba(0, 0, 0, 0);
|
||||
display: inline-block;
|
||||
font-size: 35px;
|
||||
}
|
||||
|
||||
/*按钮点击的效果*/
|
||||
button::before {
|
||||
content: '';
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 1px;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
border-radius: 50%;
|
||||
background-color: #ffffff;
|
||||
opacity: 0.35;
|
||||
}
|
||||
|
||||
.block::before {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#slideUp {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.topText {
|
||||
font-size: 20px;
|
||||
height: 26.5px;
|
||||
line-height: 26.5px;
|
||||
width: 80px;
|
||||
left: calc(50% - 80px / 2 + 3px);
|
||||
top: calc(50% - 26.5px / 2 - 168.75px);
|
||||
}
|
||||
.spanContainer {
|
||||
position: absolute;
|
||||
left: 206px;
|
||||
top: 349.5px;
|
||||
}
|
||||
.grid {
|
||||
position: absolute;
|
||||
display: grid;
|
||||
grid-template-areas: '1 2 3 ' '4 5 6' '7 8 9' '. 0 .';
|
||||
grid-gap: 20px;
|
||||
margin: 404px 176px;
|
||||
}
|
||||
|
||||
.cancel,
|
||||
.delete {
|
||||
position: absolute;
|
||||
font-family: 'OPPOSans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
color: #292929;
|
||||
width: 36px;
|
||||
height: 23.5px;
|
||||
line-height: 23.5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
.cancel {
|
||||
left: calc(50% - 36px / 2 - 90px);
|
||||
top: calc(50% - 23.5px / 2 + 231.75px);
|
||||
}
|
||||
.delete {
|
||||
left: calc(50% - 36px / 2 + 90px);
|
||||
top: calc(50% - 23.5px / 2 + 231.75px);
|
||||
}
|
||||
.cancel:hover,
|
||||
.delete:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
.cancel:active,
|
||||
.delete:active {
|
||||
color: #777;
|
||||
transition: color 0.5s;
|
||||
}
|
||||
|
||||
/*抖动反馈*/
|
||||
@keyframes errtips {
|
||||
10% {
|
||||
transform: translateY(2px);
|
||||
}
|
||||
20% {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
30% {
|
||||
transform: translateY(2px);
|
||||
}
|
||||
40% {
|
||||
transform: translateY(2px);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
60% {
|
||||
transform: translateY(2px);
|
||||
}
|
||||
70% {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
80% {
|
||||
transform: translateY(2px);
|
||||
}
|
||||
90% {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*密码输入正确后动效*/
|
||||
@keyframes suctip {
|
||||
0% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(-1000px);
|
||||
}
|
||||
}
|
||||
`
|
|
@ -0,0 +1,152 @@
|
|||
import {html, LitElement, CSSResultArray} from 'lit'
|
||||
import {customElement, property, query, queryAll} from 'lit/decorators.js'
|
||||
import {sharedStyles} from './digicipher-style'
|
||||
|
||||
@customElement('star-digicipher')
|
||||
export class StarLockNumber extends LitElement {
|
||||
public static override get styles(): CSSResultArray {
|
||||
return [sharedStyles]
|
||||
}
|
||||
@query('#slideUp') slideUp!: HTMLDivElement
|
||||
@queryAll('button') buttons!: NodeListOf<HTMLButtonElement>
|
||||
@query('zero') zero!: HTMLButtonElement
|
||||
@queryAll('span') span!: NodeListOf<HTMLSpanElement>
|
||||
@query('spanContainer') spanContainer!: HTMLDivElement
|
||||
@query('#parent') parent!: HTMLDivElement
|
||||
@query('.delete') _delete!: HTMLParagraphElement
|
||||
@query('.cancel') cancel!: HTMLParagraphElement
|
||||
@query('.topText') topText!: HTMLParagraphElement
|
||||
@query('.screen') screen!: HTMLDivElement
|
||||
|
||||
@property({type: Number}) clicks = 0
|
||||
@property({type: Number}) _number = 0
|
||||
@property({type: Number}) clickNumber = 0
|
||||
@property({type: String}) color = ''
|
||||
@property({type: String}) opacity = ''
|
||||
@property({type: String}) guess = ''
|
||||
@property({type: String}) passwd = '123456'
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div id="slideUp">
|
||||
<p class="topText">输入密码</p>
|
||||
<div class="spanContainer">
|
||||
<span id="sOne"></span>
|
||||
<span id="sTwo"></span>
|
||||
<span id="sThree"></span>
|
||||
<span id="sFour"></span>
|
||||
<span id="sFive"></span>
|
||||
<span id="sSix"></span>
|
||||
</div>
|
||||
<div
|
||||
id="parent"
|
||||
@touchstart=${this.touchStart}
|
||||
@touchend=${this.touchEnd}
|
||||
>
|
||||
<button class="0" id="zero" data-num="0">0</button>
|
||||
<div class="grid">
|
||||
<button data-num="1">1</button>
|
||||
<button data-num="2">2</button>
|
||||
<button data-num="3">3</button>
|
||||
<button data-num="4">4</button>
|
||||
<button data-num="5">5</button>
|
||||
<button data-num="6">6</button>
|
||||
<button data-num="7">7</button>
|
||||
<button data-num="8">8</button>
|
||||
<button data-num="9">9</button>
|
||||
</div>
|
||||
<p class="cancel" id="lockCancel">取消</p>
|
||||
<p class="delete">删除</p>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
touchStart(e: TouchEvent) {
|
||||
e.preventDefault()
|
||||
// console.log('e.target', (e.target as HTMLElement).dataset.num)
|
||||
// console.log('click', this.clickNumber)
|
||||
// 点击数字,圆点变色并输出
|
||||
if ((e.target as Element).tagName === 'BUTTON') {
|
||||
this.clickNumber = Number((e.target as HTMLElement).dataset.num)
|
||||
this.makeZero()
|
||||
//点击反馈
|
||||
this.changeNumberBgColor()
|
||||
if (this.clicks < 6) {
|
||||
//圆点变化
|
||||
this.changeBgColor('#333333', this.clicks, 1)
|
||||
this.clicks += 1
|
||||
this.guess += (e.target as HTMLElement).dataset.num
|
||||
console.log('输入后为:', this.guess)
|
||||
}
|
||||
//密码错误
|
||||
if (this.clicks == 6 && this.guess !== this.passwd) {
|
||||
console.log('密码错误')
|
||||
// 抖动反馈
|
||||
for (let i = 0; i < 10; i++) {
|
||||
this.buttons[i].style.setProperty('animation', 'errtips .5s')
|
||||
}
|
||||
//清空密码且删除抖动反馈
|
||||
for (let i = 0; i < 6; i++) {
|
||||
this.changeBgColor('#000000', i, 0.2)
|
||||
}
|
||||
this.guess = ''
|
||||
this.clicks = 0
|
||||
}
|
||||
} else if ((e.target as Element).className === 'delete') {
|
||||
if (this.clicks == 0) {
|
||||
console.log('不可再删除')
|
||||
} else {
|
||||
this.clicks -= 1
|
||||
this.changeBgColor('#000000', this.clicks, 0.2)
|
||||
this.guess = this.guess.slice(0, -1)
|
||||
console.log('删除后为:', this.guess)
|
||||
}
|
||||
} else if ((e.target as Element).className === 'cancel') {
|
||||
//点击取消,返回锁屏
|
||||
console.log('返回锁屏')
|
||||
// this.makeZero()
|
||||
for (let i = 0; i < 6; i++) {
|
||||
this.changeBgColor('#000000', i, 0.2)
|
||||
}
|
||||
this.guess = ''
|
||||
this.clicks = 0
|
||||
}
|
||||
if (this.guess === this.passwd) {
|
||||
for (let j = 0; j < 10; j++) {
|
||||
this.buttons[j].removeAttribute('style')
|
||||
}
|
||||
console.log('密码正确')
|
||||
// this.slideUp.removeAttribute('style')
|
||||
for (let i = 0; i < 6; i++) {
|
||||
this.changeBgColor('#000000', i, 0.2)
|
||||
}
|
||||
this.guess = ''
|
||||
this.clicks = 0
|
||||
this.slideUp.style.setProperty('animation', 'suctip .6s')
|
||||
}
|
||||
}
|
||||
touchEnd(e: TouchEvent) {
|
||||
if ((e.target as Element).tagName === 'BUTTON') {
|
||||
this.removeNumberBgColor()
|
||||
}
|
||||
}
|
||||
|
||||
changeBgColor(color: string, _number: number, opacity: number) {
|
||||
this.span[_number].style.backgroundColor = color
|
||||
this.span[_number].style.opacity = String(opacity)
|
||||
}
|
||||
removeNumberBgColor() {
|
||||
this.buttons[this.clickNumber].classList.remove('block')
|
||||
}
|
||||
changeNumberBgColor() {
|
||||
this.buttons[this.clickNumber].classList.add('block')
|
||||
}
|
||||
makeZero() {
|
||||
//抖动、滑动属性清零
|
||||
this.slideUp.removeAttribute('style')
|
||||
for (let j = 0; j < 10; j++) {
|
||||
this.buttons[j].removeAttribute('style')
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,9 @@ import './components/picker/picker'
|
|||
import './components/overflowmenu/overflowmenu'
|
||||
import './components/slider/slider'
|
||||
import './components/prompt/prompt'
|
||||
import './components/prompt/prompt'
|
||||
import './components/digicipher/digicipher'
|
||||
import './components/pattern-view/pattern-view'
|
||||
|
||||
@customElement('settings-app')
|
||||
export class SettingsApp extends LitElement {
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import {html, LitElement, css} from 'lit'
|
||||
import {customElement, property} from 'lit/decorators.js'
|
||||
import '../icon/icon'
|
||||
|
||||
@customElement('panel-digicipher')
|
||||
export class PanelDigicipher extends LitElement {
|
||||
static styles = css`
|
||||
.screen {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: rgb(124, 194, 235);
|
||||
}
|
||||
`
|
||||
render() {
|
||||
return html`
|
||||
<div class="screen">
|
||||
<star-digicipher></star-digicipher>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'panel-digicipher': PanelDigicipher
|
||||
}
|
||||
}
|
|
@ -20,6 +20,8 @@ import './confirm/confirm'
|
|||
import './overflowmenu/overflowmenu'
|
||||
import './switch/switch'
|
||||
import './slider/slider'
|
||||
import './digicipher/digicipher'
|
||||
import './pattern-view/pattern-view'
|
||||
import './container/homescreen-container'
|
||||
import './toast/toast'
|
||||
import './picker/picker'
|
||||
|
@ -116,7 +118,7 @@ export class PanelRoot extends LitElement {
|
|||
type=${LiType.ICON_LABEL}
|
||||
label="开关"
|
||||
icon="switch"
|
||||
iconcolor="black"
|
||||
iconcolor="#EB7347"
|
||||
href="#switch"
|
||||
></star-li>
|
||||
<hr />
|
||||
|
@ -124,10 +126,26 @@ export class PanelRoot extends LitElement {
|
|||
type=${LiType.ICON_LABEL}
|
||||
label="滑动条"
|
||||
icon="scene"
|
||||
iconcolor="brown"
|
||||
iconcolor="#EB7347"
|
||||
href="#slider"
|
||||
></star-li>
|
||||
<hr />
|
||||
<star-li
|
||||
type=${LiType.ICON_LABEL}
|
||||
label="Digicipher"
|
||||
icon="lock"
|
||||
iconcolor="#EB7347"
|
||||
href="#digicipher"
|
||||
></star-li>
|
||||
<hr />
|
||||
<star-li
|
||||
type=${LiType.ICON_LABEL}
|
||||
label="PatternView"
|
||||
icon="lock"
|
||||
iconcolor="#EB7347"
|
||||
href="#pattern-view"
|
||||
></star-li>
|
||||
<hr />
|
||||
<star-li
|
||||
type=${LiType.ICON_LABEL}
|
||||
label="按钮"
|
||||
|
|
Loading…
Reference in New Issue