使用canvas制作“学写一个字”
2018-04-08 本文已影响0人
伯纳乌的追风少年
image.png
主要就是这样一个程序,选择一种颜色,然后可以用鼠标或者手指在米字格中绘制想要的文字,点击“清除”按钮可以清除米字格中的内容。笔画的粗细与书写的速度成反比,滑动速度越快,则笔画效果越细。
不多解释,直接贴代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"
content="width=device-width,
height=device-height,
initial-scale=1.0,
minimum-scale=1.0,
maximum-scale=1.0,
user-scalable=no
">
<title>学写一个字</title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<style>
#canvas{
display:block;
margin:0 auto;
border: 1px solid #ccc;
}
#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 10px 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;
}
#blue_btn{
background-color: blue;
}
#green_btn{
background-color: green;
}
#red_btn{
background-color: red;
}
#orange_btn{
background-color: orange;
}
#yellow_btn{
background-color: yellow;
}
</style>
</head>
<body>
<canvas id="canvas">您的浏览器不支持canvas</canvas>
<div id="controller">
<div id="black_btn" class="color_btn color_btn_selected"></div>
<div id="blue_btn" class="color_btn"></div>
<div id="green_btn" class="color_btn"></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="clear_btn" class="op_btn">清除</div>
<div class="clearfix"></div>
</div>
<script type="text/javascript">
var canvasWidth=Math.min(800,$(window).width()-20)
var canvasHeight=canvasWidth
var canvas=document.getElementById("canvas")
var context=canvas.getContext("2d")
canvas.width=canvasWidth;
canvas.height=canvasHeight;
var isMouseDown=false;
var lastLoc={
x:0,
y:0
}
var lastTimestamp=0
var lastLineWidth=-1
var strokeColor="black"
function drawGrid(){
context.save()
context.strokeStyle = "rgb(230,11,9)"
context.beginPath()
context.moveTo( 3 , 3 )
context.lineTo( canvasWidth - 3 , 3 )
context.lineTo( canvasWidth - 3 , canvasHeight - 3 )
context.lineTo( 3 , canvasHeight - 3 )
context.closePath()
context.lineWidth = 6
context.stroke()
context.beginPath()
context.moveTo(0,0)
context.lineTo(canvasWidth,canvasHeight)
context.moveTo(canvasWidth,0)
context.lineTo(0,canvasHeight)
context.moveTo(canvasWidth/2,0)
context.lineTo(canvasWidth/2,canvasHeight)
context.moveTo(0,canvasHeight/2)
context.lineTo(canvasWidth,canvasHeight/2)
context.lineWidth = 1
context.stroke()
context.restore()
}
//绘制米字格
drawGrid()
$("#controller").css("width",canvasWidth+"px")
function beginStroke(obj){
isMouseDown=true
lastLoc=windowToCanvas(obj.x,obj.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)
context.beginPath();
context.moveTo(lastLoc.x,lastLoc.y)
context.lineTo(curLoc.x,curLoc.y)
context.lineWidth=lineWidth;
context.lineCap="round"
context.lineJoin="round"
context.strokeStyle=strokeColor
context.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})
}
};
//触控事件:touchstart,touchmove,touchend
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()
})
//坐标系的转换----将鼠标事件的坐标系换成canvas的坐标系
function windowToCanvas(x,y){
var bbox=canvas.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))
}
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
}
return lastLineWidth*2/3+resultLineWidth/3
}
$("#clear_btn").click(function(e){
context.clearRect(0,0,canvasWidth,canvasHeight)
drawGrid()
})
$(".color_btn").click(function(e){
$(".color_btn").removeClass("color_btn_selected")
$(this).addClass("color_btn_selected")
strokeColor=$(this).css("background-color")
})
</script>
</body>
</html>
把这个代码保存成一个index.html文件,然后在浏览器中打开即可。