canvas結合js實現寫字繪圖功能


前陣子手上的事情比較少,研究了一下canvas畫圖,寫了一個簡單的demo,寫字和復顯寫字過程的功能。今天抽了個空把邏輯和代碼整理記錄一下。

先把效果圖展示一下:

  

 

下面附上源碼:

  

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0">
	<script src="./jquery.js"></script>
	<style>

		#canvas{
			display: block;
			margin: 0 auto;
		}
		#controller{
			width:800px;
			margin:0 auto;
		}
		.op_btn{
			float: right;
			margin:10px 0 0 10px;
			border:2px solid #aaa;
			width:80px;
			height:40px;
			line-height: 40px;
			text-align: center;
			font-size: 20px;
			border-radius: 5px;
			cursor: pointer;
			background-color:#fff;
			font-weight: bold
		}
		.op_btn:hover{
			background-color:#def;
		}
		.clearfix{
			clear: both;
		}
	</style>
</head>
<body>
	<canvas id="canvas"></canvas>
	<div id="controller">
		<div id="clear_btn" class="op_btn">清除</div>
		<div id="submit" class="op_btn">完成</div>
		<div class="clearfix"></div>
	</div>

	<canvas id="canvas_show"></canvas>
</body>
<script>

//調整畫筆粗細

var canvasWidth = Math.min(800,$(window).width()-20);
var canvasHeight = canvasWidth;

var isMouseDown = false;
var lastLoc = {x:0,y:0};//用戶上一次繪制的位置
var lastTimestamp = 0;
var lastLineWidth = -1;

//以下兩個變量(locHistory ,endTime )用於復顯寫字過程,將軌跡坐標和時間保存於本地,實際項目中應存於服務器端
var locHistory = [];
var endTime = '';

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
canvas.height = canvasHeight;
canvas.width = canvasWidth;

$('#controller').css('width',canvasWidth+'px')
drawGrid()
document.getElementById('clear_btn').onclick = function(){
	context.clearRect(0,0,canvasWidth,canvasHeight)
	drawGrid();//重繪底部寫字格
	localStorage.removeItem('locHistory') // 清除本地數據,實際項目中不需要
}
$('#submit').click(function(){
 //保存軌跡和時間到本地,實際項目中應將數據傳給服務器端
    localStorage.setItem('locHistory',JSON.stringify(locHistory))
})

//開始繪制
function beginStroke(point){
	isMouseDown = true
	// console.log('mouse down')
	lastTimestamp = new Date().getTime()

	lastLoc = windowToCanvas(point.x,point.y)

	locHistory.push({x:lastLoc.x,y:lastLoc.y,width:0,t:lastTimestamp-endTime})
}
function endStroke(){
	locHistory.push({x:lastLoc.x,y:lastLoc.y,width:0,t:0})
	isMouseDown = false;
	endTime = new Date().getTime()
	console.log(locHistory)
}
function moveStroke(point){
		// console.log("mouse move")
		 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)	
		  console.log(lineWidth)
		 //draw
		 context.beginPath()
		 context.moveTo(lastLoc.x,lastLoc.y)
		 context.lineTo(curLoc.x,curLoc.y)

		 locHistory.push({x:curLoc.x,y:curLoc.y,with:lineWidth,t:t})

		 context.lineWidth = lineWidth
		 context.lineCap = "round"
		 context.linJoin = "round"
		 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})
	}
}
// 移動端觸控
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 calcLineWidth(t,s){
	var v = s/t;
	var resultLineWidth;

	if(v <= 0.1){
		resultLineWidth = 20;
	}else if(v >= 10){
		resultLineWidth = 4
	}else{
		resultLineWidth = 20 - (v-0.1)/(10-0.1)*(20-4)
	}
	if(lastLineWidth == -1){
		return resultLineWidth
	}
	return lastLineWidth*2/3 + resultLineWidth*1/3
}
function calcDistance(loc1,loc2){
	return Math.sqrt((loc1.x - loc2.x)*(loc1.x - loc2.x) + (loc1.y - loc2.y)*(loc1.y - loc2.y))  //通過起始結束坐標x,y值計算路程長度
}
function windowToCanvas(x,y){
	var bbox = canvas.getBoundingClientRect(); //獲取canvas的位置信息
	return {x:Math.round(x-bbox.left),y:Math.round(y-bbox.top)}  //返回當前鼠標相對於canvas的位置
}
function drawGrid(){
	context.save()//保存context的原始狀態
	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.closePath()

	context.lineWidth = "1"
	context.stroke()

	context.restore()//避免影響外部的程序
}

//復顯繪制過程
var locaData = JSON.parse(localStorage.getItem('locHistory'))
var i = 0;
	console.log(locaData)
showFont() 
function showFont(){
 	i++;
 	if(i<locaData.length-1 && locaData[i].t != 0){
 		setTimeout(function(){
 		
 			 context.beginPath()
			 context.moveTo(locaData[i].x,locaData[i].y)
			 
			 context.lineTo(locaData[i-0+1].x,locaData[i-0+1].y)		

			 context.lineWidth = locaData[i].with;
			 context.lineCap = "round"
			 context.linJoin = "round"
			 context.stroke() ;

			 showFont()
 		},locaData[i].t)
 	}else if(i<locaData.length-1){
 		 showFont()
 	}

}



</script>
</html>

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM