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