GVKun编程网logo

canvas实现手机的手势解锁(步骤详细)(canvas实现app中的手写功能)

5

最近很多小伙伴都在问canvas实现手机的手势解锁和步骤详细这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展canvas图像旋转与翻转姿势解锁、canvas实现vue手势解锁组件、

最近很多小伙伴都在问canvas实现手机的手势解锁步骤详细这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展canvas 图像旋转与翻转姿势解锁、canvas 实现vue 手势解锁组件、canvas实现手机端用来上传用户头像的代码、canvas手势解锁源码等相关知识,下面开始了哦!

本文目录一览:

canvas实现手机的手势解锁(步骤详细)(canvas实现app中的手写功能)

canvas实现手机的手势解锁(步骤详细)(canvas实现app中的手写功能)

按照国际惯例,先放效果图

1、js动态初始化Dom结构

首先在index.html中添加基本样式

body{background:pink;text-align: center;}

加个移动端Meta头

<Meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">

引入index.js脚本

script src="index.js"></script>

index.js

// 匿名函数自执行
(function(){
     canvasLock是全局对象
    window.canvasLock=(obj){
        this.width=obj.width;
        this.height=obj.height;
    }
    动态生成DOM
    canvasLock.prototype.initDom=(){
        创建一个div
        var div=document.createElement("div");
        var h4="<h4 id=''title''title''>绘制解锁图案</h4>";
        div.innerHTML=h4;
        div.setAttribute("style","position:absolute;top:0;left:0;right:0;bottom:0;");

        创建canvas
        var canvas=document.createElement("canvas");
        canvas.setAttribute("id","canvas"csstext 的本质就是设置 HTML 元素的 style 属性值
        canvas.style.csstext="background:pink;display:inine-block;margin-top:15px;";

        div.appendChild(canvas);
        document.body.appendChild(div);

        设置canvas默认宽高
        var width=this.width||300;
        var height=this.height||300;

        canvas.style.width=width+"px";
        canvas.style.height=height+"px";

        canvas.width=width;
        canvas.height=height;

    }

    
    init代表初始化,程序的入口
    canvasLock.prototype.init=动态生成DOM
        this.initDom();

        创建画布
        this.canvas=document.getElementById("canvas"this.ctx=this.canvas.getContext("2d");

    }
})();

在index.html中创建实例并初始化

new canvasLock({}).init();

效果图

 

 

2、 画圆函数

需要补充一下画布宽度与圆的半径的关系

如果一行3个圆,则有4个间距,间距的宽度与圆的直径相同,相当于7个直径,即14个半径

如果一行4个圆,则有5个间距,间距的宽度与圆的直径相同,相当于9个直径,即18个半径

如果一行n个圆,则有n+1个间距,间距的宽度与圆的直径相同,相当于2n+1个直径,即4n+2个半径

 

 

补充两个方法:

以给定坐标点为圆心画出单个圆
    canvasLock.prototype.drawCircle=(x,y){
        this.ctx.strokethis.ctx.linewidth=2.ctx.beginPath();
        this.ctx.arc(x,y,this.r,2*Math.PI,1)">true.ctx.closePath();
        .ctx.stroke();
    }
    
    绘制出所有的圆
    canvasLock.prototype.createCircle=var n=this.circleNum;一行几个圆
        var count=0this.r=this.canvas.width/(4*n+2);//公式计算出每个圆的半径
        this.lastPoint=[];储存点击过的圆的信息
        this.arr=[];储存所有圆的信息
        this.restPoint=[];储存未被点击的圆的信息
        var r=.r;

        for(var i=0;i<n;i++){
            var j=0;j<n;j++){
                count++;
                var obj={
                    x:(4*j+3)*r,y:(4*i+3)*给每个圆标记索引
                };
                .arr.push(obj);
                this.restPoint.push(obj);初始化时为所有点
            }
        }

        清屏
        this.ctx.clearRect(0,1)">this.canvas.width,1)">.canvas.height);

        以给定坐标点为圆心画出所有圆
        var i=0;i<this.arr.length;i++循环调用画单个圆的方法
            this.drawCircle(this.arr[i].x,1)">.arr[i].y);
        }

    }

初始化的时候记得调用

canvasLock.prototype.init=绘制出所有的圆
        .createCircle();
    }

别忘了在index.html中实例化时传入参数(一行定义几个圆)

new canvasLock({circleNum:3}).init();

效果图

 

 

3、canvas事件操作——实现画圆和画线

getPosition方法用来得到鼠标触摸点离canvas的距离(左边和上边)

