基于HTML5 Canvas和jQuery 的绘图工具的实现
简单介绍
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 的绘图工具的实现的更多相关文章
- 18个基于 HTML5 Canvas 开发的图表库
如今,HTML5 可谓如众星捧月一般,受到许多业内巨头的青睐.很多Web开发者也尝试着用 HTML 5 来制作各种各样的富 Web 应用.HTML 5 规范引进了很多新特性,其中之一就是 Canvas ...
- 一款基于HTML5 Canvas的画板涂鸦动画
今天给各网友分享一款基于HTML5 Canvas的画板涂鸦动画.记得之前我们分享过一款HTML5 Canvas画板工具,可以切换不同的笔刷,功能十分强大.本文今天要再来分享一款基于HTML5 Canv ...
- 基于html5 canvas和js实现的水果忍者网页版
今天爱编程小编给大家分享一款基于html5 canvas和js实现的水果忍者网页版. <水果忍者>是一款非常受喜欢的手机游戏,刚看到新闻说<水果忍者>四周年新版要上线了.网页版 ...
- 基于HTML5 Canvas的线性区域图表教程
之前我们看到过很多用jQuery实现的网页图表,有些还是比较实用的.今天我们来介绍一款基于HTML5 Canvas的线性区域图表应用,这个图表应用允许你使用多组数据来同时展示,并且将数据结果以线性图的 ...
- 基于html5 Canvas图表库 : ECharts
ECharts开源来自百度商业前端数据可视化团队,基于html5 Canvas,是一个纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表.创新的拖拽重计算.数据视图.值 ...
- 基于html5 canvas 的客户端异步上传图片的插件,支持客户端压缩图片尺寸
/** * Created by xx on 15-05-28. * 基于html5 canvas 的客户端异步上传画片的插件 * 在实际应用中,常常要用于上传图片的功能.在现在越来越多的手机weba ...
- JavaScript 基于HTML5 canvas 获取文本占用的像素宽度
基于HTML5 canvas 获取文本占用的像素宽度 by:授客 QQ:1033553122 直接上代码 // 获取单行文本的像素宽度 getTextPixelWith(text, fontS ...
- 基于HTML5 Canvas实现的图片马赛克模糊特效
效果请点击下面网址: http://hovertree.com/texiao/html5/1.htm 一.开门见山受美国肖像画家Chuck Close的启发,此脚本通过使用HTML5 canvas元素 ...
- 基于HTML5 Canvas的网页画板实现教程
HTML5的功能非常强大,尤其是Canvas的应用更加广泛,Canvas画布上面不仅可以绘制任意的图形,而且可以实现多种多样的动画,甚至是一些交互式的应用,比如网页网版.这次我们要来看的就是一款基于H ...
随机推荐
- 【LeetCode】Permutations(全排列)
这道题是LeetCode里的第46道题. 题目要求: 给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3 ...
- 划分树C++版百度百科模板
此代码同hdu2665改编#include <iostream> #include <cstdio> #include<cstring> #include < ...
- Python logging 学习
基本用法: import logging #初始化logger 对象 logger = logging.getLogger("main") #设置logger对象基础级别,后面的h ...
- [luoguP1131] [ZJOI2007]时态同步(贪心)
传送门 显然是一棵树. 又显然一段一段地增加比较优. 我们可以dfs,并且尽量把每一个节点所有子树中所有节点的时间增加到一样. #include <vector> #include < ...
- 洛谷P2365 任务安排 [解法一]
题目描述 N个任务排成一个序列在一台机器上等待完成(顺序不得改变),这N个任务被分成若干批,每批包含相邻的若干任务.从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间是Ti.在每批任务开始 ...
- Codevs 5564 陶陶摘苹果2
5564 陶陶摘苹果2 时间限制: 1 s 空间限制: 16000 KB 题目等级 : 白银 Silver 题目描述 Description 陶陶已经够高摘到所有苹果了,但是他力量有限,最大承受质量为 ...
- C++ assert 的一点说明
断言(ASSERT)的用法 转载自http://www.cnblogs.com/moondark/archive/2012/03/12/2392315.html 我一直以为assert仅仅是个报错函数 ...
- laravel 操作数据库
建立student控制器,控制器代码 namespace App\Http\Controllers; use Illuminate\Support\Facades\DB; class StudentC ...
- MongoDB GridFS(命令行+php操作)
一.GridFS是什么 & 为什么需要它 我们知道目前MongoDB的BSON文件最大只能是16M,也就是说单个文档最多只能存储16M的数据,那么如果需要MongoDB存储超过16M的大文件该 ...
- hdu 2686 费用流 / 双线程DP
题意:给一个方阵,求从左上角出到右下角(并返回到起点),经过每个点一次不重复,求最大获益(走到某处获得改点数值),下来时每次只能向右或向下,反之向上或向左. 俩种解法: 1 费用流法:思路转化:从左 ...