基于canvas通过touch事件来画箭头的方法
**
注意:我用的是touch事件,需要在f12中将切换为ipad才可以看到效果
**
目前在看到的一般只是直接生成出一个箭头,不是真正画笔画出它的效果,下方是使用touch事件完成的demo源码,当然如果您喜欢,也可以将它换成其他的事件来触发。
touch事件在windows网页中无效不知道怎么处理的朋友们,可以进入f12开发者工具中,点击下图圆圈位置,选择iPad查看
梳理思路:
画线的难度不高,我们的问题一般都纠结在箭头的画法
我们首先要知道箭头指向的方向与箭头头部展开大小的夹角进行运算
我们需要:起始点坐标,结束点坐标,箭头开叉的尾部两个点的坐标
整理完需求,我们先针对没使用过Math算过角度的兄台展示个简单的小例子
举个例子:
我们都知道坐标点(1,1)与(0,0)的夹角为45°
我们怎么通过js程序来得到它的角度?
我们可以通过公式
Math.atan2(y,x) 来得出弧度
而弧度转为角度的公式为:
Math.atan2(y, x) * 180 / Math.PI
不多逼逼,直接根据公式上代码:
var x0=0;
var y0=0;
var x1=1;
var y1=1;
var res = Math.atan2(y1-y0,x1-x0)*180/Math.PI;
console.log(res);//打印得到45°
由上可知我们拿到了角度为45°,此处需要注意的是,谁减谁不要搞错了,用结束位置减去起始位置得到的是我们想拿到的角度,如果上方变为(y0-y1,x0-x1),此处的结果为-135°
然而在js中,我们要拿到它夹角
角= 弧度 * Math.PI / 180
既然这样:
再假定我们的点为(0,0)和(1,0),可以知道角度为0,我们主要是想拿到它箭头开叉两边的尾部点的位置
假设箭头开叉的大小设定为30°,尝试着写一下逻辑:
//我们假设点为(0,0)和(1,0)
var fromX = 0;
var fromY = 0;
var toX = 1;
var toY = 0;
var color = "#f00";
function drawAngle(ctx,fromX,fromY,toX,toY){
var arrow1_x, arrow1_y, arrow2_x, arrow2_y; //定义箭头开叉的尾部两个点的坐标
var customAngle = 30; //箭头开叉的大小设定为30°
var arrowLangth = 20; //箭头长度为20
var angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI; //拿到起始点与结束点的夹角,因为我们用起始点减去结束点的坐标,所以目前为180°,为什么用180°不用0°呢,因为在下方的arrow1_x部分如果是0°的话,需要有减法运算,这样的话,反方向画线的时候会有问题,所以都使用加法,这个了解一下就可以了,如果不理解,建议使用0°试一下,如果改成0°的话,下方arrow1_x和arrow2_x的赋值过程中需要把后面toX+X变为toX-X
var angle1 = angle + customAngle; //箭头上方的线与中间直线的角度
var angle2 = angle - customAngle; //箭头下方的线与中间直线的角度
//JS中sin和cos的参数都为弧度,不要直接把角度传进去
var X1 = arrowLangth * Math.cos(angle1 * Math.PI / 180); //得到上方开叉的尾部到中间直线的X轴的长度
var Y1 = arrowLangth * Math.sin(angle1 * Math.PI / 180); //得到上方开叉的尾部到中间直线Y轴(切线)的长度
var X2 = arrowLangth * Math.cos(angle2 * Math.PI / 180); //得到下方开叉的尾部到中间直线的X轴的长度
var Y2 = arrowLangth * Math.sin(angle2 * Math.PI / 180); //得到下方开叉的尾部到中间直线Y轴(切线)的长度
console.log(X1 + "||" + X2);
arrow1_x = toX + X1; //上方开叉的尾部点的x坐标
arrow1_y = toY + Y1; //上方开叉的尾部点的y坐标
arrow2_x = toX + X2; //下方开叉的尾部点的x坐标
arrow2_y = toY + Y2; //下方开叉的尾部点的y坐标
//虚线(中间那条长线)
ctx.beginPath();
ctx.setLineDash([15, 5]); //虚线
ctx.moveTo(fromX, fromY); //起始点
ctx.lineTo(toX, toY); //结束点
ctx.strokeStyle = color; //虚线颜色
ctx.stroke();
//画上边箭头线
ctx.beginPath();
ctx.setLineDash([]);
ctx.moveTo(arrow1_x, arrow1_y); //上箭头坐标
ctx.lineTo(toX, toY);
ctx.lineTo(arrow2_x, arrow2_y); //下箭头坐标
ctx.strokeStyle = color;
ctx.stroke();
}
可以直接使用的Demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<!-- <meta name="apple-mobile-web-app-capable" content="yes" /> -->
<link rel="shortcut icon" href="#">
<script src="static/vendors/jquery/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="static/vendors/bootstrap/bootstrap.css">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
<style type="text/css">
* {
margin: 0;
padding: 0;
}
html,
body {
width: 100vw;
height: 70vh;
background-color: skyblue;
}
</style>
</head>
<body>
<div id="body_" style="width: 100%;height: 100%;box-sizing: border-box;">
<div id="centerBox" style="width: 960px;height: 540px;margin:0 auto;margin-top: 20px;background: url('./img/1.jpg') center 0;background-size: cover;border:solid 1px #000;" ontouchmove="return false;">
<canvas id="my" style="border: 0px solid #f00;width: 960px;height: 540px;position: absolute;z-index: 9;"></canvas>
</div>
</div>
</body>
<script type="text/javascript">
var c = document.getElementById("my");
c.width = 960;
c.height = 540;
var ctx = c.getContext("2d");
var lineInitColor = "#0f0";
var clineWidth = 2
// 绘制方法
var boxGesture = setGesture(c); //得到一个对象
ctx.lineWidth = clineWidth;
function setGesture(el) {
var obj = {}; //定义一个对象
var istouch = false;
var start = [];
var One_hd = [];
var can_move = false;
el.addEventListener("touchstart", function(e) {
ctx.strokeStyle = lineInitColor;
startX = e.changedTouches[0].clientX - c.offsetLeft;
startY = e.changedTouches[0].clientY - c.offsetTop;
console.log(startX + "---start--" + startY); //鼠标按下
return false;
}, false);
el.addEventListener("touchmove", function(e) {
movingX = e.changedTouches[0].clientX - c.offsetLeft;
movingY = e.changedTouches[0].clientY - c.offsetTop;
console.log(movingX + "---moving--" + movingY);
}, false);
el.addEventListener("touchend", function(e) {
endX = e.changedTouches[0].clientX - c.offsetLeft;
endY = e.changedTouches[0].clientY - c.offsetTop;
console.log(endX + "---end--" + endY);
drawLineBroken(ctx, startX, startY, endX, endY, lineInitColor);
return false;
}, false);
return obj;
};
//虚线
function drawLineBroken(ctx, fromX, fromY, toX, toY, color) {
var arrow1_x, arrow1_y, arrow2_x, arrow2_y; //定义箭头开叉的尾部两个点的坐标
var customAngle = 30; //假设夹角设定为30°
var arrowLangth = 20; //箭头长度为20
if (fromX == toX && fromY == toY) {
// 开始和结束在同一点
} else {
var angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI; //拿到夹角,目前为180°
}
var angle1 = angle + customAngle; //箭头上方的线与中间直线的角度
var angle2 = angle - customAngle; //箭头下方的线与中间直线的角度
//JS中sin和cos的参数都为弧度,不要直接把角度传进去
var X1 = arrowLangth * Math.cos(angle1 * Math.PI / 180); //得到上方开叉的尾部到中间直线的X轴的长度
var Y1 = arrowLangth * Math.sin(angle1 * Math.PI / 180); //得到上方开叉的尾部到中间直线Y轴(切线)的长度
var X2 = arrowLangth * Math.cos(angle2 * Math.PI / 180); //得到下方开叉的尾部到中间直线的X轴的长度
var Y2 = arrowLangth * Math.sin(angle2 * Math.PI / 180); //得到下方开叉的尾部到中间直线Y轴(切线)的长度
console.log(X1 + "||" + X2);
arrow1_x = toX + X1; //上方开叉的尾部点的x坐标
arrow1_y = toY + Y1; //上方开叉的尾部点的y坐标
arrow2_x = toX + X2; //下方开叉的尾部点的x坐标
arrow2_y = toY + Y2; //下方开叉的尾部点的y坐标
//虚线(中间那条长线)
ctx.beginPath();
ctx.setLineDash([15, 5]); //虚线
ctx.moveTo(fromX, fromY); //起始点
ctx.lineTo(toX, toY); //结束点
ctx.strokeStyle = color; //虚线颜色
ctx.stroke();
//画上边箭头线
ctx.beginPath();
ctx.setLineDash([]);
ctx.moveTo(arrow1_x, arrow1_y); //上箭头坐标
ctx.lineTo(toX, toY);
ctx.lineTo(arrow2_x, arrow2_y); //下箭头坐标
ctx.strokeStyle = color;
ctx.stroke();
}
</script>
</html>
效果
尽情的瞎画吧兄台们