canvasLock.prototype.getPosition=(e){
        var rect=e.currentTarget.getBoundingClientRect();获得canvas距离屏幕的上下左右距离
        var po={
            鼠标与视口的左距离 - canvas距离视口的左距离 = 鼠标与canvas的左距离
            x:(e.touches[0].clientX-rect.left),鼠标与视口的上距离 - canvas距离视口的上距离 = 鼠标距离canvas的上距离
            y:(e.touches[0].clientY-rect.top)
        };
        return po;
    }

给canvas添加 touchstart 事件,判断触摸点是否在圆内

触摸点在圆内则允许拖拽,并将该圆添加到 lastPoint 中,从 restPoint 中剔除

this.canvas.addEventListener("touchstart",1)">(e){
            var po=self.getPosition(e);鼠标距离canvas的距离

            判断是否在圆内
            var i=0;i<self.arr.lenth;i++){
                if(Math.abs(po.x-self.arr[i].x)<self.r && Math.abs(po.y-self.arr[i].y)<self.r){
                    self.touchFlag=true;允许拖拽
                    self.lastPoint.push(self.arr[i]);点击过的点
                    self.restPoint.splice(i,1);剩下的点剔除这个被点击的点
                    break;
                }
            }
        },1)">false);

 

判断是否在圆内的原理:

 

 圆心的x轴偏移和鼠标点的x轴偏移的距离的绝对值小于半径

并且

 圆心的y轴偏移和鼠标点的y轴偏移的距离的绝对值小于半径

则可以判断鼠标位于圆内

 

给touchmove绑定事件,在触摸点移动时给点击过的圆画上实心圆,并画线

触摸点移动时的动画
    canvasLock.prototype.update=(po){
        清屏,canvas动画前必须清空原来的内容
        .arr[i].y);
        }

        this.drawPoint();点击过的圆画实心圆
        this.drawLine(po);画线

    }

    画实心圆
    canvasLock.prototype.drawPoint=this.lastPoint.length;i++this.ctx.fill;
            .ctx.beginPath();
            this.ctx.arc(this.lastPoint[i].x,1)">this.lastPoint[i].y,1)">this.r/2,true);
            .ctx.closePath();
            .ctx.fill();
        }
    }

    画线
    canvasLock.prototype.drawLine=this.linewidth=3this.ctx.moveto(this.lastPoint[0].x,1)">this.lastPoint[0].y);线条起点
        var i=1;i<this.ctx.lineto(.lastPoint[i].y);
        }
        this.ctx.lineto(po.x,po.y);触摸点
        .ctx.stroke();
        .ctx.closePath();
    }

效果图

 

 

4、canvas手势链接操作实现

在touchmove中补充当碰到下一个目标圆时的操作

碰到下一个圆时只需要push到lastPoint当中去
        this.restPoint.length;i++if((Math.abs(po.x-this.restPoint[i].x)<this.r) && (Math.abs(po.y-this.restPoint[i].y)<.r)){
                this.lastPoint.push(this.restPoint[i]);将这个新点击到的点存入lastPoint
                this.restPoint.splice(i,1)">从restPoint中剔除这个新点击到的点
                ;
            }
        }

效果图

 

 

5、解锁成功与否的判断

 

设置密码
    canvasLock.prototype.storePass=if(.checkPass()){
            document.getElementById("title").innerHTML="解锁成功"this.drawStatusPoint("lightgreen");
        }else{
            document.getElementById("title").innerHTML="解锁失败"this.drawStatusPoint("orange");
        }
    }

    判断输入的密码
    canvasLock.prototype.checkPass=var p1="123",1)">成功的密码
            p2=""){
            p2+=.lastPoint[i].index;
        }
        return p1===p2;
    }

    绘制判断结束后的状态
    canvasLock.prototype.drawStatusPoint=(type){
        this.ctx.strokeStyle=type;
            );
            .ctx.stroke();
        }
    }

    程序全部结束后重置
    canvasLock.prototype.reset=.createCircle();
    }

 

大功告成!!下面晒出所有代码

index.html

<!DOCTYPE html>
html lang="en"head>
    charset="UTF-8"title>手势解锁</<!-- 移动端Meta头 -->
    style>
           body{background:pink;text-align center}
    body>

    >
        // circleNum:3 表示一行3个圆
        new canvasLock({circleNum:3}).init();
    >
  
htmlobj.height;
        this.circleNum=obj.circleNum;
    }
    height;

    }

    .arr[i].y);
        }

    }

    添加事件
    canvasLock.prototype.bindEvent=var self=;

        var i=0;i<self.arr.length;i++if((Math.abs(po.x-self.arr[i].x)<self.r) && (Math.abs(po.y-self.arr[i].y)<self.r)){
                    self.touchFlag=falsethis.canvas.addEventListener("touchmove",1)">if(self.touchFlag){
                触摸点移动时的动画
                self.update(self.getPosition(e));
            }
        },1)">触摸离开时
        this.canvas.addEventListener("touchend",1)">(self.touchFlag){
                self.storePass(self.lastPoint);
                setTimeout((){
                    self.reset();
                },300);
            }
        },1)">);

    }

    .createCircle();
    }
    
    获取鼠标点击处离canvas的距离
    canvasLock.prototype.getPosition= po;
    }

     鼠标每移动一下都会重绘canvas,update操作相当于每一个move事件都会触发
        画线

        ;
            }
        }
    }

    .ctx.closePath();
    }

    默认不允许拖拽
        this.touchFlag=.createCircle();

        添加事件
        .bindEvent();
    }
})();

 

