适应web端和移动端的canvas写字板(初版)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="height=device-height
width=device-width,
initial-scale = 1.0,
minimum-scale = 1.0,
maximum-scale = 1.0,
user-scalable = no"/>
<title>Title</title>
</head>
<style>
#canvas{
display:block;
margin:0 auto;
/*border:1px solid #aaa;*/
}
</style>
<body>
<canvas id="canvas"></canvas>
</body>
<script>
var canvasWidth=Math.min(800,window.innerWidth-20);
var canvasHeight=canvasWidth;
var canvas=document.querySelector("#canvas");
canvas.width=canvasWidth;
canvas.height=canvasHeight;
var cx=canvas.getContext("2d");
var isMouseDown=false;
var lastLoc={x:0,y:0};
var lastTimestamp = 0;
var lastLineWidth = -1;

drawGrid();


//写字开始函数
function beginStroke(point) {
isMouseDown=true;
lastLoc=windowToCanvas(point.x,point.y);
lastTimestamp = new Date().getTime();
}
// 写字结束函数
function endStroke() {
isMouseDown=false;
}
// 写字函数函数
function moveStroke(point) {
var curLoc=windowToCanvas(point.x,point.y);
var curTimestamp = new Date().getTime();
var s = calcDistance(curLoc,lastLoc);
var t = curTimestamp - lastTimestamp;

var lineWidth = calcLineWidth(t,s);

// draw
cx.beginPath();
cx.moveTo(lastLoc.x,lastLoc.y);
cx.lineTo(curLoc.x,curLoc.y);

cx.strokeStyle="black";
cx.lineWidth=lineWidth;
cx.lineCap="round";
cx.lineJoin="round";
cx.stroke();

lastLoc = curLoc;
lastTimestamp=curTimestamp;
lastLineWidth = lineWidth;
}
canvas.onmousedown=function (e) {
e.preventDefault();
beginStroke({x:e.clientX,y:e.clientY})
};
canvas.onmouseup=function (e) {
e.preventDefault();
endStroke();
};
canvas.onmouseout=function (e) {
e.preventDefault();
endStroke();
};
canvas.onmousemove=function (e) {
e.preventDefault();
if(isMouseDown){
moveStroke({x:e.clientX,y:e.clientY})
}
};
// 移动端
canvas.addEventListener('touchstart',function (e) {
e.preventDefault();
// 触碰事件没有client,用e.touches.pageX取代;
touch = e.touches[0];//第一个手指
beginStroke({x:touch.pageX,y:touch.pageY})
});
canvas.addEventListener('touchmove',function (e) {
e.preventDefault();
touch = e.touches[0];
moveStroke({x:touch.pageX,y:touch.pageY})
});
canvas.addEventListener('touchend',function (e) {
e.preventDefault();
endStroke();
});


var maxLineWidth = 30;
var minLineWidth = 1;
var maxStrokeV = 10;
var minStrokeV = 0.1;
//速度快慢改变笔画粗细函数(毛笔字效果,还不完善),以上参数可调配,这个效果需要一定的数学技巧,可以不用这个函数,写的字也能看。
function calcLineWidth(t,s){
var v = s/t;
var resultLineWidth;

if(v<=minStrokeV)
resultLineWidth=maxLineWidth;
else if(v>=maxStrokeV)
resultLineWidth=minLineWidth;
else
resultLineWidth=maxLineWidth-(v-minStrokeV)/(maxStrokeV-minStrokeV)*(maxLineWidth-minLineWidth);

if(lastLineWidth == -1)
return resultLineWidth;
//改变resultLineWidth和lastLineWidth的比例可改变笔画平滑度
return resultLineWidth*1/3 + lastLineWidth*2/3;

}
//move时当前的点与上一个点的距离函数
function calcDistance(loc1,loc2) {
return Math.sqrt((loc1.x-loc2.x)*(loc1.x-loc2.x)+(loc1.y-loc2.y)*(loc1.y-loc2.y));
}
//鼠标在canvas上的坐标函数
function windowToCanvas(x,y){
var bbox=canvas.getBoundingClientRect();
return {x:Math.round(x-bbox.left),y:Math.round(y-bbox.top)}
}
//画网格函数
function drawGrid() {
cx.save();

cx.strokeStyle = "red";
cx.beginPath();
cx.moveTo(3, 3);
cx.lineTo(canvas.width - 3, 3);
cx.lineTo(canvas.width - 3, canvas.height - 3);
cx.lineTo(3, canvas.height - 3);
cx.closePath();

cx.lineWidth = 6;
cx.stroke();

cx.beginPath();
cx.moveTo(0, 0);
cx.lineTo(canvas.width, canvas.height);

cx.moveTo(canvas.width, 0);
cx.lineTo(0, canvas.height);

cx.moveTo(canvas.width / 2, 0);
cx.lineTo(canvas.width / 2, canvas.height);

cx.moveTo(0, canvas.height / 2);
cx.lineTo(canvas.width, canvas.height / 2);

cx.lineWidth = 1;
cx.stroke();

cx.restore();
}

</script>
</html>
原文地址:https://www.cnblogs.com/wabxl/p/6056280.html