简单介绍

HTML5 提供了强大的Canvas元素。使用Canvas并结合Javascript 能够实现一些很强大的功能。本文就介绍一下基于HTML5 Canvas 的绘图工具的实现。废话少说,先看成品:

该应用是遵循所见即所得(WYSIWYG, What you see is what you get)原则设计的,它具有下面功能:

1. 能够绘制自由曲线、直线、矩形框和文字。

2. 能够依据须要定义线段和矩形框的颜色和宽度;

3. 你能够须要字体的大小、颜色、字体;

4. 支持undo、redo操作;

5. 支持橡皮擦功能。

6. 支持本地图片保存功能。

源代码下载       1. 读者能够去我的GitHub jPainter项目下下载,

2. 或者直接使用git 工具:https://github.com/LuanLouis/jPainter.git

       3. 或者 通过
http://download.csdn.net/detail/u010349169/7748093 下载

开发心得分享

上述功能的实现,难点倒不是非常多,值得一提的有下面几点:

1.  鼠标按下并移动 事件应该如何实现 

2. 如何实现所见即所得  的设计

3. undo redo 的实现原理

4. 画板信息另存为图片

鼠标按下并移动 事件应该如何实现

        假设我们在画板想画自由曲线,我们须要捕获鼠标按下并拖动的过程中 拖动的轨迹。

那么如何捕获这种事件呢?
熟悉javascript 事件的读者应该知道,鼠标移动事件的句柄是 onmousemove。有的读者可能觉得。能够直接为onmousemove 绑定事件处理函数。从event事件对象的button属性来推断是鼠标的哪一个键点击不即可了吗?代码例如以下:

$(function() {
$(document).mousemove(function(e){
console.log(e.button+" "+e.which);
})
});

而实际上,上述的代码执行时,当我们在页面上不管是点击鼠标的哪个键。都是输出例如以下的信息:

从输出的结果能够看出。结果和我们预期的并不一样。这是为什么呢?

原因是:  javascript的事件机制是这种。当用户触发了事件之后,javascript宿主-浏览器会将事件封装成event对象,然后依据事件的类型对event属性进行赋值。然后依据event的类型,依据什么类型的事件来调用对应的事件处理函数。举例来说。假设我们在界面上按下了鼠标的右键,那么。浏览器会首先创建一个event对象,然后对event属性赋值,而对应的button会被置为2、which为3表示右键被按下;然后javascript
会将此event对象作为參数传递给相应的事件处理函数,运行事件处理函数。

也就是说。event的button属性(以及jquery封装后的which属性)仅仅有当 click、mousedown,mousup 相应的事件处理函数才有意义。

那么。我们如何才干推断当鼠标移动时,鼠标键是否被按下呢?

解决方法:鼠标按下和松开是个过程。我们能够设置一个 flag。在鼠标按下的时候置为true,鼠标松开的时候置为false。然后在鼠标移动的事件处理函数中推断这个flag。进而能够区分鼠标是否被按下。

如果我们须要在<body> 元素上捕获 对应的鼠标事件,下面是使用jquery 进行事件处理函数的绑定:

    //onmousemove 事件
$("body").mousemove(function(e){
if(flag) {
// 鼠标被按下
} }) //onmousedown事件
$("body").onmousedown(function(e){
flag = true; // 事件处理
}) //onmouseup事件
$("body").mouseup(function(e){
flag = false; // 事件处理
})

当然,假设读者有其它的实现方案。还请指教。共同学习!

如何实现所见即所得的设计

使用Canvas画图时。其画图是通过javascript控制的,比方,我想绘制一个矩形,应该使用类似下面的代码:

var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
cxt.fillStyle="#FF0000";
cxt.fillRect(0,0,150,75);

可是对于对于可交互的用户界面,假设想创建一个矩形,应该是通过鼠标在画板上拖动,然后能够随时看到我将要画的矩形的大小、边框、颜色等等。如何让用户能够看到动态的效果呢? 当然了,使用canvas 肯定是实现不了的。这里我想到了一个方法。就是使用<DIV> 元素模拟我们须要绘制的矩形,当用户在拖动鼠标的过程中,使用DIV 显示矩形的信息,一旦用户松开鼠标,那么。将此DIV隐藏。依据鼠标的轨迹以及矩形配置,使用javascript绘制在相应的形状。