总结

以上是小编为你收集整理的canvas实现手机的手势解锁(步骤详细)全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

canvas 图像旋转与翻转姿势解锁

canvas 图像旋转与翻转姿势解锁

多图预警,数学不好可直接跳至文末小结。

需求背景

从一个游戏需求说起:

  1. 技术选型:canvas
    上图所展示的游戏场景,“可乐瓶”里有多个“气泡”,需要设置不同的动画效果,且涉及 deviceOrientation 的交互,需要有大量计算改变元素状态。从性能方面考虑,canvas 是不二的选择。

  2. 技术点:canvas 绘制图像
    通过对游戏场景的进一步分析,可见场景中的“气泡”元素形状都是相同的,且不规则,通过 canvas 直接绘制形状实现成本较高,因此需要在 canvas 上绘制图像。

  3. 技术点:canvas 图像旋转与翻转
    虽然“气泡”元素是相同的,可以使用相同的图像,但图像需要多个角度/多个方向展示,因此需要对图像进行相应的旋转与翻转(镜像),这也是本文所要介绍的重点。

后文代码以下图左侧绿框的“气泡”为示例,右侧展示了场景中用到的两个图像:

认识 canvas 坐标系

canvas 上图像的旋转和翻转,常见的做法是将 canvas 坐标系统进行变换。因此,我们需要先认识 canvas 坐标系统:

由上图可得,canvas 2D 环境中坐标系统和 Web 的坐标系统是一致的,有以下几个特点:

  1. 坐标原点 (0,0) 在左上角

  2. X坐标向右方增长

  3. Y坐标向下方延伸

回到上述需求中,我们获取 canvas 对象并设置相应的宽高:

<canvas id=''myCanvas''></canvas>
// 获取 canvas 对象
var canvas = document.getElementById(''myCanvas'')
canvas.width = 750
canvas.height = 1054
// 获取 canvas 2D 上下文对象
var ctx = canvas.getContext(''2d'')

此时,canvas 的坐标系统如下图所示:

在 canvas 上绘制图像

在 canvas 上绘制图像,可以使用 drawImage() 方法,语法如下(详细用法参见 MDN):

void ctx.drawImage(image, dx, dy);
void ctx.drawImage(image, dx, dy, dWidth, dHeight);
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

需要注意的是,图像必须加载完毕,才能绘制到 canvas 上,否则会出现空白:

var img = new Image()
img.src = ''xxxxxxx.png''
img.onload = function() {
// 绘制图像
ctx.drawImage(img, 512, 220, 160, 192);
}

此时,便可以 canvas 上看到一个未旋转/翻转的“气泡”图像,如下图所示:

canvas 坐标变换

接下来,我们再来了解 canvas 坐标的变换。上述需求仅涉及 2D 绘制上下文,因此仅介绍 2D 绘制上下文支持的各种变换:

  1. 平移 translate:

    ctx.translate(x, y)

    translate() 方法接受两个参数。x 是左右偏移量,y 是上下偏移量。

  2. 旋转 rotate:

    ctx.rotate(angle)

    rotate() 方法只接受一个参数。旋转的角度 angle,它是顺时针方向的,以弧度为单位的值。

  3. 缩放 scale:

    ctx.scale(x, y)

    scale() 方法接受两个参数。x 和 y 分别是横轴和纵轴的缩放因子。其缩放因子默认是 1,如果比 1 小是缩小,如果比 1 大则放大。

  4. 变形 transform:

    ctx.transform (a, b, c, d, e, f)

    transform() 方法是对当前坐标系进行矩阵变换。

    ctx.setTransform (a, b, c, d, e, f)

    setTransform() 方法重置变形矩阵。先将当前的矩阵重置为单位矩阵(即默认的坐标系),再用相同的参数调用 transform() 方法设置矩阵。
    以上两个方法均接受六个参数,具体如下:

参数 含义
a 水平缩放绘图
b 水平倾斜绘图
c 垂直倾斜绘图
d 垂直缩放绘图
e 水平移动绘图
f 垂直移动绘图

图像旋转的实现


