
我最近研究了html5 canvas,并想编写一个小项目并进行实践. 结果,我写了一个具有功能点的绘图板,例如绘图,线条,圆形,正方形,涂鸦,线条粗细,颜色切换,撤消,回滚. 用于保存,下载和拖动外部图片的技术包括本地存储html5中的下载,下载和画布技术,如上所示.

演示地址: %E7%94%BB%E5%9B%BE%E6%9D%BF /
该项目使用了画布的许多基本功能. 在这里解释核心代码的想法.

在此项目中我使用了2层画布,因为用户希望在绘制某些图形(例如绘制圆)时看到绘制过程,并且该画布当前支持清空和绘制操作,因此在这里我使用了bak层产生幻觉. 用户的所有初始图形都在bak层中完成,然后释放鼠标时,它将被保存到真实的画布层中. 这是核心思想.
接下来,我们看一下代码的结构.
1. 首先. 它进行对象初始化,包括初始化画布,上下文画图板教程,高度和宽度. 这非常简单,解释不多. 代码如下.
//初始化
var initCanvas = function(){
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
context = canvas.getContext('2d');
canvasTop = $(canvas).offset().top
canvasLeft = $(canvas).offset().left;
canvas_bak = document.getElementById("canvas_bak");
canvas_bak.width = canvasWidth;
canvas_bak.height = canvasHeight;
context_bak = canvas_bak.getContext('2d');
}

2. 第二部分是绘图. 这个想法是确定单击鼠标时的起始点,并在鼠标移动时开始绘制. 如前所述,鼠标移动仅在bak层上进行. 释放鼠标后,bak层将添加到画布层. 所以这是三个事件. 单击,移动,释放,分别对应三种不同的方法. 代码如下:
//鼠标按下获取 开始xy开始画图
var mousedown = function(e){
context.strokeStyle= color;
context_bak.strokeStyle= color;
context_bak.lineWidth = size;
e=e||window.event;
startX = e.clientX - canvasLeft;
startY = e.clientY - canvasTop;
context_bak.moveTo(startX ,startY );
canDraw = true;
if(graphType == 'pencil'){
context_bak.beginPath();
}else if(graphType == 'circle'){
context.beginPath();
context.moveTo(startX ,startY );
context.lineTo(startX +2 ,startY+2);
context.stroke();
}else if(graphType == 'rubber'){
context.clearRect(startX - size * 10 , startY - size * 10 , size * 20 , size * 20);
}
};
//鼠标离开 把蒙版canvas的图片生成到canvas中
var mouseup = function(e){
e=e||window.event;
canDraw = false;
var image = new Image();
if(graphType!='rubber'){
image.src = canvas_bak.toDataURL();
image.onload = function(){
context.drawImage(image , 0 ,0 , image.width , image.height , 0 ,0 , canvasWidth , canvasHeight);
clearContext();
saveImageToAry();
}
var x = e.clientX - canvasLeft;
var y = e.clientY - canvasTop;
context.beginPath();
context.moveTo(x ,y );
context.lineTo(x +2 ,y+2);
context.stroke();
}
};
// 鼠标移动
var mousemove = function(e){
e=e||window.event;
var x = e.clientX - canvasLeft;
var y = e.clientY - canvasTop;
//方块 4条直线搞定
if(graphType == 'square'){
if(canDraw){
context_bak.beginPath();
clearContext();
context_bak.moveTo(startX , startY);
context_bak.lineTo(x ,startY );
context_bak.lineTo(x ,y );
context_bak.lineTo(startX ,y );
context_bak.lineTo(startX ,startY );
context_bak.stroke();
}
//直线
}else if(graphType =='line'){
if(canDraw){
context_bak.beginPath();
clearContext();
context_bak.moveTo(startX , startY);
context_bak.lineTo(x ,y );
context_bak.stroke();
}
//画笔
}else if(graphType == 'pencil'){
if(canDraw){
context_bak.lineTo(e.clientX - canvasLeft ,e.clientY - canvasTop);
context_bak.stroke();
}
//圆 未画得时候 出现一个小圆
}else if(graphType == 'circle'){
clearContext();
if(canDraw){
context_bak.beginPath();
var radii = Math.sqrt((startX - x) * (startX - x) + (startY - y) * (startY - y));
context_bak.arc(startX,startY,radii,0,Math.PI * 2,false);
context_bak.stroke();
}else{
context_bak.beginPath();
context_bak.arc(x,y,20,0,Math.PI * 2,false);
context_bak.stroke();
}
//涂鸦 未画得时候 出现一个小圆
}else if(graphType == 'handwriting'){
if(canDraw){
context_bak.beginPath();
context_bak.strokeStyle = color;
context_bak.fillStyle = color;
context_bak.arc(x,y,size*10,0,Math.PI * 2,false);
context_bak.fill();
context_bak.stroke();
context_bak.restore();
}else{
clearContext();
context_bak.beginPath();
context_bak.fillStyle = color;
context_bak.arc(x,y,size*10,0,Math.PI * 2,false);
context_bak.fill();
context_bak.stroke();
}
//橡皮擦 不管有没有在画都出现小方块 按下鼠标 开始清空区域
}else if(graphType == 'rubber'){
context_bak.lineWidth = 1;
clearContext();
context_bak.beginPath();
context_bak.strokeStyle = '#000000';
context_bak.moveTo(x - size * 10 , y - size * 10 );
context_bak.lineTo(x + size * 10 , y - size * 10 );
context_bak.lineTo(x + size * 10 , y + size * 10 );
context_bak.lineTo(x - size * 10 , y + size * 10 );
context_bak.lineTo(x - size * 10 , y - size * 10 );
context_bak.stroke();
if(canDraw){
context.clearRect(x - size * 10 , y - size * 10 , size * 20 , size * 20);
}
}
};
顺便说一下,撤消和回滚. 前面提到过,释放鼠标时,我们会将bak层的内容绘制到canvas层中. 然后,此时,图片信息将存储在数组中以进行回滚. 当单击“撤消”时,您只需要取出先前的图片信息并再次绘制画布. 撤消和还原也是如此.
4. 接下来说说保存功能的实现. 使用HTML5的存储功能保存图像. 存储是打开5M控制提供程序的浏览器. 开发人员使用存储键值的键值对. 它们类似于cookie,因此女性保存的实施非常简单. 单击保存按钮时,可以获取图片的dataUrl. 保存并存储,下次打开浏览器,进入画布. 代码如下:

