Merge pull request #41 in YR/star-web-components from feature-component-pattern to master
* commit '7596c5db719cd5dbd282564fd140c502c9d38f9e': TASK: #111576 图案密码组件化
This commit is contained in:
commit
c1d7721430
|
@ -0,0 +1,32 @@
|
|||
# 图案密码 pattern-view
|
||||
|
||||
|
||||
工作职责:
|
||||
|
||||
- 由九宫圆圈组成的图案密码
|
||||
- 默认密码为 `012543` (滑动如下图)
|
||||
```
|
||||
--- --- ---
|
||||
| * | **** | * | **** | * |
|
||||
--- --- ---
|
||||
*
|
||||
--- --- ---
|
||||
| * | **** | * | **** | * |
|
||||
--- --- ---
|
||||
|
||||
--- --- ---
|
||||
| | | | | |
|
||||
--- --- ---
|
||||
```
|
||||
- 点击数字反馈,输入成功上滑,输入错误抖动反馈
|
||||
|
||||
### 默认
|
||||
```
|
||||
<star-pattern-view></star-pattern-view>
|
||||
```
|
||||
### 距离顶部的位置 `topDir` 默认`217.5px`
|
||||
```
|
||||
<star-pattern-view topDir="300px"></star-pattern-view>
|
||||
<star-pattern-view topDir="-100px"></star-pattern-view>
|
||||
|
||||
```
|
|
@ -0,0 +1,78 @@
|
|||
import {css, CSSResult} from 'lit'
|
||||
export const sharedStyles: CSSResult = css`
|
||||
.bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-image: url(../assets/backgroud.png);
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
background-position: top;
|
||||
}
|
||||
|
||||
.groundGlass {
|
||||
display: none;
|
||||
position: relative;
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
line-height: 100%;
|
||||
color: #fff;
|
||||
font-size: 30px;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.bg ::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -100%;
|
||||
left: -100%;
|
||||
right: -100%;
|
||||
bottom: -100%;
|
||||
background-image: url(../assets/backgroud.png);
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
background-size: cover;
|
||||
background-position: top;
|
||||
filter: blur(10px);
|
||||
z-index: -2;
|
||||
}
|
||||
|
||||
.bg ::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(217, 217, 217, 0.65);
|
||||
z-index: -1;
|
||||
}
|
||||
/* canvas{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 11%;
|
||||
right:0;
|
||||
bottom:0;
|
||||
margin:auto;
|
||||
} */
|
||||
/* #lockCancel {
|
||||
position: absolute;
|
||||
width: 50px;
|
||||
height: 30px;
|
||||
left: calc(50% - 50px/2);
|
||||
top: calc(81.5%);
|
||||
font-family: 'OPPOSans';
|
||||
font-weight: 900;
|
||||
font-size: 14px;
|
||||
line-height: 30px;
|
||||
color: #292929;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
} */
|
||||
`
|
|
@ -0,0 +1,190 @@
|
|||
import {html, LitElement, css, PropertyValueMap} from 'lit'
|
||||
import {customElement, property, query} from 'lit/decorators.js'
|
||||
// import {sharedStyles} from './pattern-view-style'
|
||||
|
||||
@customElement('star-pattern-view')
|
||||
export class StarPatternView extends LitElement {
|
||||
_topDir: string = ''
|
||||
_getRed: boolean = false
|
||||
static styles = css`
|
||||
:host {
|
||||
--top-dir: 217.5px;
|
||||
}
|
||||
canvas {
|
||||
margin-top: var(--top-dir);
|
||||
}
|
||||
`
|
||||
// public static override get styles(): CSSResultArray {
|
||||
// return [sharedStyles]
|
||||
// }
|
||||
@query('canvas') canvas!: HTMLCanvasElement
|
||||
@property({attribute: false}) cxt!: CanvasRenderingContext2D
|
||||
@property({type: Boolean})
|
||||
get getRed() {
|
||||
return this._getRed
|
||||
}
|
||||
set getRed(value) {
|
||||
if (this._getRed !== value) {
|
||||
this._getRed = value
|
||||
this.Draw()
|
||||
}
|
||||
}
|
||||
@property({type: Number}) top = 0
|
||||
@property({type: Number}) R = 35
|
||||
@property({type: Number}) X = 0
|
||||
@property({type: Number}) Y = 0
|
||||
@property({type: Number}) canvasWidth = document.body.offsetWidth
|
||||
@property({type: Number}) canvasHeight = document.body.offsetWidth
|
||||
@property({type: Number}) OffsetX = document.body.offsetWidth / 3.5
|
||||
@property({type: Number}) OffsetY = document.body.offsetWidth / 3.5
|
||||
@property({type: Array}) circleArr: {X: number; Y: number}[] = []
|
||||
@property({type: Array}) pwdArr: number[] = []
|
||||
@property({type: Array}) passwdArr = [0, 1, 2, 5, 4, 3]
|
||||
@property({type: String})
|
||||
get topDir() {
|
||||
return this._topDir
|
||||
}
|
||||
set topDir(value: string) {
|
||||
this.style.setProperty('--top-dir', value)
|
||||
this._topDir = value
|
||||
this.top = parseInt(this._topDir)
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<!-- <div style="height:200px;background-color:red"></div> -->
|
||||
<canvas
|
||||
id="canvas"
|
||||
@touchstart=${this.touchStart}
|
||||
@touchmove=${this.touchMove}
|
||||
@touchend=${this.touchEnd}
|
||||
></canvas>
|
||||
`
|
||||
}
|
||||
|
||||
protected firstUpdated(
|
||||
_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>
|
||||
): void {
|
||||
this.top = this.top ? this.top : 217.5
|
||||
//canvas的高度和宽度都是
|
||||
this.canvas.width = this.canvasWidth
|
||||
this.canvas.height = this.canvasHeight
|
||||
//getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性。
|
||||
this.cxt = this.canvas.getContext('2d')!
|
||||
this.X = (this.canvasWidth - 2 * this.OffsetX - this.R * 2 * 3) / 2
|
||||
this.Y = (this.canvasHeight - 2 * this.OffsetY - this.R * 2 * 3) / 2
|
||||
this.createCirclePoint(this.X, this.Y)
|
||||
this.Draw()
|
||||
}
|
||||
|
||||
createCirclePoint(diffX: number, diffY: number) {
|
||||
for (var row = 0; row < 3; row++) {
|
||||
for (var col = 0; col < 3; col++) {
|
||||
// 计算圆心坐标
|
||||
var Point = {
|
||||
X: this.OffsetX + col * diffX + (col * 2 + 1) * this.R,
|
||||
Y: this.OffsetY + row * diffY + (row * 2 + 1) * this.R,
|
||||
}
|
||||
this.circleArr.push(Point)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Draw(touchPoint?: {X: any; Y: any}) {
|
||||
if (this.pwdArr.length > 1) {
|
||||
this.cxt.beginPath()
|
||||
for (var i = 0; i < this.pwdArr.length; i++) {
|
||||
var pointIndex = this.pwdArr[i]
|
||||
this.cxt.lineTo(
|
||||
this.circleArr[pointIndex].X,
|
||||
this.circleArr[pointIndex].Y
|
||||
)
|
||||
}
|
||||
//锁屏线
|
||||
this.cxt.lineWidth = 2
|
||||
this.cxt.strokeStyle = this.getRed ? '#FF4040' : '#333333'
|
||||
this.cxt.stroke()
|
||||
this.cxt.closePath()
|
||||
if (touchPoint != null) {
|
||||
var lastPointIndex = this.pwdArr[this.pwdArr.length - 1]
|
||||
var lastPoint = this.circleArr[lastPointIndex]
|
||||
this.cxt.beginPath()
|
||||
this.cxt.moveTo(lastPoint.X, lastPoint.Y)
|
||||
this.cxt.lineTo(touchPoint.X, touchPoint.Y)
|
||||
this.cxt.stroke()
|
||||
this.cxt.closePath()
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < this.circleArr.length; i++) {
|
||||
var Point = this.circleArr[i]
|
||||
//大圆
|
||||
this.cxt.fillStyle = 'rgb(51,51,51,0.08)'
|
||||
this.cxt.beginPath()
|
||||
this.cxt.arc(Point.X, Point.Y, this.R, 0, Math.PI * 2, true)
|
||||
this.cxt.closePath()
|
||||
this.cxt.fill()
|
||||
//小圆
|
||||
this.cxt.fillStyle = 'rgb(51,51,51,0.2)'
|
||||
this.cxt.beginPath()
|
||||
this.cxt.arc(Point.X, Point.Y, this.R - 26, 0, Math.PI * 2, true)
|
||||
this.cxt.closePath()
|
||||
this.cxt.fill()
|
||||
//滑动后小圆的颜色
|
||||
if (this.pwdArr.indexOf(i) >= 0) {
|
||||
this.cxt.fillStyle = this.getRed ? '#FF4040' : '#333333'
|
||||
this.cxt.beginPath()
|
||||
this.cxt.arc(Point.X, Point.Y, this.R - 26, 0, Math.PI * 2, true)
|
||||
this.cxt.closePath()
|
||||
this.cxt.fill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getSelectPwd(touches: any, pwdArr: number[]) {
|
||||
for (var i = 0; i < this.circleArr.length; i++) {
|
||||
var currentPoint = this.circleArr[i]
|
||||
var xdiff = Math.abs(currentPoint.X - touches.pageX)
|
||||
/******** this.top = canvas向下移动的距离 **********/
|
||||
var ydiff = Math.abs(currentPoint.Y - touches.pageY + this.top)
|
||||
var dir = Math.pow(xdiff * xdiff + ydiff * ydiff, 0.5)
|
||||
if (dir > this.R || pwdArr.indexOf(i) >= 0) continue
|
||||
pwdArr.push(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
touchStart(e: TouchEvent) {
|
||||
this.getRed = false
|
||||
this.getSelectPwd(e.touches[0], this.pwdArr)
|
||||
}
|
||||
touchMove(e: TouchEvent) {
|
||||
e.preventDefault()
|
||||
var touches = e.touches[0]
|
||||
this.getSelectPwd(touches, this.pwdArr)
|
||||
// 清除画布,0,0代表从什么位置开始,canvasWidth,canvasHeight代表清除的宽度和高度
|
||||
this.cxt = this.canvas.getContext('2d')!
|
||||
this.cxt.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
|
||||
/*this.top = 手指拖动时,线条的起始位置。 */
|
||||
this.Draw({
|
||||
X: touches.pageX,
|
||||
Y: touches.pageY - this.top,
|
||||
})
|
||||
}
|
||||
touchEnd(e: TouchEvent) {
|
||||
this.cxt.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
|
||||
this.Draw()
|
||||
// if (this.pwdArr.toString() == this.passwdArr.toString()) {
|
||||
// console.log('密码正确', this.passwdArr.toString())
|
||||
// } else {
|
||||
// console.log('密码错误', this.pwdArr.toString())
|
||||
// this.Draw(null)
|
||||
// }
|
||||
this.getRed = true
|
||||
this.pwdArr = []
|
||||
this.dispatchEvent(
|
||||
new TouchEvent('end', {
|
||||
composed: true,
|
||||
})
|
||||
)
|
||||
return this.passwdArr
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ import './components/slider/slider'
|
|||
import './components/notification/notification'
|
||||
import './components/prompt/prompt'
|
||||
import './components/digicipher/digicipher'
|
||||
// import './components/pattern-view/pattern-view'
|
||||
import './components/pattern-view/pattern-view'
|
||||
import './components/overlay/active-overlay'
|
||||
|
||||
@customElement('settings-app')
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import {html, LitElement, css} from 'lit'
|
||||
import {customElement} from 'lit/decorators.js'
|
||||
import '../icon/icon'
|
||||
|
||||
@customElement('panel-pattern-view')
|
||||
export class PanelPatternView extends LitElement {
|
||||
static styles = css`
|
||||
.screen {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: rgb(124, 194, 235);
|
||||
}
|
||||
`
|
||||
render() {
|
||||
return html`
|
||||
<star-pattern-view></star-pattern-view>
|
||||
<!-- <star-pattern-view topDir="100px"></star-pattern-view> -->
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'panel-pattern-view': PanelPatternView
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@ import './overflowmenu/overflowmenu'
|
|||
import './switch/switch'
|
||||
import './slider/slider'
|
||||
import './digicipher/digicipher'
|
||||
// import './pattern-view/pattern-view'
|
||||
import './pattern-view/pattern-view'
|
||||
import './container/homescreen-container'
|
||||
import './toast/toast'
|
||||
import './picker/picker'
|
||||
|
|
Loading…
Reference in New Issue