|
@@ -0,0 +1,175 @@
|
|
|
+class GestureLock {
|
|
|
+
|
|
|
+ constructor(containerWidth, cycleRadius) {
|
|
|
+ this.containerWidth = containerWidth; // 容器宽度
|
|
|
+ this.cycleRadius = cycleRadius; // 圆的半径
|
|
|
+
|
|
|
+ this.circleArray = []; // 全部圆的对象数组
|
|
|
+ this.checkPoints = []; // 选中的圆的对象数组
|
|
|
+ this.lineArray = []; // 已激活锁之间的线段数组
|
|
|
+ this.lastCheckPoint = 0; // 最后一个激活的锁
|
|
|
+ this.offsetX = 0; // 容器的 X 偏移
|
|
|
+ this.offsetY = 0; // 容器的 Y 偏移
|
|
|
+ this.activeLine = {}; // 最后一个激活的锁与当前位置之间的线段
|
|
|
+
|
|
|
+ this.windowWidth = wx.getSystemInfoSync().windowWidth; // 窗口大小(用于rpx 和 px 转换)
|
|
|
+
|
|
|
+ this.initCircleArray();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化 画布上的 9个圆
|
|
|
+ initCircleArray() {
|
|
|
+ const cycleMargin = (this.containerWidth - 6 * this.cycleRadius) / 6;
|
|
|
+ let count = 0;
|
|
|
+ for (let i = 0; i < 3; i++) {
|
|
|
+ for (let j = 0; j < 3; j++) {
|
|
|
+ count++;
|
|
|
+ this.circleArray.push({
|
|
|
+ count: count,
|
|
|
+ x: this.rpxTopx((cycleMargin + this.cycleRadius) * (j * 2 + 1)),
|
|
|
+ y: this.rpxTopx((cycleMargin + this.cycleRadius) * (i * 2 + 1)),
|
|
|
+ radius: this.rpxTopx(this.cycleRadius),
|
|
|
+ check: false,
|
|
|
+ style: {
|
|
|
+ left: (cycleMargin + this.cycleRadius) * (j * 2 + 1) - this.cycleRadius + 'rpx',
|
|
|
+ top: (cycleMargin + this.cycleRadius) * (i * 2 + 1) - this.cycleRadius + 'rpx',
|
|
|
+ width: this.cycleRadius * 2 + 'rpx',
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onTouchStart(e) {
|
|
|
+ this.setOffset(e);
|
|
|
+ this.checkTouch({
|
|
|
+ x: e.touches[0].pageX - this.offsetX,
|
|
|
+ y: e.touches[0].pageY - this.offsetY
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ onTouchMove(e) {
|
|
|
+ this.moveDraw(e)
|
|
|
+ }
|
|
|
+
|
|
|
+ onTouchEnd(e) {
|
|
|
+ const checkPoints = this.checkPoints;
|
|
|
+ this.reset();
|
|
|
+ return checkPoints;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 初始化 偏移量
|
|
|
+ setOffset(e) {
|
|
|
+ this.offsetX = e.currentTarget.offsetLeft;
|
|
|
+ this.offsetY = e.currentTarget.offsetTop;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检测当时 触摸位置是否位于 锁上
|
|
|
+ checkTouch({
|
|
|
+ x,
|
|
|
+ y
|
|
|
+ }) {
|
|
|
+ for (let i = 0; i < this.circleArray.length; i++) {
|
|
|
+ let point = this.circleArray[i];
|
|
|
+ if (this.isPointInCycle(x, y, point.x, point.y, point.radius)) {
|
|
|
+ if (!point.check) {
|
|
|
+ this.checkPoints.push(point.count);
|
|
|
+ if (this.lastCheckPoint != 0) {
|
|
|
+ // 已激活锁之间的线段
|
|
|
+ const line = this.drawLine(this.lastCheckPoint, point);
|
|
|
+ this.lineArray.push(line);
|
|
|
+ }
|
|
|
+ this.lastCheckPoint = point;
|
|
|
+ }
|
|
|
+ point.check = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 画线 - 返回 样式 对象
|
|
|
+ drawLine(start, end) {
|
|
|
+ const width = this.getPointDis(start.x, start.y, end.x, end.y);
|
|
|
+ const rotate = this.getAngle(start, end);
|
|
|
+
|
|
|
+ return {
|
|
|
+ activeLeft: start.x + 'px',
|
|
|
+ activeTop: start.y + 'px',
|
|
|
+ activeWidth: width + 'px',
|
|
|
+ activeRotate: rotate + 'deg'
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取 画线的 角度
|
|
|
+ getAngle(start, end) {
|
|
|
+ var diff_x = end.x - start.x,
|
|
|
+ diff_y = end.y - start.y;
|
|
|
+ if (diff_x >= 0) {
|
|
|
+ return 360 * Math.atan(diff_y / diff_x) / (2 * Math.PI);
|
|
|
+ } else {
|
|
|
+ return 180 + 360 * Math.atan(diff_y / diff_x) / (2 * Math.PI);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断 当前点是否位于 锁内
|
|
|
+ isPointInCycle(x, y, circleX, circleY, radius) {
|
|
|
+ return (this.getPointDis(x, y, circleX, circleY) < radius) ? true : false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取两点之间距离
|
|
|
+ getPointDis(ax, ay, bx, by) {
|
|
|
+ return Math.sqrt(Math.pow(ax - bx, 2) + Math.pow(ay - by, 2));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 移动 绘制
|
|
|
+ moveDraw(e) {
|
|
|
+ // 画经过的圆
|
|
|
+ const x = e.touches[0].pageX - this.offsetX;
|
|
|
+ const y = e.touches[0].pageY - this.offsetY;
|
|
|
+ this.checkTouch({
|
|
|
+ x,
|
|
|
+ y
|
|
|
+ });
|
|
|
+
|
|
|
+ // 画 最后一个激活的锁与当前位置之间的线段
|
|
|
+ this.activeLine = this.drawLine(this.lastCheckPoint, {
|
|
|
+ x,
|
|
|
+ y
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使 画布 恢复初始状态
|
|
|
+ reset() {
|
|
|
+ this.circleArray.forEach((item) => {
|
|
|
+ item.check = false;
|
|
|
+ });
|
|
|
+ this.checkPoints = [];
|
|
|
+ this.lineArray = [];
|
|
|
+ this.activeLine = {};
|
|
|
+ this.lastCheckPoint = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // 获取 最后一个激活的锁与当前位置之间的线段
|
|
|
+ getActiveLine() {
|
|
|
+ return this.activeLine;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取 圆对象数组
|
|
|
+ getCycleArray() {
|
|
|
+ return this.circleArray;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取 已激活锁之间的线段
|
|
|
+ getLineArray() {
|
|
|
+ return this.lineArray;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将 RPX 转换成 PX
|
|
|
+ rpxTopx(rpx) {
|
|
|
+ return rpx / 750 * this.windowWidth;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export default GestureLock;
|