开发Canvas 绘画应用(二):实现绘画
开发Canvas 绘画应用(一):搭好框架 中我们已经把基本框架及基础功能实现了,现在要实现本应用的重点:绘画功能。
首先分析一下,我们要实现绘画,需要具备的理论知识如下:
(1)获取触摸点的坐标
类似于获取鼠标在屏幕上的位置,我们现在需要获取手指在绘图板上的位置,这就需要用到触摸事件的跟踪触摸的属性:
touches:表示当前跟踪的触摸操作的 Touch 对象的数组。targetTouches:特定于事件目标的 Touch 对象的数组。changedTouches:表示自上次触摸以来发生了什么改变的 Touch 对象的数组。
可以将有几个 Touch 对象看成有几个手指,每个手指的触摸点对应一系列属性。
注意:与
changedTouches不同,touches和targetTouches在touchend触发时均没有 Touch 数组,length为0,即触摸点数为0。可以在浏览器上打印输出进行对比。
其中,每个 Touch 对象包含下列属性:
- clientX:触摸目标在视口中的 x 坐标。
- clientY:触摸目标在视口中的 y 坐标。
- identifier:标识触摸的唯一 ID。
- pageX:触摸目标在页面中的 x 坐标。
- pageY:触摸目标在页面中的 y 坐标。
- screenX:触摸目标在屏幕中的 x 坐标。
- screenY:触摸目标在屏幕中的 y 坐标。
- target:触摸的 DOM 节点目标。
(2)Canvas 绘制路径的方法
beginPath():绘制路径前必须调用,表示要开始绘制新路径。lineTo(x,y):从上一点开始绘制一条直线。moveTo(x,y):从绘图游标开始移动到(x,y),不画线。closePath():创建路径之后,绘制一条连接到起点的线条。fill():对路径进行填充。stroke():对路径进行描边。clip():在路径上创建一个剪切区域。
绘画实现
OK,理论知识已经具备了,接下去就要开始搬砖了。
① 初始化数据
initData() {
this.lastX = 0;
this.lastY = 0;
this.isPaint = false;
return this;
}
② 实现绘画函数
/**
* 绘画函数
* @param {[type]} x 触摸点x坐标
* @param {[type]} y 触摸点y坐标
* @return {[type]} 将当前坐标赋给上一个点坐标
*/
draw(x, y) {
if (this.isPaint) {
this.ctx.beginPath(); // 开始绘制路径,必须调用
this.ctx.moveTo(this.lastX, this.lastY); // 将绘图游标移动到到上一点
this.ctx.lineTo(x, y); // 从上一点开始绘制一条到(x,y)的直线
this.ctx.stroke(); // 描边路径
}
// 上面必须判断 this.isPaint
// 当 'touchstart' 时,先移动到触摸点
this.lastX = x;
this.lastY = y;
}
③ 完善事件处理函数(★重点)
// 触摸事件处理函数
touchF(e) {
e.preventDefault(); // 阻止浏览器默认行为
const touches = e.changedTouches; // 获取 Touch 对象list
const point = touches[0]; // 获取第一个 Touch 对象
// 获取元素宽、高及距窗口上下左右距离
const rect = this.cva.getBoundingClientRect();
// 相当于const rect = $('.painter').offset();
// 相当于const rect = { left: this.cva.offsetLeft, top: this.cva.offsetTop }
switch (e.type) {
case 'touchstart':
// 获取触摸点的x,y坐标,传入draw函数
this.draw(point.clientX - rect.left, point.clientY - rect.top);
this.isPaint = true;
break;
case 'touchmove':
this.draw(point.clientX - rect.left, point.clientY - rect.top);
break;
case 'touchend':
this.isPaint = false;
break;
default:
this.isPaint = false;
break;
}
}
这里需要获取 canvas 在视口中距离左边及顶部的距离,有3种方式:
(1) this.cva.getBoundingClientRect():返回一个对象,包含元素的宽、高及距窗口上下左右距离;
console.log(this.cva.getBoundingClientRect());

(2) 采用 jQuery 方法 $('.painter').offset():同样返回一个对象,但只包含left值和top值;
console.log($('.painter').offset());

(3) 采用js原生方法获取坐标
console.log(this.cva.offsetWidth); // 800
console.log(this.cva.offsetHeight); // 600
console.log(this.cva.offsetLeft); // 90
console.log(this.cva.offsetTop); // 137
注意:原生 js 只有上述4个方法,没有 offsetRight 和 offsetBottom。
大功告成!至此,已经可以在我们的画布上进行类似于铅笔的绘画了~~当然,这是绘图板最最基本的功能,接下去要实现更多的功能,还会用到更多的 Canvas API,需要进行迭代开发啦,有木有很兴奋,嘿嘿;-)