类似地,绘画直线和加入文字也是通过HTML伪装的逻辑:

绘画直线时,用户在画板上拖动并按下鼠标时,动态地显示出一条使用HTML伪装的直线,能够随着用户鼠标的移动而变化。当用户松开鼠标时。相应模拟直线的HTML元素隐藏,调用javavscript绘制真正的直线。

加入文字时。这里使用的<textarea>元素 进行模拟文本输入框。当用户在画板上加入文字时,能够拖动鼠标设置输入框的大小,然后输入文字,一旦输入框失去焦点,则隐藏此<textarea> 元素,然后使用javascript绘制对应的文字

undo redo 的实现原理

在介绍 undo  redo 的实现之前。要先讲一下canvas的toDataURL()方法。

toDataURL()方法将canvas上所绘制的内容转换成格式png格式图片,并将图片通过base64编码。转换成形如如:data:image/png;base64,iVBORw0KGg....... 的字符串,用来表示图片数据。

(PS:对此比較困惑的读者能够自行查找关于HTML
图片 BASE64 存储
的相关问题,这个知识点还是非常重要的)

undo redo 的原理实际上非常easy。就是当每运行一次绘画,则将画板的内容转换成base64编码的字符串,存到缓存数组中去,然后在须要undo 的时候,将画板清空。再将缓存数组中的最后一次编辑的图片绘制到画板上就可以。相关的实现细节例如以下代码所看到的:

			      //undo redo
var history =new Array();
var cStep = -1; /**
* put current canvas to cache
*/
function historyPush()
{
cStep++;
if (cStep < history.length)
{
history.length = cStep;
} history.push($("#myCanvas").get(0).toDataURL());
}
/**
* function: undo
*/
function undo()
{
if (cStep >= 0)
{
cStep--;
var tempImage = new Image();
tempImage.src = history[cStep];
tempImage.onload = function () { ctx.drawImage(tempImage, 0, 0);};
} } /**
* function: redo
*/
function redo()
{
if (cStep <history.length-1)
{
clearCanvas();
cStep++;
var tempImage = new Image();
tempImage.src = history[cStep];
tempImage.onload = function () { ctx.drawImage(tempImage, 0, 0); };
}
}

画板信息存为图片

代码例如以下:

				  /**
* save canvas content as image
*/
function saveItAsImage()
{
var image = $("#myCanvas").get(0).toDataURL("image/png").replace("image/png", "image/octet-stream");
//locally save
window.location.href=image;
}

源代码下载      
1. 读者能够去我的GitHub jPainter项目下下载,

2. 或者直接使用git 工具:https://github.com/LuanLouis/jPainter.git

       3. 或者 通过 http://download.csdn.net/detail/u010349169/7748093 下载

-----------------------------------------------------------------------------------------------------------------------------------------

本文源自  http://blog.csdn.net/luanlouis/。如需转载。请注明出处,谢谢!