上图所示“气泡”,宽为 160,高为 192,x 轴方向距离原点 512,y 轴方向距离原点 220,逆时针旋转 35 度。
要绘制该“气泡”,需要先将坐标系平移(translate),再旋转(rotate)。具体实现步骤如下:

save() 方法与 restore() 方法:

  1. save() 方法用来保存 Canvas 状态的,没有参数。每一次调用 save() 方法,当前的状态就会被推入栈中保存起来。当前状态包括:

    • 当前应用的变形(移动/旋转/缩放)

    • strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation 的值

    • 当前的裁切路径(clipping path)

  2. restore() 方法用来恢复 Canvas 状态,没有参数。每一次调用 restore() 方法,上一个保存的状态就从栈中弹出,所有设定都恢复。

  3. 状态保存在栈中,可以嵌套使用 save() 与 restore()。

图像翻转的实现

上图所示“气泡”,宽为 160,高为 192,x 轴方向距离原点 172,y 轴方向距离原点 365,顺时针旋转 35 度。
要绘制该“气泡”,需要先将坐标系统平移(translate),翻转(scale),平移(translate),再旋转(rotate)。具体实现步骤如下:

至此,实现了“气泡”的镜像翻转,但翻转后的“气泡”还需要旋转特定的角度,在方法一的基础上继续对坐标系统进行变换:

以上操作中进行了两次平移(translate)操作,可以进行合并简化:

坐标系统的矩阵变换

前文介绍了 2D 绘制上下文变形(transform)变换,实际是直接修改变换的矩阵,它可以实现前面介绍的平移(translate)/旋转(rotate)/缩放( scale)变换,还可以实现切变/镜像反射变换等。矩阵计算遵循数学矩阵公式规则:

由上公式可得:

x'' = ax + cy + e
y'' = bx + dy + f

矩阵变换可实现以下变换效果:

  1. 平移 translate:

    x'' = 1x+0y+tx = x+tx
    y'' = 0x+1y+ty = y+ty

  2. 旋转 rotate:

    x'' = x*cosθ-y*sinθ+0 = x*cosθ-y*sinθ
    y'' = x*sinθ+y*cosθ+0 = x*sinθ+y*cosθ

  3. 缩放 scale:

    x'' = Sx*x+0y+0 = Sx*x
    y'' = 0x+Sy*y+0 = Sy*y

  4. 切变

    x'' = x+y*tan(θx)+0 = x+y*tan(θx)
    y'' = x*tan(θy)+y+0 = x*tan(θy)+y

  5. 镜像反射

    // 定义(ux,uy)为直线(y=kx)方向的单位向量
    ux=1/sqrt(1+k^2)
    uy=k/sqrt(1+k^2)
    x'' = (2*ux^2-1)*x+2*ux*uy*y
    y'' = 2*ux*uy*x+(2*uy^2-1)*y

结合上述公式,可推导出图像旋转和翻转的矩阵变换实现:

  1. 图像旋转: 

  2. 图像翻转: 

  3. 图像镜像反射(翻转+旋转): 

像素操作实现图像翻转

除了坐标系统变换,canvas 的像素操作同样可以实现图像的翻转。首先需要了解下 getImageData()方法(详细用法参见MDN)和 putImageData()(详细用法参见MDN)方法:
1. getImageData()
CanvasRenderingContext2D.getImageData() 返回一个 ImageData 对象,用来描述 canvas 区域隐含的像素数据,这个区域通过矩形表示,起始点为 (sx, sy)、宽为 sw、高为 sh。

ImageData ctx.getImageData(sx, sy, sw, sh);
  1. putImageData() CanvasRenderingContext2D.putImageData() 是 Canvas 2D API 将数据从已有的 ImageData 对象绘制到位图的方法。 如果提供了脏矩形,只能绘制矩形的像素。

void ctx.putImageData(imagedata, dx, dy);
void ctx.putImageData(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight);

水平翻转实现:

// 绘制图像
ctx.drawImage(img, x, y, width, height)
// 获取 img_data 数据
var img_data = ctx.getImageData(x, y, width, height),
i, i2, t,
h = img_data.height,
w = img_data.width,
w_2 = w / 2;
// 将 img_data 的数据水平翻转
for (var dy = 0; dy < h; dy ++) {
for (var dx = 0; dx < w_2; dx ++) {
i = (dy << 2) * w + (dx << 2)
i2 = ((dy + 1) << 2) * w - ((dx + 1) << 2)
for (var p = 0; p < 4; p ++) {
t = img_data.data[i + p]
img_data.data[i + p] = img_data.data[i2 + p]
img_data.data[i2 + p] = t
}
}
}
// 重绘水平翻转后的图片
ctx.putImageData(img_data, x, y)

小结

