原文:canvas-画图改进版

前几天在canvas——画板中做了个很简陋的画板,只能画简单的线条,可以选择颜色和线条粗度,今天在此简陋的画板上增加了新的形状,撤销,保存,橡皮擦等功能,虽然功能还是很简单,刚接触canvas,过程中还是遇到了很多困难。

形状包括:铅笔、直线、直角矩形,圆角矩形、原型(利用圆角矩形能够画出很多其他好玩的图形)

提供橡皮擦、撤销、重做、清屏、保存功能

1、html中使用两个canvas,一个相当于蒙版用于缓存

<div id="imgContent"><canvas id="canvas" width="600" height="490">浏览器不支持~</canvas><!--此canvas用于暂存graph,绘制过程中需要清除context,因而需要缓存,否则更换形状时会出现问题 --><canvas id="canvasTemp"width="600" height="490" >&nbsp;</canvas></div>

2、主要鼠标事件:

        $(canvasTemp).unbind();$(canvasTemp).bind('mousedown',down);$(canvasTemp).bind('mousemove',move);$(canvasTemp).bind('mouseup',up);$(canvasTemp).bind('mouseout',out);

3、更换图形时需清空蒙版canvas即canvasTemp的context环境,并且将上次绘制内容添加到canvas中

4、另外需要为各种形状添加鼠标移动时的图标,例如选择circle时鼠标未按下时需要绘制一个小圆

    else if(type === "circle"){clearContext();if(mouseState === true){ //鼠标按下时ctxTemp.beginPath();var radius = Math.sqrt((oldX - newX) *  (oldX - newX)  + (oldY - newY) * (oldY - newY));ctxTemp.arc(oldX,oldY,radius,0,Math.PI * 2,false);                                    ctxTemp.stroke();}else{//鼠标没有按下时出现小圆
                    ctxTemp.beginPath();//ctxTemp.strokeStyle ='#9F35FF';    ctxTemp.arc(newX,newY,10 ,0, Math.PI * 2,false);ctxTemp.stroke();}

5、需要存储绘制的过程,以便撤销和重做

    function saveImageHistory(){cancelTimes = 0;imageHistoryList.push(canvas.toDataURL());if(imageHistoryList.length > 0){document.getElementById("undoImage").src="./images/undo.png";}}

6、由于body背景设置为蓝色,canvas fill 的是白色,因而用橡皮擦时如果直接用clearRect会擦出蓝色背景,因而采用填充白色代替

//ctx.clearRect(newX - lineWeight * 10 ,  newY - lineWeight * 10 , lineWeight * 20 , lineWeight * 20);//重新填充白色背景,否则擦出后是颜色背景ctx.fillStyle = "white";  ctx.fillRect(newX - lineWeight * 10 ,  newY - lineWeight * 10 , lineWeight * 20 , lineWeight * 20);

7.问题总结:

 1)body为蓝色背景,因而想将canvas背景设置为白色,然后尝试将canvas设置背景,这种方式是不行的,只能使用fillRect方式为canvas填充背景,此种方式为橡皮擦的擦除带来了问题,橡皮擦的擦除应该也使用fillRect方式而不能使用clearRect方式

   2)DOM中定义的id会再javasvript中以变量自动定义,因而一定注意js中与id同名的变量或者方法可能不起作用

 3)使用原生js时事件解绑中遇到问题,尝试了removeEventListener和最原始的将绑定事件置为null,但是没起作用,没找到解决方法因而使用了jQuery的unbind,希望有人指导

8.代码:

