线上demo:https://my.weblf.cn/xly/demo/canvas/hand.html
代码:
<!DOCTYPE html>
<html>
<head lang="en">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
name="viewport"/>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
<script type="text/javascript">
var R = 26, //半径
CW = 400, //画布默认宽度
CH = 320, //画布默认高度
OffsetX = 30, //距离左边距离
OffsetY = 30;//距离上面距离
//计算9个圆的圆心位置
function CaculateNinePointLotion(diffX, diffY) {
var Re = [];
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
var Point = {
X: (OffsetX + col * diffX + ( col * 2 + 1) * R),
Y: (OffsetY + row * diffY + (row * 2 + 1) * R)
};
Re.push(Point);
}
}
//返回9个圆心位置数组
return Re;
}
var PointLocationArr = [];
//页面加载完运行
window.onload = function () {
var c = document.getElementById("myCanvas");//获取元素
CW = document.body.offsetWidth;//获取浏览器宽度,并修改默认宽度
c.width = CW;//设置画布的宽高
c.height = CH;
var cxt = c.getContext("2d");//创建一个2d环境对象
//两个圆之间的外距离 就是说两个圆心的距离去除两个半径,由此算出x=两个圆之间的x距离,y=两个圆之间y距离。
var X = (CW - 2 * OffsetX - R * 2 * 3) / 2;
var Y = (CH - 2 * OffsetY - R * 2 * 3) / 2;
PointLocationArr = CaculateNinePointLotion(X, Y);//获取9个圆的圆心位置数组
InitEvent(c, cxt);//在这里已经调用监听手指触摸事件
Draw(cxt, PointLocationArr, [],null);//开始画九个圆,cxt=2d绘画环境,PointLocationArr=9个点的坐标,_LinePointArr=已连线的点数组,touchPoint=触摸到的x与y
}
//画圈画线方法
function Draw(cxt, _PointLocationArr, _LinePointArr,touchPoint){
if(_LinePointArr.length > 0){//如果连过线的点大于0,则画线
cxt.beginPath();
//则按顺序将连过的点的圆心用线连起来
for (var i = 0; i < _LinePointArr.length; i++) {
var pointIndex = _LinePointArr[i];
cxt.lineTo(_PointLocationArr[pointIndex].X, _PointLocationArr[pointIndex].Y);
}
cxt.lineWidth = 10;
cxt.strokeStyle = "#627eed";
cxt.stroke();
cxt.closePath();
//如果手指触摸的xy有值,那么就将连线的最后一个点当做起点,手指触摸的地方为终点连线
if(touchPoint!=null)
{
var lastPointIndex=_LinePointArr[_LinePointArr.length-1];
var lastPoint=_PointLocationArr[lastPointIndex];
cxt.beginPath();
cxt.moveTo(lastPoint.X,lastPoint.Y);
cxt.lineTo(touchPoint.X,touchPoint.Y);
cxt.stroke();
cxt.closePath();
}
}
//不论怎么样,都要花圆
for (var i = 0; i < _PointLocationArr.length; i++) {
var Point = _PointLocationArr[i];
cxt.fillStyle = "#627eed";
cxt.beginPath();
cxt.arc(Point.X, Point.Y, R, 0, Math.PI * 2, true);
cxt.closePath();
cxt.fill();
cxt.fillStyle = "#ffffff";
cxt.beginPath();
cxt.arc(Point.X, Point.Y, R - 3, 0, Math.PI * 2, true);
cxt.closePath();
cxt.fill();
//如果这个圆是连线了的,则改变颜色
if(_LinePointArr.indexOf(i)>=0)
{
cxt.fillStyle = "#627eed";
cxt.beginPath();
cxt.arc(Point.X, Point.Y, R -16, 0, Math.PI * 2, true);
cxt.closePath();
cxt.fill();
}
}
}
//判断点是否被选中
function IsPointSelect(touches,LinePoint)
{
for (var i = 0; i < PointLocationArr.length; i++) {
var currentPoint = PointLocationArr[i];
var xdiff = Math.abs(currentPoint.X - touches.pageX);
var ydiff = Math.abs(currentPoint.Y - touches.pageY);
var dir = Math.pow((xdiff * xdiff + ydiff * ydiff), 0.5);
if (dir < R ) {
if(LinePoint.indexOf(i) < 0){ LinePoint.push(i);}
break;
}
}
}
//监听触摸事件
function InitEvent(canvasContainer, cxt) {
var LinePoint = [];
canvasContainer.addEventListener("touchstart", function (e) {
IsPointSelect(e.touches[0],LinePoint);
}, false);
canvasContainer.addEventListener("touchmove", function (e) {
e.preventDefault();
var touches = e.touches[0];
IsPointSelect(touches,LinePoint);
cxt.clearRect(0,0,CW,CH);
Draw(cxt,PointLocationArr,LinePoint,{X:touches.pageX,Y:touches.pageY});
}, false);
canvasContainer.addEventListener("touchend", function (e) {
cxt.clearRect(0,0,CW,CH);
Draw(cxt,PointLocationArr,LinePoint,null);
alert("密码结果是:"+LinePoint.join("->"));
LinePoint=[];
}, false);
}
</script>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
</html>
原文:https://www.cnblogs.com/linfblog/p/12147300.html