canvas学习(十五):学写一个字
先来张效果图:
这个特效是跟着慕课网上的视频学的,视频链接如下: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.onload=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.onmousedown=function(e){ e.preventDefault(); //console.log("mouse down"); startStroke({x:e.clientX,y:e.clientY}); } myCanvas.onmouseup=function(e){ e.preventDefault(); //console.log("mouse up"); endStroke(); } myCanvas.onmouseout=function(e){ e.preventDefault(); //console.log("mouse out"); endStroke(); } myCanvas.onmousemove=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").onclick=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(); }
相关推荐
大地飞鸿 2020-11-12
星星有所不知 2020-10-12
jinxiutong 2020-07-26
MIKUScallion 2020-07-05
songfens 2020-07-05
songfens 2020-06-11
songfens 2020-06-08
northwindx 2020-05-31
northwindx 2020-05-31
northwindx 2020-05-27
northwindx 2020-05-25
MIKUScallion 2020-05-25
jinxiutong 2020-05-10
xdyangxiaoromg 2020-05-10
大地飞鸿 2020-05-06
northwindx 2020-04-25