要知下回如何,请继续阅读 开发Canvas绘画应用(三)-对照绘画
✈ Github:paintApp
✎ 参考:
开发Canvas 绘画应用(二):实现绘画的更多相关文章
- 开发Canvas 绘画应用(一):搭好框架
毕业汪今年要毕业啦,毕设做的是三维模型草图检索,年前将算法移植到移动端做了一个小应用(利用nodejs搭的服务),正好也趁此机会可以将前端的 Canvas 好好学一下~~毕设差不多做完了,现将思路和代 ...
- 开发Canvas 绘画应用(四):实现拖拽绘画
在开发Canvas绘画应用(三):实现对照绘画中,我们实现了视图引导的第一部分,这一篇我们来完成第二部分,即将图片直接拖到画布上进行绘画. ✁ 拖放如何实现? [拖放的基本概念]:创建一个绝对定位的元 ...
- 开发Canvas 绘画应用(三):实现对照绘画
需求分析 在我的毕设中,提出了视图引导的概念,由两部分功能组成: (1)可以对照着图片进行绘画,即将图片以半透明的方式呈现在绘图板上,然后用户可以对照着进行绘画: (2)可以直接将简笔画图片直接拖拽到 ...
- cWeb开发框架,基于asp.net的cWeb应用开发平台介绍(二)
cWeb是基于微软的.Net Framework 4框架,数据库是sql server 2008 r2. cWeb开发框架下载,点击这里去下载. cWeb开发框架借鉴三层架构理论分为三层,分别是:cD ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十二):OAuth2.0说明
紧接上一篇<Senparc.Weixin.MP SDK 微信公众平台开发教程(十一):高级接口说明>,这里专讲OAuth2.0. 理解OAuth2.0 首先我们通过一张图片来了解一下OAu ...
- iOS开发Swift篇—(二)变量和常量
iOS开发Swift篇—(二)变量和常量 一.语言的性能 (1)根据WWDC的展示 在进行复杂对象排序时Objective-C的性能是Python的2.8倍,Swift的性能是Python的3.9倍 ...
- SNF开发平台WinForm之二-开发-单表表单管理页面-SNF快速开发平台3.3-Spring.Net.Framework
2.1运行效果: 2.2开发实现: 2.2.1 这个开发与第一个开发操作步骤是一致的,不同之处就是在生成完代码之后,留下如下圈红程序,其它删除. 第一个开发地址:开发-单表表格编辑管理页面 http: ...
- 使用Jquery+EasyUI 进行框架项目开发案例讲解之二---用户管理源码分享
使用Jquery+EasyUI 进行框架项目开发案例讲解之二 用户管理源码分享 在上一篇文章<使用Jquery+EasyUI进行框架项目开发案例讲解之一---员工管理源码分享>我们分享 ...
- JAVA+PHP+阿里云组件纯手工实现POP、SMTP、IMAP开发邮件服务器(二)
java开发邮件服务器的接收模块 用java建立socket服务端,监听端口25,实现SMTP协议.即可完成邮件服务器的接收模块. 这里要注意的是,SMTP协议其实可以分为两种.一种是你用手机.PC等 ...
随机推荐
- Form表单发送到服务器时的编码方式
---恢复内容开始--- 表单中的表单中enctype是设置表单的MIME编码. 所谓MIME编码,是指当服务器传送数据给客户端时,必须指定这个文件是什么类型,才能方便客户端调用相应的应用软件来打开该 ...
- Excel中如何截取字符串中指定字符后的部分字符
1.如何给某列属性为时间整体加一个时间值: 场景一:假如我有一个excel中的某一列如下图所示,如何将该列的时间(用B代替整列)整体加一分钟呢?方法很简单,在空白单元格填写时间格式图中A所示 ...
- Webpack学习-Loader
什么是Loader? 继上两篇文章webpack工作原理介绍(上篇.下篇),我们了解到Loader:模块转换器,也就是将模块的内容按照需求装换成新内容,而且每个Loader的职责都是单一,只会完成一种 ...
- 推荐好用的css调试工具,两个
一:Emmet LiveStyle(http://livestyle.io/) CSS,LESS和SCSS的第一个双向实时编辑工具. 官网说只适用与谷歌跟sublime,可以自行测试 1.subl ...
- Python2.7.13下载安装全过程(Windows版)
前提: 我下载的Python是windows版本的,演示过程是在win10 64位操作系统上安装的. 1.下载 进入官网https://www.python.org/,找到Dowdloads,根 ...
- Springmvc对就jdbc封装的操作
解释: JdbcTemplate 封装常用的JDBC方法 HibernateTemplate 封装常用Hibernate方法 JdbcDaoSupport JDBC数据访问对象的基类 Hibern ...
- linux挂载数据盘步骤
Linux添加新硬盘自动挂载硬盘的具体步骤 1.插入新硬盘,启动Linux服务器,使用fdisk -l 查看硬盘 #fdisk -l Disk /dev/sdb: 100GB, *********** ...
- Android使用Jenkins自动化构建测试打包apk
Jenkins这东西搭建起来真是一点也不省心啊,看着别人的教程摸着石头过河,配置的东西有点多啊,稍有不慎,就构建不成功啦!即使步骤跟别人一样也会报各种乱七八糟的错误啊哈哈~~这东西只能佛系搭建~~在经 ...
- 【算法】单源最短路——Dijkstra
对于固定起点的最短路算法,我们称之为单源最短路算法.单源最短路算法很多,最常见的就是dijkstra算法. dijkstra主要用的是一种贪心的思想,就是说如果i...s...t...j是最短路,那么 ...
- UnboundLocalError: local variable 'f' referenced before assignment
参考方案链接: 1.http://blog.chinaunix.net/uid-631981-id-3766212.html 2.http://blog.sina.com.cn/s/blog_4b9e ...