var canvas,ctx,canvasTemp,ctxTemp,mouseState = false, //初始化鼠标是否按下和坐标点位置, true为按下oldX = 0,oldY = 0,pencilX = 0,pencilY = 0,lineColor = "black",lineWeight = 1,canvasTop,canvasLeft,canvasWidth = 700,canvasHeight = 550,cancelTimes = 0, //撤销次数imageHistoryList = new Array(); //存储图片绘制历史信息
        onLoad(function(){init(); //初始化canvas//颜色和线宽绑定点击事件var colorDiv = document.getElementById("color");var lineDiv = document.getElementById("lineWeight");colorDiv.addEventListener("click", chosen);lineDiv.addEventListener("click", chosen);document.getElementById("pencil").click(); //未选择图形时默认为铅笔document.getElementById("blackBtn").click(); //默认黑色document.getElementById("line1").click(); //默认线宽2px
    });var chosen = function(event){var parentNode = event.target.parentNode;for(var i=0; i<parentNode.childNodes.length; i++){parentNode.childNodes[i].className = "";}event.target.className = "chosen";};var init = function(){//初始化canvascanvas = document.getElementById("canvas");canvas.width = canvasWidth;canvas.height = canvasHeight;//判断是否支持canvasif(!canvas || !canvas.getContext){return false;}ctx = canvas.getContext("2d");//初始化画图区域白色背景ctx.fillStyle = "white";ctx.fillRect(0, 0, 700, 550);//初始化canvasTempcanvasTemp = document.getElementById("canvasTemp");canvasTemp.width = canvasWidth;canvasTemp.height = canvasHeight;ctxTemp = canvasTemp.getContext("2d");canvasTop = canvas.offsetTop,canvasLeft = canvas.offsetLeft;//初始化撤销和重做按钮状态document.getElementById("undoImage").src="./images/undoDis.png";document.getElementById("redoImage").src="./images/redoDis.png";};//绘制picturevar drawPicture = function(type, obj){var down, //鼠标按下事件up, //鼠标弹起事件move, //鼠标移动事件out, //鼠标离开区域chosen, //图形选中clearContext; //清除canvas环境
        down = function(event){mouseState = true;event = event || window.event;oldX =  event.clientX - canvasLeft;pencilX =  event.clientX - canvasLeft;oldY = event.clientY - canvasTop;pencilY = event.clientY - canvasTop;ctxTemp.strokeStyle = lineColor;ctxTemp.lineWidth = lineWeight;ctxTemp.lineCap = "round";clearContext();ctxTemp.moveTo(oldX, oldY);if(type === "rubber"){//ctx.clearRect(oldX-lineWeight*10, oldY-lineWeight*10, lineWeight*20, lineWeight*20);//重新填充白色背景,否则擦出后是颜色背景ctx.fillStyle = "white";ctx.fillRect(oldX-lineWeight*10, oldY-lineWeight*10, lineWeight*20, lineWeight*20);}};up = function(event){//更改鼠标状态mouseState = false;event = event || window.event;//将canvasTemp中graph添加到canvas中var image = new Image();if(type !== "rubber"){image.src = canvasTemp.toDataURL();image.onload = function(){ctx.drawImage(image, 0, 0, image.width, image.height);clearContext();//保存历史记录,撤销时使用
                    saveImageHistory();};}};chosen = function(obj){var shape = document.getElementById("shape");for(var i=0; i<shape.childNodes.length; i++){shape.childNodes[i].className = "";}if(type !== "rubber"){document.getElementById("rubber").className = "";}obj.className = "chosen";};//鼠标按下,拖动画图move = function(event){var newX = event.clientX - canvasLeft;var newY = event.clientY - canvasTop;if(type === "pencil"){if(mouseState === true){ctxTemp.beginPath();ctxTemp.moveTo(pencilX, pencilY);ctxTemp.lineTo(newX, newY);ctxTemp.stroke();pencilX = newX;pencilY = newY;}}else if(type === "rec"){clearContext();if(mouseState === true){ctxTemp.beginPath();ctxTemp.moveTo(oldX, oldY);ctxTemp.lineTo(newX, oldY);ctxTemp.lineTo(newX, newY);ctxTemp.lineTo(oldX, newY);ctxTemp.lineTo(oldX, oldY);ctxTemp.stroke();}else{//鼠标移动时出现矩形
                    ctxTemp.beginPath();    ctxTemp.moveTo(newX - 10 ,  newY - 10 );                        ctxTemp.lineTo(newX + 10  , newY - 10 );ctxTemp.lineTo(newX + 10  , newY + 10 );ctxTemp.lineTo(newX - 10  , newY + 10 );ctxTemp.lineTo(newX- 10  , newY - 10 );    ctxTemp.stroke();}}else if(type === "line"){if(mouseState === true){ctxTemp.beginPath();clearContext();ctxTemp.moveTo(oldX, oldY);ctxTemp.lineTo(newX, newY);ctxTemp.stroke();}}else if(type === "circle"){clearContext();if(mouseState === true){ctxTemp.beginPath();var radius = Math.sqrt((oldX - newX) *  (oldX - newX)  + (oldY - newY) * (oldY - newY));ctxTemp.arc(oldX,oldY,radius,0,Math.PI * 2,false);                                    ctxTemp.stroke();}else{//鼠标没有按下时出现小圆
                    ctxTemp.beginPath();//ctxTemp.strokeStyle ='#9F35FF';    ctxTemp.arc(newX,newY,10 ,0, Math.PI * 2,false);ctxTemp.stroke();}}else if(type === "roundRec"){clearContext();if(mouseState === true){ctxTemp.beginPath();ctxTemp.moveTo(oldX, oldY);ctxTemp.lineTo(newX, oldY);ctxTemp.arcTo(newX+20,oldY, newX+20, oldY+20, 20);ctxTemp.lineTo(newX+20, newY);ctxTemp.arcTo(newX+20,newY+20, newX, newY+20, 20);ctxTemp.lineTo(oldX, newY+20);ctxTemp.arcTo(oldX-20,newY+20, oldX-20, newY, 20);ctxTemp.lineTo(oldX-20, oldY+20);ctxTemp.arcTo(oldX-20,oldY, oldX, oldY, 20);ctxTemp.stroke();}else{//鼠标没有按下时出现小的圆角矩形
                    ctxTemp.beginPath();//ctxTemp.strokeStyle ='#9F35FF';    ctxTemp.moveTo(newX - 10 ,  newY - 10);ctxTemp.lineTo(newX, newY - 10);ctxTemp.arcTo(newX + 10,newY - 10, newX + 10, newY, 10);ctxTemp.lineTo(newX + 10, newY + 10);ctxTemp.arcTo(newX + 10, newY + 20, newX, newY + 20, 10);ctxTemp.lineTo(newX - 10, newY + 20);ctxTemp.arcTo(newX - 20,newY + 20, newX - 20,newY + 10,10);ctxTemp.lineTo(newX - 20,newY);ctxTemp.arcTo(newX - 20,newY - 10, newX - 10,newY - 10, 10);ctxTemp.stroke();}}else if(type === "rubber"){//鼠标没有按下时出现橡皮擦图标
                ctxTemp.beginPath();clearContext();ctxTemp.strokeStyle =  '#000000';                        ctxTemp.moveTo(newX - lineWeight * 10 ,  newY - lineWeight * 10 );                        ctxTemp.lineTo(newX + lineWeight * 10  , newY - lineWeight * 10 );ctxTemp.lineTo(newX + lineWeight * 10  , newY + lineWeight * 10 );ctxTemp.lineTo(newX - lineWeight * 10  , newY + lineWeight * 10 );ctxTemp.lineTo(newX- lineWeight * 10  , newY - lineWeight * 10 );    ctxTemp.stroke();    if(mouseState === true){//ctx.clearRect(newX - lineWeight * 10 ,  newY - lineWeight * 10 , lineWeight * 20 , lineWeight * 20);//重新填充白色背景,否则擦出后是颜色背景ctx.fillStyle = "white";ctx.fillRect(newX - lineWeight * 10 ,  newY - lineWeight * 10 , lineWeight * 20 , lineWeight * 20);}}};out = function(){clearContext();};clearContext = function(){ctxTemp.clearRect(0,0,canvas.width,canvas.height);};//将选中的形状置为选中状态
        chosen(obj);//canvas添加鼠标事件, 鼠标移动、鼠标按下和鼠标弹起/*canvasTemp.addEventListener("mousemove", move);canvasTemp.addEventListener("mousedown", down);canvasTemp.addEventListener("mouseup", up);canvasTemp.addEventListener("mouseout", out);*//** 本来尝试使用原生js来写,但是在上面的事件解绑中遇到问题* 尝试了removeEventListener和最原始的将绑定事件置为null,但是没起作用,没找到解决方法因而使用了jQuery的unbind* */$(canvasTemp).unbind();$(canvasTemp).bind('mousedown',down);$(canvasTemp).bind('mousemove',move);$(canvasTemp).bind('mouseup',up);$(canvasTemp).bind('mouseout',out);};/** 保存picture历史记录*/function saveImageHistory(){cancelTimes = 0;imageHistoryList.push(canvas.toDataURL());if(imageHistoryList.length > 0){document.getElementById("undoImage").src="./images/undo.png";}}var  exportImage = function(event){var imgSrc = canvas.toDataURL("image/png");document.getElementById("image").src = imgSrc;};/** undo 撤销一次*/var undo = function(){cancelTimes++;if(cancelTimes >= imageHistoryList.length+1){cancelTimes--;return;}else if(cancelTimes == imageHistoryList.length){document.getElementById("redoImage").src="./images/redo.png";ctx.clearRect(0, 0, canvasWidth, canvasHeight);document.getElementById("undoImage").src="./images/undoDis.png";}else{document.getElementById("redoImage").src="./images/redo.png";ctx.clearRect(0, 0, canvasWidth, canvasHeight);var image = new Image();image.src = imageHistoryList[imageHistoryList.length-1-cancelTimes];image.onload = function(){ctx.drawImage(image, 0, 0, image.width, image.height);};}};/** redo,重做上一次操作*/var redo = function(){cancelTimes--;if(cancelTimes < 0){cancelTimes++;return;}else{if(cancelTimes == 0){document.getElementById("redoImage").src="./images/redoDis.png";document.getElementById("undoImage").src="./images/undo.png";}ctx.clearRect(0, 0, canvasWidth, canvasHeight);var image = new Image();image.src = imageHistoryList[imageHistoryList.length-1-cancelTimes];image.onload = function(){ctx.drawImage(image, 0, 0, image.width, image.height);};}};/***清屏 */function clearScreen(){ctx.clearRect(0, 0, canvasWidth, canvasHeight);ctxTemp.clearRect(0, 0, canvasWidth, canvasHeight);}/*** 工具函数onLoad,当文档载入完成时调用一个函数*/function onLoad(f){if(onLoad.loaded){window.setTimeout(f,0);}else if(window.addEventListener){window.addEventListener("load",f,false);}else if(window.attachEvent){window.attachEvent("onload",f);}}onLoad.loaded = false;onLoad(function(){onLoad.loaded = true;});

canvas-画图改进版相关推荐

  1. HTML5 canvas画图

    HTML5 canvas画图 HTML5 <canvas> 标签用于绘制图像(通过脚本,通常是 JavaScript). 不过,<canvas> 元素本身并没有绘制能力(它仅仅 ...

  2. html5 canvas 画图移动端出现锯齿毛边的解决方法

    html5 canvas 画图移动端出现锯齿毛边的解决方法 参考文章: (1)html5 canvas 画图移动端出现锯齿毛边的解决方法 (2)https://www.cnblogs.com/dear ...

  3. 小程序---canvas画图,生成分享图片,画图文字换行

    小程序目前只支持转发,不支持分享朋友圈,为了能实现分享,很多线上小程序通过生成分享图片,保存到相册来给用户增加分享的可能. 具体思路及简要代码如下: 一:canvas画图drawCanvas:func ...

  4. 解决canvas画图模糊的问题

    canvas 画图经常发现他是模糊的.解决这个问题主要从两个方面下手. 改变canvas渲染的像素 情况:画1像素的线条看起来模糊不清,好像更宽的样子. 解决方案 var ctx = canvas.g ...

  5. [转]html5 Canvas画图教程(1)—画图的基本常识

    今天看到一个讲Canvas的教程,很通俗移动,所以转载了下. 虽然大家都称Canvas为html5的新标签,看起来好像Canvas属于html语言的新知识,但其实Canvas画图是通过javascri ...

  6. HTML5的Canvas画图模拟太阳系运转

    今天研究的是利用HTML5的Canvas画图来模拟太阳系运转,首先,在这个太阳系里分为画轨道和画星球两个部分, 对于每一个星球我们要知道它的颜色和公转周期,如下图. 采用面向对象编程的思想,代码如下 ...

  7. android 画布控件,Android canvas画图操作之切割画布实现方法(clipRect)

    本文实例讲述了Android canvas画图操作之切割画布实现方法.分享给大家供大家参考,具体如下: android切割画布的历程不算很难,可是理解起来也比较麻烦,这里写一下我的理解 但是不一定正确 ...

  8. canvas 画图移动端出现锯齿毛边的解决方法

    最近项目中用的canvas 越来越多,但是之前都是在canvas 上画图片, 最近这次是做一个折线图,自己画出来以后发现有锯齿,百度一番后找到了解决办法,记录到博客里. 声明一下,我用的是第二种方法, ...

  9. 微信小程序用canvas画图并分享

    最近开始做微信小程序,有这样一个需求: 从列表页进入详情,在每一个详情页面去分享,分享出来的图片是带有当前详情数据的图片 如下图的列表: 分享出来的样子: 解决方案和思路:canvas画图生成图片 上 ...

  10. 今天的码农女孩做了关于svg画图和canvas画图 2022/1/18

    svg和canvas画图 svg和canvas区别: svg:不依赖分辨率,不能嵌入图片和文字,不能通过事件操作,但是可以通过css执行动画,矢量图形,放大缩小不失真,渲染能力强,适合做图标,地图,动 ...

最新文章

  1. tf/idf_Neo4j:带密码的TF / IDF(和变体)
  2. SpringMVC学习笔记整理
  3. 计算机考级各省份难度,2018年全国各省份高考难度排名,基于高分率最新统计数据!...
  4. GDB中创建要素数据集
  5. DPVS_吊打面试官的项目——DPVS
  6. or计算机二级,计算机二级VF历年上机试题or答案
  7. php 可逆加密方法
  8. Eclipse安装中文简体语言包(详细)
  9. 作为一名管理者,如何做好上传下达工作呢?
  10. adams2020安装教程(附详细图文安装教程)
  11. java-遍历Json
  12. python二手房数据分析_使用python抓取分析链家网二手房数据
  13. 线性空间里的线性映射
  14. 2022年全球及中国公共关系(PR)工具行业头部企业市场占有率及排名调研报告
  15. H5页面播放M4a音频文件
  16. 阿里云服务器是干什么用的?
  17. 小程序商城制作一个需要多少钱?一般包括哪些费用?
  18. 直播预售+涨粉神器,创客匠人教你如何快速裂变涨粉
  19. dos命令行-禁用和启用本地连接
  20. 游览器、兼容(五大游览器内核)

热门文章

  1. Apache Tika源码研究(三)
  2. 学习python: 常见面试题总结
  3. Amadeus Pro for Mac(多轨音频编辑器)
  4. Android自定义控件之自定义Toast
  5. 助您写出优雅的Java代码七点建议
  6. 1-Java基础语法-Java初识
  7. 利用卷积自编码器对图片进行降噪
  8. Java是如何读到hbase-site.xml 的内容的
  9. sas软件连接Oracle数据库的办法
  10. SQL Server 数据库做读写分离