至此,小编的数学姿势又恢复到了高考水平。
1. 图像旋转:
- 基础变换法:
javascript
ctx.save()
ctx.translate(x + width / 2, y + height / 2)
ctx.rotate(angle * Math.PI / 180)
ctx.drawImage(img, -width / 2, -height / 2, width, height)
ctx.restore()

- 矩阵变换法:
javascript
ctx.save()
var rad = angle * Math.PI/180
ctx.transform( Math.cos(rad), Math.sin(rad), -Math.sin(rad), Math.cos(rad), x + width / 2, y + height / 2)
ctx.drawImage(img, -width / 2, -height / 2, width, height)
ctx.restore()

  1. 图像翻转:

    • 基础变换法: javascript // 方法一 ctx.save() ctx.translate(canvasWidth, 0) ctx.scale(-1, 1) ctx.drawImage(img, canvasWidth-width-x, y, width, height) ctx.restore() javascript // 方法二 ctx.save() ctx.scale(-1, 1) ctx.drawImage(img, -width-x, y, width, height) ctx.restore()

    • 矩阵变换法: javascript // 方法一 ctx.save() ctx.transform(-1, 0, 0, 1, canvasWidth, 0) ctx.drawImage(img, canvasWidth-width-x, y, width, height) ctx.restore() javascript // 方法二 ctx.save() ctx.transform(-1, 0, 0, 1, 0, 0) ctx.drawImage(img, -width-x, y, width, height) ctx.restore()

    • 像素操作法: javascript ctx.drawImage(img, x, y, width, height) var img_data = ctx.getImageData(x, y, width, height), i, i2, t, h = img_data.height, w = img_data.width, w_2 = w / 2; for (var dy = 0; dy < h; dy ++) { for (var dx = 0; dx < w_2; dx ++) { i = (dy << 2) * w + (dx << 2) i2 = ((dy + 1) << 2) * w - ((dx + 1) << 2) for (var p = 0; p < 4; p ++) { t = img_data.data[i + p] img_data.data[i + p] = img_data.data[i2 + p] img_data.data[i2 + p] = t } } } ctx.putImageData(img_data, x, y)

  2. 图像镜像对称(翻转+旋转):

    • 基础变换法: javascript ctx.save() ctx.scale(-1, 1) ctx.translate(-width/2-x, y+height/2) ctx.rotate(-angle * Math.PI / 180) ctx.drawImage(img, -width / 2, -height / 2, width, height) ctx.restore()

    • 矩阵变换法: javascript ctx.save() var k = Math.tan( (180-angle)/2 * Math.PI / 180 ) var ux = 1 / Math.sqrt(1 + k * k) var uy = k / Math.sqrt(1 + k * k) ctx.transform( (2*ux*ux-1), 2*ux*uy, 2*ux*uy, (2*uy*uy-1), x + width/2, y + height/2 ) ctx.drawImage(img, -width/2, -height/2, width, height) ctx.restore()

参考文章

  • 《W3cplus - CANVAS 系列》

  • 《html5 canvas.transform[转]》

  • 《html5 canvas 学习笔记》

  • 《在HTML5中翻转图片》

说明:本文讨论的 canvas 环境均为 2D 环境。若有更好的实现方式,欢迎留言告知。


本文分享自微信公众号 - 凹凸实验室(AOTULabs)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

canvas 实现vue 手势解锁组件

canvas 实现vue 手势解锁组件

1.手机锁屏九宫格解锁组件

2.代码如下

<template>
<canvas id="gesture" ref="canvas" :/>
</template>

