先来张效果图:
这个特效是跟着慕课网上的视频学的,视频链接如下:https://www.imooc.com/learn/284
源码和技术点已经上传到附件,有需要的可以查看、下载。
下面直接上代码(PS:代码中的注释是根据个人理解添加的,并不是老师原有的注释):
页面结构:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="Generator" content="EditPlus®">
<meta name="Author" content="">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>canvas学习-学写一个字</title>
<link type="text/css" href="handwriting.css" rel="stylesheet"/>
<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"/>
<script type="text/javascript" src="handwriting.js"></script>
<script type="text/javascript" src="jquery.min.js"></script>
</head>
<body>
<canvas id="myCanvas">
您的浏览器不支持canvas,请换个浏览器试试
<!--这句话在支持canvas的浏览器中会被忽略,不支持的则会显示出来-->
</canvas>
<!--颜色选择和清除 -->
<div id="controller">
<div id="black_btn" class="color_btn color_btn_selected"></div>
<div id="red_btn" class="color_btn"></div>
<div id="orange_btn" class="color_btn"></div>
<div id="yellow_btn" class="color_btn"></div>
<div id="green_btn" class="color_btn"></div>
<div id="cyan_btn" class="color_btn"></div>
<div id="blue_btn" class="color_btn"></div>
<div id="clear_btn" class="op_btn">清 除</div>
<div class="clearfix"></div>
</div>
</body>
</html>
CSS样式:
#myCanvas{
height:100%;
display:block;
margin:0 auto;
}
#controller{
margin:0 auto;
}
.op_btn{
float:right;
margin:10px 0 0 10px;
border:2px solid #aaa;
width:80px;
height:40px;
line-height:40px;
font-size:20px;
text-align:center;
border-radius:5px 5px;
cursor:pointer;
background-color:white;
font-weight:bold;
font-family:Microsoft Yahei,Arial;
}
.op_btn:hover{
background-color:#def;
}
.clearfix{
clear:both;
}
.color_btn{
float:left;
margin:10px 5px 0 0;
border:5px solid white;
width:40px;
height:40px;
border-radius:5px 5px;
cursor:pointer;
}
.color_btn:hover{
border:5px solid violet;
}
.color_btn_selected{
border:5px solid blueviolet;
}
#black_btn{
background-color:black;
}
#red_btn{
background-color:red;
}
#orange_btn{
background-color:orange;
}
#yellow_btn{
background-color:yellow;
}
#green_btn{
background-color:green;
}
#blue_btn{
background-color:blue;
}
#cyan_btn{
background-color:cyan;
}
JS代码:
//学习链接:http://www.imooc.com/learn/284 var windowWidth = 600; var windowHeight = 600; var isMouseDowm=false;//鼠标是否按下 var myCanvas = null; var context = null; var lastLoc = {x:0,y:0};//鼠标最后一个落脚点 var lastTimestamp=0; var lastLineWidth = -1;//最后一次笔画的大小 var strokeColor = "black"; window.οnlοad=function(){ myCanvas = document.getElementById("myCanvas"); if(myCanvas.getContext("2d")){ windowWidth = document.documentElement.clientWidth-20; windowHeight = document.documentElement.clientHeight-20-60;//60:清除按钮所需要的高度 //取两个数中最小的那个值 if(windowWidth>windowHeight){windowWidth = windowHeight;} else{windowHeight = windowWidth;} //alert(windowWidth); myCanvas.width = windowWidth; myCanvas.height = windowHeight; context =myCanvas.getContext("2d"); //alert(myCanvas.width+"\n"+myCanvas.height); //控制功能区的大小 $("#controller").css("width",windowWidth+"px"); //绘制一个米字格 drawGird(); //阻止鼠标的默认事件 myCanvas.οnmοusedοwn=function(e){ e.preventDefault(); //console.log("mouse down"); startStroke({x:e.clientX,y:e.clientY}); } myCanvas.οnmοuseup=function(e){ e.preventDefault(); //console.log("mouse up"); endStroke(); } myCanvas.οnmοuseοut=function(e){ e.preventDefault(); //console.log("mouse out"); endStroke(); } myCanvas.οnmοusemοve=function(e){ e.preventDefault(); if(isMouseDowm){ //console.log("mouse move"); moveStroke({x:e.clientX,y:e.clientY}); } } //添加触控事件 myCanvas.addEventListener("touchstart",function(e){ e.preventDefault(); var touch = e.touches[0];//只获取一个触控点 startStroke({x:touch.pageX,y:touch.pageY}); }); myCanvas.addEventListener("touchend",function(e){ e.preventDefault(); endStroke(); }); myCanvas.addEventListener("touchmove",function(e){ e.preventDefault(); if(isMouseDowm){ var touch = e.touches[0];//只获取一个触控点 moveStroke({x:touch.pageX,y:touch.pageY}); } }); //清除功能 document.getElementById("clear_btn").οnclick=function(){ //清除画布中的内容 context.clearRect(0,0,windowWidth,windowHeight); //重新绘制米字格 drawGird(); } //选择颜色功能 $(".color_btn").click(function(){ //清除选中状态 $(".color_btn").removeClass("color_btn_selected"); $(this).addClass("color_btn_selected"); strokeColor = $(this).css("background-color"); }); }else{ return false; } } //开始绘制 function startStroke(point){ isMouseDowm=true; lastLoc = windowToCanvas(point.x,point.y); lastTimestamp = new Date().getTime(); //alert(lastLoc.x+","+lastLoc.y); } //结束绘制 function endStroke(){ isMouseDowm=false; } //绘制过程中 function moveStroke(point){ //获取鼠标所在canvas的当前位置 var curLoc = windowToCanvas(point.x,point.y); //添加“根据写字速度的快慢调整笔画大小”的应用 //计算两个点之间的距离 var s = calcDistance(curLoc,lastLoc); //计算绘制两个点需要的时间 var curTimestamp = new Date().getTime(); var t = curTimestamp-lastTimestamp;//使用当前时间减去最后一个落笔的时间 //根据s和t的值计算线的宽度 var lineWidth = calcLineWidth(s,t); //alert(curLoc); context.beginPath(); context.moveTo(lastLoc.x,lastLoc.y); context.lineTo(curLoc.x,curLoc.y); context.closePath(); context.strokeStyle = strokeColor; context.lineCap="round"; context.lineJoin="round"; context.lineWidth = lineWidth; context.stroke(); lastLoc = curLoc; lastTimestamp = curTimestamp; lastLineWidth = lineWidth; } //该方法用来将窗口坐标转换成canvas中的坐标 function windowToCanvas(x,y){ var bbox = myCanvas.getBoundingClientRect(); return {x:Math.round(x-bbox.left),y:Math.round(y-bbox.top)}; } //该方法用来计算两个点之间的距离 function calcDistance(loc1,loc2){ return Math.sqrt((loc1.x-loc2.x)*(loc1.x-loc2.x)+(loc1.y-loc2.y)*(loc1.y-loc2.y)); } //该方法根据路程和时间计算速度,依次计算线条宽度 function calcLineWidth(s,t){ var v = s/t; //先判断运笔速度较快和较慢时的情况 var min = 5,max = 20;//笔画大小 var min2 = 0.5,max2=10;//运笔速度大小 var result = min; if(v<=min2){//运笔速度特别慢,那么笔画应该特别大 result = max; }else if(v>=max2){//运笔速度特别快,那么笔画应该特别小 result = min; }else{//不快也不慢的情况下,使用差值的方式逐渐减 //计算方法:使用最大值-(当前速度与最小速度之间的差值)占(最大速度与最小速度之间差值)的比例 * (最大笔画与最小笔画之间的差值) result = max - (v-min2)/(max2-min2)*(max-min) } //解决平滑问题 if(lastLineWidth==-1){//说明还没有赋值 return result; } return lastLineWidth*3/4+result*1/4; } //该方法用来绘制米字格 function drawGird(){ context.save(); //绘制一个红色的正方形 context.strokeStyle="rgb(230,11,9)"; context.beginPath(); context.rect(0,0,windowWidth,windowWidth); context.closePath(); context.lineWidth = 5; context.stroke(); //绘制米字格 context.beginPath(); context.moveTo(0,0); context.lineTo(windowWidth,windowHeight); context.moveTo(windowWidth/2,0); context.lineTo(windowWidth/2,windowHeight); context.moveTo(windowWidth,0); context.lineTo(0,windowHeight); context.moveTo(0,windowHeight/2); context.lineTo(windowWidth,windowHeight/2); context.closePath(); context.lineWidth = 1; context.stroke(); context.restore(); }