html部分:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="http://cdn.bootcss.com/jquery/2.2.4/jquery.js"></script>
<link rel="stylesheet" type="text/css" href="css/handwriting.css">
<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>
</head>
<body>
<canvas id="canvas"></canvas>
<div class="bottom-button">
<div class="black color"></div>
<div class="green color"></div>
<div class="red color"></div>
<div class="yellow color"></div>
<div class="gray color"></div>
<div class="blue color"></div>
<button class="clear" value="">清除</button>
</div>
<script src="js/handwriting.js" type="text/jscript"></script>
</body>
</html>
css部分:
@charset "utf-8";
/* CSS Document */
body{text-alien:center;}
#canvas {
display: block;
margin: 0 auto;
}
.bottom-button{ height:300px; margin:0 auto; margin-top:20px;}
.color{ float:left;width:30px; height:30px; margin-right:15px; cursor:pointer;}
.color:hover{border:#93F 1px solid}
.blue{ background-color:#00F;}
.yellow{ background-color:#FF0}
.green{ background-color:#0F0}
.red{ background-color:#F00;}
.gray{ background-color:#666;}
.black{ background-color:#000;}
.clear{background-color:80px; height:30px; float:right;}
js部分:
var canvasWidth=Math.min(800,$(window).width()-20);
var canvasHeight=canvasWidth;
var canvas = document.getElementById('canvas');
var cxt = canvas.getContext('2d');
var isMouseDown=false;
var lastloc={x:0,y:0}
var LastTimestamp=0;
var lastlinewidth=-1;
var strokecolor="black";
canvas.width=canvasWidth;
canvas.height=canvasHeight;
$('.bottom-button').css('width',canvasWidth+'px');
drawGrid();
$('.clear').click(function(){
cxt.clearRect(0,0,canvasWidth,canvasHeight);
drawGrid();
});
$('.color').click(function(){
strokecolor=$(this).css('background-color');
$(this).css('border','red 2px solid').siblings().css('border','none');
});
//开始绘制
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);
cxt.beginPath();
cxt.moveTo(lastloc.x,lastloc.y);
cxt.lineTo(curloc.x,curloc.y);
cxt.strokeStyle=strokecolor;
cxt.lineWidth=lineWidth;
cxt.lineCap='round';
cxt.lineJoin='round';
cxt.stroke();
lastloc=curloc;
LastTimestamp=curTimestamp;
lastlinewidth=lineWidth;
}
//pc版绘制
canvas.οnmοusedοwn=function(e){
e.preventDefault();
beginstroke({x:e.clientX,y:e.clientY});
};
canvas.οnmοuseup=function(e){
e.preventDefault();
endstroke()
};
canvas.οnmοuseοut=function(e){
e.preventDefault();
endstroke()
};
canvas.οnmοusemοve=function(e){
e.preventDefault();
if( isMouseDown){
movestroke({x:e.clientX,y:e.clientY});
}
};
//移动端绘制
canvas.addEventListener('touchstart',function(e){
e.preventDefault();
touch=e.touches[0];
beginstroke({x:touch.pageX,y:touch.pageY});
});
canvas.addEventListener('touchmove',function(e){
e.preventDefault();
if( isMouseDown){
touch=e.touches[0];
movestroke({x:touch.pageX,y:touch.pageY});
}
});
canvas.addEventListener('touchend',function(e){
e.preventDefault();
endstroke();
});
function calcDistance(loc1,loc2){
return Math.sqrt((loc1.x-loc2.x)*(loc1.x-loc2.x)+(loc1.y-loc2.y)*(loc1.y-loc2.y));
}
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=30-(v-minstrokev)*(maxlinewidth-minlinewidth)/(maxstrokev-minstrokev)+1;
}
if(lastlinewidth==-1){return resultLineWidth;}
else{return lastlinewidth*2/3 + resultLineWidth*1/3 }
}
function windowTocanvas(x,y)
{
var bbox= canvas.getBoundingClientRect();
return{ x:Math.round(x-bbox.left),y:Math.round(y-bbox.top)}
}
//绘制底框
function drawGrid(){
cxt.save();
cxt.strokeStyle="red";
cxt.beginPath();
cxt.moveTo(3,3);
cxt.lineTo(canvasWidth-3,3);
cxt.lineTo(canvasWidth-3,canvasHeight-3);
cxt.lineTo(3,canvasHeight-3);
cxt.closePath();
cxt.lineWidth=6;
cxt.stroke();
cxt.strokeStyle="red";
cxt.fillStyle="red";
//绘制实线格
/* cxt.moveTo(0,canvasHeight/2);
cxt.lineTo(canvasWidth,canvasHeight/2);
cxt.moveTo(canvasWidth/2,0);
cxt.lineTo(canvasWidth/2,canvasHeight);
cxt.moveTo(0,0);
cxt.lineTo(canvasWidth,canvasHeight);
cxt.moveTo(0,canvasHeight);
cxt.lineTo(canvasWidth,0);
cxt.lineWidth=1;
cxt.stroke();*/
//绘制虚线格
for(i=0;i<120;i++){
var x1=canvasWidth/120*i;
var y1=canvasHeight/2;
cxt.beginPath();
cxt.arc(x1, y1, 1, 0, Math.PI * 2, false);
cxt.fill();
var x2=canvasWidth/2;
var y2=canvasHeight/120*i;
cxt.beginPath();
cxt.arc(x2, y2, 1, 0, Math.PI * 2, false);
cxt.fill();
}
for(r=0;r<200;r++){
var x3=canvasWidth/200*r;
var y4=canvasHeight/200*r;
cxt.beginPath();
cxt.arc(x3, y4, 1, 0, Math.PI * 2, false);
cxt.fill();
var x3=canvasWidth/200*r;
var y4=canvasHeight/200*(200-r);
cxt.beginPath();
cxt.arc(x3, y4, 1, 0, Math.PI * 2, false);
cxt.fill();
}
cxt.restore();
}
运行结果: