实现思路:监听鼠标按下、移动、松开事件,将鼠标按下的值赋值给moveTo的x和y值,作为起始位置。在移动事件中,将鼠标距离可视区x和y值赋给lineTo,再将路径闭合。以下是具体的代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
<style>
#canvas{
border:1px solid #000;
}
</style>
</head>
<body>
<canvas id="canvas" width="300" height="300"></canvas>
</body>
</html>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d'); canvas.onmousedown = function(ev){
var x = ev.clientX - this.offsetLeft;
var y = ev.clientY - this.offsetTop;
ctx.beginPath();
ctx.moveTo(x,y);
canvas.onmousemove = function(ev){
var targetX = ev.clientX - this.offsetLeft;
var targetY = ev.clientY - this.offsetTop; ctx.lineWidth = 1;
ctx.lineTo(targetX,targetY);
ctx.stroke();
};
window.onmouseup = function(ev){
canvas.onmousemove = null;
canvas.onmouseup = null;
};
};
</script>

以上的原理就是每次按下鼠标都重新开始一条路径,并将画笔移动到鼠标按下的那个位置,当鼠标移动的时候将线画到鼠标所在的位置,然后闭合,一直重复这一过程,最终就会变成我们所要画的形状,当鼠标松开,清空移动事件和松开事件,直到鼠标再次按下开始新的一轮画图。

注意鼠标松开事件要给window或者document加,不然就会出现下面这个情况

给canvas加鼠标松开事件之所以会出现这种情况,是因为我并不是在canvas中松开鼠标的,因此自然就不会执行canvas中的onmouseup事件了,因而当我们再回到canvas中时它依然还会执行onmousemove事件,而如果给window加,就不会有这种问题,因为整个窗口都属于window范围的,只要你在窗口中松开鼠标就会响应onmouseup事件。

2017.02.24更新

完善canvas功能,新增后退,前进,清除功能

清除功能通过canvas上下文对象的clearRect方法实现。

后退和前进功能,我的想法是每画一次就将整个画布的数据push到一个数组中,按前进和后退时再将对应的数据取出来,这个可以通过getImageData和putImageData方法实现,这两个方法的使用可以到http://www.w3school.com.cn/tags/html_ref_canvas.asp中查看,以下是功能的全部代码

function Graffiti(dom,context){
this.canvas = document.querySelector(dom);
this.context = this.canvas.getContext("2d");
this.imgList = []; this.prevIndex = 0;
this.nextIndex = 0;
this.currentIndex = 0; this.init();
} Graffiti.prototype = {
constructor:this,
init:function(){
var _this = this;
this.move(function(){
_this.pushImg(); _this.upIndex(_this.imgList.length - 1);
});
},
move:function(endCallback){
var _this = this;
var canvas = this.canvas;
var context = this.context; canvas.onmousedown = function(ev){
var x = ev.clientX - this.offsetLeft;
var y = ev.clientY - this.offsetTop;
context.beginPath();
context.moveTo(x,y); canvas.onmousemove = function(ev){
var targetX = ev.clientX - this.offsetLeft;
var targetY = ev.clientY - this.offsetTop; context.lineWidth = 1;
context.lineTo(targetX,targetY);
context.stroke();
};
window.onmouseup = function(ev){
canvas.onmousemove = null;
canvas.onmouseup = null;
endCallback&&ev.target.matches("#canvas")&&endCallback();
};
};
},
back:function(){
this.clear();
this.context.putImageData(this.imgList[this.prevIndex],0,0);
this.upIndex(this.prevIndex);
},
go:function(){
this.clear();
this.context.putImageData(this.imgList[this.nextIndex],0,0);
this.upIndex(this.nextIndex);
},
pushImg:function(){
this.imgList.push(this.context.getImageData(0,0,this.canvas.width,this.canvas.height));
},
clear:function(){
this.context.clearRect(0,0,this.canvas.width,this.canvas.height);
},
upIndex:function(index){
if(index===0){
this.prevIndex = 0;
}else{
this.prevIndex = index - 1;
} if(index===this.imgList.length-1){
this.nextIndex = index;
}else{
this.nextIndex = index + 1;
} this.currentIndex = index;
}
}; var can = new Graffiti("#canvas"); var back = document.getElementById("back");
var go = document.getElementById("go");
var clear = document.getElementById("clear"); back.onclick = can.back.bind(can);
go.onclick = can.go.bind(can);
clear.onclick = can.clear.bind(can);

注意在window.onmouseup的时候有个坑,因为我是在这里面执行储存信息的,因此会出现一个问题,就算我不是在canvas上提起也会相应这个事件,所以在里面我加了一个判断,如果不是canvas就不储存

ev.target.matches("#canvas")

总的来说,这几个功能的难点就在于,你要知道有哪些API,以及如何取储存数据和取数据。

canvas实现涂鸦板的更多相关文章

  1. 重新想象 Windows 8 Store Apps (51) - 输入: 涂鸦板

    [源码下载] 重新想象 Windows 8 Store Apps (51) - 输入: 涂鸦板 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 涂鸦板 通过 Poin ...

  2. Android应用开发实例篇(1)-----简易涂鸦板

    链接地址:http://www.cnblogs.com/lknlfy/archive/2012/03/03/2378328.html 一.概述 这次要做一个简单的涂鸦板应用,以前在Qt上实现过,突然想 ...

  3. HTML5实现涂鸦板

    原文:HTML5实现涂鸦板 最近闲的,看了看html5,强大的绘图功能让我惊奇,于是,写了个小玩意---涂鸦板,能实现功能有:画画,改色,调整画笔大小 html5的绘图可以分为点,线,面,圆,图片等, ...

  4. 背水一战 Windows 10 (60) - 控件(媒体类): Pointer 涂鸦板, InkCanvas 涂鸦板

    [源码下载] 背水一战 Windows 10 (60) - 控件(媒体类): Pointer 涂鸦板, InkCanvas 涂鸦板 作者:webabcd 介绍背水一战 Windows 10 之 控件( ...

  5. iOS_Quartz2D之涂鸦板

    响应者对象:继承了UIResponder的对象 触摸事件:一根或多根手指: 开始触摸: - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent ...

  6. 实现简单的手写涂鸦板(demo源码)

    在一些软件系统中,需要用到手写涂鸦的功能,然后可以将涂鸦的结果保存为图片,并可以将"真迹"通过网络发送给对方.这种手写涂鸦功能是如何实现的了?最直接的,我们可以使用Windows提 ...

  7. 微信小程序-基于canvas画画涂鸦

    代码地址如下:http://www.demodashi.com/demo/14461.html 一.前期准备工作 软件环境:微信开发者工具 官方下载地址:https://mp.weixin.qq.co ...

  8. PPAPI+Skia实现的涂鸦板

    在PPAPI插件中使用Skia画图介绍了怎样在PPAPI中使用Skia,文末说回头要提供一个简单的涂鸦板插件,这次我来兑现承诺了. foruok原创,关注微信订阅号"程序视界"可联 ...

  9. 【Android】自己定义View、画家(画布)Canvas与画笔Paint的应用——绘图、涂鸦板app的实现

    利用一个简单的绘图app来说明安卓的图形处理类与自己定义View的应用. 例如以下图,有一个供用户自己随意绘图.涂鸦的app. 这里不做那么花俏了,仅提供黑白两色.但能够改变笔尖的粗细. 实质上这里的 ...

随机推荐

  1. Django URLs error: view must be a callable or a list/tuple in the case of include()

    Django 1.10 no longer allows you to specify views as a string (e.g. 'myapp.views.home') in your URL ...

  2. axios基础

    一.安装 <script src="https://unpkg.com/axios/dist/axios.min.js"></script> npm ins ...

  3. numpy和pandas和matplotlib用法

    numpy result = [ [0, 10, 20, 30, 40], [10, 23, 33, 43, 53], [20, 83, 23, 55, 33], [30, 93, 44, 22, 5 ...

  4. CSS 基础 例子 水平 & 垂直对齐

    一.元素居中对齐 margin:auto 水平居中对齐一个元素(如 <div>),即div本身在容器中的对齐,用margin:auto,而且,需要设置 width 属性(或者设置 100% ...

  5. SET FOREIGN_KEY_CHECKS=0;在Mysql中取消外键约束

      Mysql中如果表和表之间建立的外键约束,则无法删除表及修改表结构.   解决方法是在Mysql中取消外键约束:  SET FOREIGN_KEY_CHECKS=0;     然后将原来表的数据导 ...

  6. Mirror--不同SQL Server版本使用的默认镜像端点加密算法不同

    在搭建镜像时遇到一个小问题,搭建镜像时报错,排查好半天,对证书/用户/登陆/连接授权等方面都做了逐一排查,未发现异常,最后生成镜像端点创建脚本时,才发现问题原因: 镜像主节点(10.50.4276)的 ...

  7. ASP.NET写的一个博客系统

    由于域名闲置,正好也有服务器空间,短期内开发了一个博客系统. 大家都来谈  http://www.djdlt.com 目前是开放注册,免费发布.(限于空间有限,图片还是尽量少传些) 网站架构: ASP ...

  8. 使用WPF制作视频监控多画面切换

    前言 曾有做过一个产品,有一个功能是视频监控模块,视频监控首先想到的是视频多画面切换功能,由于前端是用WPF开发的,所以当时就做了一个多画面切换组件,效果如下: 功能设计前提: 由于要使用海康大华天地 ...

  9. Python3.5 学习二十二

    回顾: 发送请求时:发送请求头和请求数据 request.META和request.request.body 响应请求时:响应头和响应返回数据 response.HEADER和response.bod ...

  10. [BZOJ2738]矩阵乘法(整体二分+二维树状数组)

    整体二分+二维树状数组. 好题啊!写了一个来小时. 一看这道题,主席树不会搞,只能用离线的做法了. 整体二分真是个好东西,啥都可以搞,尤其是区间第 \(k\) 大这种东西. 我们二分答案,然后用二维树 ...