<script>
export default {
name: ''GestureLock'',
props: {
chooseType: {
type: Number,
default: 3 // 3: 3*3, 4: 4*4, 5: 5*5
}
},
data() {
return {
touchedFlag: false, // 是否正在绘制
canvas: null,
ctx: null,
radius: 0, // 计算后的半径大小
style: {
width: 450,
height: 500
},
devicePixelRatio: window.devicePixelRatio || 1,
circleArr: [],
lastPoint: [],
restPoint: []
};
},
mounted() {
this.canvas = this.$refs.canvas;
this.ctx = this.canvas.getContext(''2d'');

this.canvas.width = this.style.width * this.devicePixelRatio;
this.canvas.height = this.style.height * this.devicePixelRatio;

this.createCircle();
this.bindEvent();
},
beforeDestroy() {
this.canvas.removeEventListener(''touchstart'', this.onStartHandler);
this.canvas.removeEventListener(''touchmove'', this.onMoveHandler);
this.canvas.removeEventListener(''touchend'', this.onEndHandler);
},
methods: {
drawPoint(style) {
// 初始化圆心
for (var i = 0; i < this.lastPoint.length; i++) {
this.ctx.fillStyle = style;
this.ctx.beginPath();
this.ctx.arc(
this.lastPoint[i].x,
this.lastPoint[i].y,
this.radius / 2.5,
0,
Math.PI * 2,
true
);
this.ctx.closePath();
this.ctx.fill();
}
},
drawStatusPoint(type) {
// 初始化状态线条
for (var i = 0; i < this.lastPoint.length; i++) {
this.ctx.strokeStyle = type;
this.ctx.beginPath();
this.ctx.arc(
this.lastPoint[i].x,
this.lastPoint[i].y,
this.radius,
0,
Math.PI * 2,
true
);
this.ctx.closePath();
this.ctx.stroke();
}
},
drawCircle(x, y) {
// 初始化解锁密码面板 小圆圈
this.ctx.stroke#648F83''; // 密码的点点默认的颜色
this.ctx.lineWidth = 2;
this.ctx.beginPath();
this.ctx.arc(x, y, this.radius, 0, Math.PI * 2, true); // 画圆
this.ctx.closePath();
this.ctx.stroke();
},
drawLine(style, position) {
// style:颜色 解锁轨迹
this.ctx.beginPath();
this.ctx.strokeStyle = style;
this.ctx.lineWidth = 3;
this.ctx.moveTo(this.lastPoint[0].x, this.lastPoint[0].y);

for (var i = 1; i < this.lastPoint.length; i++) {
this.ctx.lineTo(this.lastPoint[i].x, this.lastPoint[i].y);
}
this.ctx.lineTo(position.x, position.y);
this.ctx.stroke();
this.ctx.closePath();
},
createCircle() {
var n = this.chooseType;
var count = 0;
this.radius = this.ctx.canvas.width / (1 + 4 * n); // 公式计算
this.lastPoint = [];
this.circleArr = [];
this.restPoint = [];
var r = this.radius;

for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
count++;
let point = {
x: j * 4 * r + 3 * r,
y: i * 4 * r + 3 * r,
index: count
};
this.circleArr.push(point);
this.restPoint.push(point);
}
}

this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);

// 画9个圆
for (let i = 0; i < this.circleArr.length; i++) {
this.drawCircle(this.circleArr[i].x, this.circleArr[i].y);
}
},
onStartHandler(e) {
e.preventDefault(); // 某些android 的 touchmove不宜触发 所以增加此行代码

// 重置图案
this.onReset();
var position = this.getPosition(e);

for (var i = 0; i < this.circleArr.length; i++) {
if (
Math.abs(position.x - this.circleArr[i].x) < this.radius &&
Math.abs(position.y - this.circleArr[i].y) < this.radius
) {
this.touchedFlag = true;
this.drawPoint(this.circleArr[i].x, this.circleArr[i].y);
this.lastPoint.push(this.circleArr[i]);
this.restPoint.splice(i, 1);
break;
}
}
},
onMoveHandler(e) {
if (this.touchedFlag) {
this.onUpdateHandler(this.getPosition(e));
}
},
onEndHandler(e) {
if (this.touchedFlag) {
this.touchedFlag = false;
this.$emit(''input'', this.lastPoint.map((point) => {
return point.index;
}));
// 重绘最后所有点
this.onUpdateHandler(this.lastPoint[this.lastPoint.length - 1]);
}
},
onUpdateHandler(position) {
// 核心变换方法在touchmove时候调用
this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);

for (let i = 0; i < this.circleArr.length; i++) {
// 每帧先把面板画出来
this.drawCircle(this.circleArr[i].x, this.circleArr[i].y);
}

this.drawPoint(''#648F83''); // 每帧花轨迹
this.drawStatusPoint(''#648F83''); // 每帧花轨迹

this.drawLine(''#648F83'', position, this.lastPoint); // 每帧画圆心

for (let i = 0; i < this.restPoint.length; i++) {
if (
Math.abs(position.x - this.restPoint[i].x) < this.radius &&
Math.abs(position.y - this.restPoint[i].y) < this.radius
) {
this.drawPoint(this.restPoint[i].x, this.restPoint[i].y);
this.lastPoint.push(this.restPoint[i]);
this.restPoint.splice(i, 1);
break;
}
}
},
onReset() {
this.createCircle();
},
bindEvent() {
// 网页
this.canvas.addEventListener(''mousedown'', this.onStartHandler);
this.canvas.addEventListener(''mousemove'', this.onMoveHandler);
this.canvas.addEventListener(''mouseup'', this.onEndHandler);
// 移动端
this.canvas.addEventListener(''touchstart'', this.onStartHandler);
this.canvas.addEventListener(''touchmove'', this.onMoveHandler);
this.canvas.addEventListener(''touchend'', this.onEndHandler);
},
getPosition(e) {
// 获取touch点相对于canvas的坐标
var rect = e.currentTarget.getBoundingClientRect();
var position = e.touches ? {
x: (e.touches[0].clientX - rect.left) * this.devicePixelRatio,
y: (e.touches[0].clientY - rect.top) * this.devicePixelRatio
} : {
x: (e.clientX - rect.left) * this.devicePixelRatio,
y: (e.clientY - rect.top) * this.devicePixelRatio
};
return position;
}
}
};
</script>
3.组件引用
<GestureLock v-model="gestureData"></GestureLock>
data () {
return {
gestureData:[]
};
}
 
