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/overflowmenu/overflowmenu'
|
||||||
import './components/slider/slider'
|
import './components/slider/slider'
|
||||||
import './components/prompt/prompt'
|
import './components/prompt/prompt'
|
||||||
|
import './components/prompt/prompt'
|
||||||
|
import './components/digicipher/digicipher'
|
||||||
|
import './components/pattern-view/pattern-view'
|
||||||
|
|
||||||
@customElement('settings-app')
|
@customElement('settings-app')
|
||||||
export class SettingsApp extends LitElement {
|
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 './overflowmenu/overflowmenu'
|
||||||
import './switch/switch'
|
import './switch/switch'
|
||||||
import './slider/slider'
|
import './slider/slider'
|
||||||
|
import './digicipher/digicipher'
|
||||||
|
import './pattern-view/pattern-view'
|
||||||
import './container/homescreen-container'
|
import './container/homescreen-container'
|
||||||
import './toast/toast'
|
import './toast/toast'
|
||||||
import './picker/picker'
|
import './picker/picker'
|
||||||
|
@ -116,7 +118,7 @@ export class PanelRoot extends LitElement {
|
||||||
type=${LiType.ICON_LABEL}
|
type=${LiType.ICON_LABEL}
|
||||||
label="开关"
|
label="开关"
|
||||||
icon="switch"
|
icon="switch"
|
||||||
iconcolor="black"
|
iconcolor="#EB7347"
|
||||||
href="#switch"
|
href="#switch"
|
||||||
></star-li>
|
></star-li>
|
||||||
<hr />
|
<hr />
|
||||||
|
@ -124,10 +126,26 @@ export class PanelRoot extends LitElement {
|
||||||
type=${LiType.ICON_LABEL}
|
type=${LiType.ICON_LABEL}
|
||||||
label="滑动条"
|
label="滑动条"
|
||||||
icon="scene"
|
icon="scene"
|
||||||
iconcolor="brown"
|
iconcolor="#EB7347"
|
||||||
href="#slider"
|
href="#slider"
|
||||||
></star-li>
|
></star-li>
|
||||||
<hr />
|
<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
|
<star-li
|
||||||
type=${LiType.ICON_LABEL}
|
type=${LiType.ICON_LABEL}
|
||||||
label="按钮"
|
label="按钮"
|
||||||
|
|
Loading…
Reference in New Issue