基于HTML5 Canvas和jQuery 的绘图工具的实现的更多相关文章

  1. 18个基于 HTML5 Canvas 开发的图表库

    如今,HTML5 可谓如众星捧月一般,受到许多业内巨头的青睐.很多Web开发者也尝试着用 HTML 5 来制作各种各样的富 Web 应用.HTML 5 规范引进了很多新特性,其中之一就是 Canvas ...

  2. 一款基于HTML5 Canvas的画板涂鸦动画

    今天给各网友分享一款基于HTML5 Canvas的画板涂鸦动画.记得之前我们分享过一款HTML5 Canvas画板工具,可以切换不同的笔刷,功能十分强大.本文今天要再来分享一款基于HTML5 Canv ...

  3. 基于html5 canvas和js实现的水果忍者网页版

    今天爱编程小编给大家分享一款基于html5 canvas和js实现的水果忍者网页版. <水果忍者>是一款非常受喜欢的手机游戏,刚看到新闻说<水果忍者>四周年新版要上线了.网页版 ...

  4. 基于HTML5 Canvas的线性区域图表教程

    之前我们看到过很多用jQuery实现的网页图表,有些还是比较实用的.今天我们来介绍一款基于HTML5 Canvas的线性区域图表应用,这个图表应用允许你使用多组数据来同时展示,并且将数据结果以线性图的 ...

  5. 基于html5 Canvas图表库 : ECharts

    ECharts开源来自百度商业前端数据可视化团队,基于html5 Canvas,是一个纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表.创新的拖拽重计算.数据视图.值 ...

  6. 基于html5 canvas 的客户端异步上传图片的插件,支持客户端压缩图片尺寸

    /** * Created by xx on 15-05-28. * 基于html5 canvas 的客户端异步上传画片的插件 * 在实际应用中,常常要用于上传图片的功能.在现在越来越多的手机weba ...

  7. JavaScript 基于HTML5 canvas 获取文本占用的像素宽度

    基于HTML5 canvas 获取文本占用的像素宽度   by:授客 QQ:1033553122 直接上代码   // 获取单行文本的像素宽度 getTextPixelWith(text, fontS ...

  8. 基于HTML5 Canvas实现的图片马赛克模糊特效

    效果请点击下面网址: http://hovertree.com/texiao/html5/1.htm 一.开门见山受美国肖像画家Chuck Close的启发,此脚本通过使用HTML5 canvas元素 ...

  9. 基于HTML5 Canvas的网页画板实现教程

    HTML5的功能非常强大,尤其是Canvas的应用更加广泛,Canvas画布上面不仅可以绘制任意的图形,而且可以实现多种多样的动画,甚至是一些交互式的应用,比如网页网版.这次我们要来看的就是一款基于H ...

随机推荐

  1. iOS第三方-百度地图地图SDK(一)

    前言 最近项目忙完了准备把百度地图的方法都熟悉一遍,基于百度地图2.10.0,写demo的同时也写下博客来记录下 模拟器设置 我直接就复制我以前写过的一篇的图了,懒得截图... 获取百度地图KEY 让 ...

  2. 【Luogu】P3116会议时间(拓扑排序,DP)

    题目链接 本题使用拓扑排序来规划DP顺序.设s[i][j]表示i步是否能走到j这个点,e[i][j]表示i步是否能走到j这个点——用第二条路径.因为要满足无后效性和正确性,只有第i个点已经全部更新完毕 ...

  3. 【Luogu】P1516青蛙的约会(线性同余方程,扩展欧几里得)

    题目链接 定理:对于方程\(ax+by=c\),等价于\(a*x=c(mod b)\),有整数解的充分必要条件是c是gcd(a,b)的整数倍. ——信息学奥赛之数学一本通 避免侵权.哈哈. 两只青蛙跳 ...

  4. Ubuntu16.04 on ThinkPad E455 不能识别耳机 的解决方法

    去年 (2016) 2月份在ThinkPad E455 上安装了Ubuntu 14.04 LTS (dual boot with Windows 10, upgraded to Ubuntu 16.0 ...

  5. BZOJ 4259 残缺的字符串 ——FFT

    [题目分析] 同bzoj4503. 只是精度比较卡,需要试一试才能行O(∩_∩)O 用过long double,也加过0.4.最后发现判断的时候改成0.4就可以了 [代码] #include < ...

  6. hdu 1166 树状数组(线段树)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  7. 洛谷 P1522 牛的旅行

    题目描述 农民 John的农场里有很多牧区.有的路径连接一些特定的牧区.一片所有连通的牧区称为一个牧场.但是就目前而言,你能看到至少有两个牧区通过任何路径都不连通.这样,Farmer John就有多个 ...

  8. net3:Button的CommandName使用,AdRotator,BulletedList的使用

    原文发布时间为:2008-07-29 -- 来源于本人的百度文章 [由搬家工具导入] using System;using System.Data;using System.Configuration ...

  9. MongoDB_单机版环境搭建

    linux上安装MogoDB http://www.runoob.com/mongodb/mongodb-linux-install.html 在https://www.mongodb.com/dow ...

  10. hdu 1827 有向图缩点看度数

    题意:给一个有向图,选最少的点(同时最小价值),从这些点出发可以遍历所有. 思路:先有向图缩点,成有向树,找入度为0的点即可. 下面给出有向图缩点方法: 用一个数组SCC记录即可,重新编号,1.... ...