watch: {
// 按绘制的顺序输出的数组
gestureData(val) {
console.log(val);
}
},
4.结果

 

canvas实现手机端用来上传用户头像的代码

canvas实现手机端用来上传用户头像的代码

废话不多说了直接给大家介绍canvas实现手机端用来上传用户头像的代码,具体代码如下所示:

rush:js;"> <Meta charset="UTF-8">

以上所述是小编给大家介绍的canvas实现手机端用来上传用户头像的代码。小编 jb51.cc 收集整理的教程希望能对你有所帮助,如果觉得小编不错,可分享给好友!感谢支持。

canvas手势解锁源码

canvas手势解锁源码

先放图

demo.html

<!DOCTYPE html>
<html lang="en"head>
    Meta charset="UTF-8"name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"title>手势解锁</style type="text/css">
        body{
            text-align: center;
            background #305066;
        }
        h4
            color #22C3AA}
    stylebodyscript ="text/javascript" src="src/index.js"></script="text/javascript">
        // 1、生成背景
         2、title生成
         3、用js动态生成canvas标签
         4、js方式动态生成h4标签和canvas标签
        new canvasLock({chooseType:3}).init();
    html>

index.js

(function(){
        /**
         * 实现画圆和划线:
         * 1、添加事件touchstart、touchmove、touchend
         * 2、touchstart判断是否点击的位置处于圆内getPosition,处于则初始化
         * lastpoint、restPoint
         * 3、touchmove做的就是:画圆drawPoint和画线drawLine
         *
         * 实现自动画圆的效果
         * 1、检测手势移动的位置是否处于圆内
         * 2、圆内的话则画圆 drawPoint
         * 3、已经画过实心圆的圆,无需重复检测
         *
         * 实现解锁成功:
         * 1、检测路径是否是对的
         * 2、如果是对的就重置,圆圈变绿
         * 3、不对也重置,圆圈变红
         * 4、重置
         */

        window.canvasLock = (obj){
            this.height = obj.height;
            this.width = obj.width;
            this.chooseType = obj.chooseType;
        };

        // js方式动态生成dom
        canvasLock.prototype.initDom = (){
            var wrap = document.createElement(''div'');
            var str = ''<h4 id="title">绘制解锁图案</h4>'';
            wrap.setAttribute(''style'',''position: absolute;top:0;left:0;right:0;bottom:0;'');


            var canvas = document.createElement(''canvas'');
            canvas.setAttribute(''id'',''canvas'');
            canvas.style.csstext = ''background-color: #305066;display: inline-block;margin-top: 15px;'';

            wrap.innerHTML = str;
            wrap.appendChild(canvas);

            var width = this.width || 300;
            var height = this.height || 300;
            
            document.body.appendChild(wrap);

             高清屏锁放
            canvas.style.width = width + "px";
            canvas.style.height = height + "px";

            canvas.width = width;
            canvas.height = height;

        }
        canvasLock.prototype.drawCle = function(x,y) {  初始化解锁密码面板
            this.ctx.stroke#CFE6FF''this.ctx.linewidth = 2this.ctx.beginPath();
            this.ctx.arc(x,y,this.r,Math.PI * 2,1)">true.ctx.closePath();
            .ctx.stroke();
        }
        canvasLock.prototype.createCircle = function() { 创建解锁点的坐标,根据canvas的大小来平均分配半径

            var n = .chooseType;
            var count = 0this.r = this.ctx.canvas.width / (2 + 4 * n); 公式计算
            this.lastPoint = [];
            this.arr =this.restPoint =var r = .r;
            for (var i = 0 ; i < n ; i++) {
                var j = 0 ; j < n ; j++) {
                    count++;
                    var obj = {
                        x: j * 4 * r + 3 * r,y: i * 4 * r + 3 *.arr.push(obj);
                    .restPoint.push(obj);
                }
            }

            this.ctx.clearRect(0,1)">this.ctx.canvas.width,1)">.ctx.canvas.height);
            var i = 0 ; i < this.arr.length ; i++ 画圆函数
                this.drawCle(this.arr[i].x,1)">.arr[i].y);
            }
            return arr;
        }

         程序初始化
        canvasLock.prototype.init = () {
            .initDom();
            this.canvas = document.getElementById(''canvas''this.ctx = this.canvas.getContext(''2d''this.touchFlag = false 1、确定半径
             2、确定每一个圆的中心坐标点
             3、一行3个圆14个半径,一行4个圆有18个半径
            .createCircle();
            .bindEvent();
        }

        canvasLock.prototype.bindEvent = var self = this.canvas.addEventListener("touchstart",1)"> (e) {
                 2、touchstart判断是否点击的位置处于圆内getPosition,处于则初始化
                          * lastpoint、restPoint
                
                 po有x和y,并且是相较于canvas边距
                var po = self.getPosition(e);
                console.log(po.x)
                 判断是否在圆内的原理:多出来的这条 x/y < r 在圆内
                var i = 0 ; i < self.arr.length ; i++) {
                    if (Math.abs(po.x - self.arr[i].x) < self.r && Math.abs(po.y - self.arr[i].y) < self.r) {
                         
                        self.touchFlag = ;

                         lastPoint存放的就是选中的圆圈的x/y坐标值
                        self.lastPoint.push(self.arr[i]);

                        self.restPoint.splice(i,1);
                        break;
                    }
                }


            },);

            this.canvas.addEventListener("touchmove",1)"> (e) {

                touchmove做的就是:画圆drawPoint和划线drawLine
               if (self.touchFlag) {
                  self.update(self.getPosition(e));
               }
            },1)">this.canvas.addEventListener("touchend",1)">(e){
                 (self.touchFlag) {
                    self.storePass(self.lastPoint);
                    setTimeout((){
                       self.reset();
                   },300);
                }
            },1)">);
        }

        canvasLock.prototype.getPosition = function(e) { 获取touch点相对于canvas的坐标
            var rect = e.currentTarget.getBoundingClientRect();
             {
                x: (e.touches[0].clientX - rect.left),y: (e.touches[0].clientY - rect.top)
            };
            return po;
        }

        
        canvasLock.prototype.update = function(po) { 核心变换方法在touchmove时候调用
            .ctx.canvas.height);

             重新画9个圆圈
            this.arr.length ; i++) {  每帧先把面板画出来
                .arr[i].y);
            }

            this.drawPoint(); 画圆
            this.drawLine(po); 画线

             1、检测手势移动的位置是否处于下一个圆内
             2、圆内的话则画圆 drawPoint
             3、已经画过实心圆的圆,无需重复检测
            this.restPoint.length ; i++if (Math.abs(po.x - this.restPoint[i].x) < this.r && Math.abs(po.y - this.restPoint[i].y) < .r) {
                    .drawPoint();
                    this.lastPoint.push(.restPoint[i]);
                    this.restPoint.splice(i,1);
                    ;
                }
            }

            console.log(.lastPoint)

        }
        canvasLock.prototype.drawLine =  解锁轨迹
            this.ctx.linewidth = 3this.ctx.moveto(this.lastPoint[0].x,1)">this.lastPoint[0].y);
            var i = 1 ; i < this.lastPoint.length ; i++this.ctx.lineto(this.lastPoint[i].x,1)">.lastPoint[i].y);
            }
            .ctx.lineto(po.x,po.y);
            .ctx.stroke();
            .ctx.closePath();
        }
        canvasLock.prototype.drawPoint = function() {  初始化圆心 
            this.ctx.fill#CFE6FF'';
                .ctx.beginPath();
                this.ctx.arc(this.lastPoint[i].y,1)">this.r / 2,1)">);
                .ctx.closePath();
                .ctx.fill();
            }
        }

         1、检测路径是否是对的
         2、如果是对的就重置,圆圈变绿
         3、不对也重置,圆圈变红
         4、重置
        canvasLock.prototype.storePass = if (.checkPass()) {
                document.getElementById(''title'').innerHTML = ''解锁成功''this.drawStatusPoint(''#2CFF26'');
            }else{
                document.getElementById(''title'').innerHTML = ''解锁失败''this.drawStatusPoint(''red'');
            }
        }
        canvasLock.prototype.checkPass = var p1 = ''123'',p2 = '''') {
                p2 += .lastPoint[i].index;
            }
            return p1 === p2;
        }
        canvasLock.prototype.drawStatusPoint = (type) {
            this.ctx.strokeStyle = type;
                .ctx.stroke();
            }
        }
        canvasLock.prototype.reset = .createCircle();
        }
})();

总结

以上是小编为你收集整理的canvas手势解锁源码全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

今天关于canvas实现手机的手势解锁步骤详细的讲解已经结束,谢谢您的阅读,如果想了解更多关于canvas 图像旋转与翻转姿势解锁、canvas 实现vue 手势解锁组件、canvas实现手机端用来上传用户头像的代码、canvas手势解锁源码的相关知识,请在本站搜索。

本文标签:

上一篇html 出现粒子线条,鼠标移动会以鼠标为中心吸附的特效之canvas-nest.js插件

下一篇valid和invalid伪类美化表单案例