//保存
var save = function(){
for(var i = 1;i<=8;i++){
var dataUrl = getStorage(i);
if(dataUrl == null || dataUrl == ''){
putStorage(i,canvas.toDataURL());
$("#history_"+i).attr("src",canvas.toDataURL());
initHistorty();
return ;
}
}
}
5. 最后,让我们谈谈下载. 许可能会因为没有后台处理而遭受这种头痛. 他们如何下载图片?实际上,在HTML5中,为标签提供了新属性. [下载]如:
<a href="javascript:void(0);" id="history_download_1" download="picture.png">下载</a></td>
默认情况下,浏览器会将其视为下载链接. 下载文件的名称为download.png. 下载的内容与src中的值相对应. 因此,我们只需要动态分配图像的dataUrl.

今天让我们谈谈. 如有任何疑问,请给我留言.
-------------- // 2013-06-258 ---------------
昨天添加了拖放功能. 您可以将其直接从文件夹拖动到绘图板上.
代码页很简单,如下所示:
{3: 2: d: 2: 7: 6: e: d: 8: 1: 7: 8: f: 9: c: 6: 6: 6: f: d: 7: 7: 9: e: a: d: 7: f: c: 7: b: c)
简要说明. 在html5支持的浏览器中,有一个drop回调函数. 获取事件后画图板教程,有一个对象dataTransfer.files. 获取文件信息. 最后,通过FileReader.readAsDataURL函数读取它. ,您可以获得html5支持的图像信息,最后创建一个图像对象并在其中绘制图像.
有兴趣探索或想要源代码的读者可以给我留言,我会定期答复谢谢!
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/ruanjian/article-154960-1.html
棒
南海那边的情况不像某些媒体或人物讲述的那么简单
防腐剂