开发Canvas 绘画应用(一):搭好框架 中我们已经把基本框架及基础功能实现了,现在要实现本应用的重点:绘画功能。

首先分析一下,我们要实现绘画,需要具备的理论知识如下:

(1)获取触摸点的坐标

类似于获取鼠标在屏幕上的位置,我们现在需要获取手指在绘图板上的位置,这就需要用到触摸事件的跟踪触摸的属性:

  • touches:表示当前跟踪的触摸操作的 Touch 对象的数组。
  • targetTouches:特定于事件目标的 Touch 对象的数组。
  • changedTouches:表示自上次触摸以来发生了什么改变的 Touch 对象的数组。

可以将有几个 Touch 对象看成有几个手指,每个手指的触摸点对应一系列属性。

注意:与 changedTouches 不同,touchestargetTouchestouchend 触发时均没有 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

✎ 参考:

HTML5实例教程——创意画板

使用html5 canvas制作涂鸦画板

JS | 移动端“刮刮卡式”蒙层画板 Canvas

开发Canvas 绘画应用(二):实现绘画的更多相关文章

  1. 开发Canvas 绘画应用(一):搭好框架

    毕业汪今年要毕业啦,毕设做的是三维模型草图检索,年前将算法移植到移动端做了一个小应用(利用nodejs搭的服务),正好也趁此机会可以将前端的 Canvas 好好学一下~~毕设差不多做完了,现将思路和代 ...

  2. 开发Canvas 绘画应用(四):实现拖拽绘画

    在开发Canvas绘画应用(三):实现对照绘画中,我们实现了视图引导的第一部分,这一篇我们来完成第二部分,即将图片直接拖到画布上进行绘画. ✁ 拖放如何实现? [拖放的基本概念]:创建一个绝对定位的元 ...

  3. 开发Canvas 绘画应用(三):实现对照绘画

    需求分析 在我的毕设中,提出了视图引导的概念,由两部分功能组成: (1)可以对照着图片进行绘画,即将图片以半透明的方式呈现在绘图板上,然后用户可以对照着进行绘画: (2)可以直接将简笔画图片直接拖拽到 ...

  4. cWeb开发框架,基于asp.net的cWeb应用开发平台介绍(二)

    cWeb是基于微软的.Net Framework 4框架,数据库是sql server 2008 r2. cWeb开发框架下载,点击这里去下载. cWeb开发框架借鉴三层架构理论分为三层,分别是:cD ...

  5. Senparc.Weixin.MP SDK 微信公众平台开发教程(十二):OAuth2.0说明

    紧接上一篇<Senparc.Weixin.MP SDK 微信公众平台开发教程(十一):高级接口说明>,这里专讲OAuth2.0. 理解OAuth2.0 首先我们通过一张图片来了解一下OAu ...

  6. iOS开发Swift篇—(二)变量和常量

    iOS开发Swift篇—(二)变量和常量 一.语言的性能 (1)根据WWDC的展示 在进行复杂对象排序时Objective-C的性能是Python的2.8倍,Swift的性能是Python的3.9倍 ...

  7. SNF开发平台WinForm之二-开发-单表表单管理页面-SNF快速开发平台3.3-Spring.Net.Framework

    2.1运行效果: 2.2开发实现: 2.2.1 这个开发与第一个开发操作步骤是一致的,不同之处就是在生成完代码之后,留下如下圈红程序,其它删除. 第一个开发地址:开发-单表表格编辑管理页面 http: ...

  8. 使用Jquery+EasyUI 进行框架项目开发案例讲解之二---用户管理源码分享

    使用Jquery+EasyUI 进行框架项目开发案例讲解之二 用户管理源码分享   在上一篇文章<使用Jquery+EasyUI进行框架项目开发案例讲解之一---员工管理源码分享>我们分享 ...

  9. JAVA+PHP+阿里云组件纯手工实现POP、SMTP、IMAP开发邮件服务器(二)

    java开发邮件服务器的接收模块 用java建立socket服务端,监听端口25,实现SMTP协议.即可完成邮件服务器的接收模块. 这里要注意的是,SMTP协议其实可以分为两种.一种是你用手机.PC等 ...

随机推荐

  1. Form表单发送到服务器时的编码方式

    ---恢复内容开始--- 表单中的表单中enctype是设置表单的MIME编码. 所谓MIME编码,是指当服务器传送数据给客户端时,必须指定这个文件是什么类型,才能方便客户端调用相应的应用软件来打开该 ...

  2. Excel中如何截取字符串中指定字符后的部分字符

    1.如何给某列属性为时间整体加一个时间值:      场景一:假如我有一个excel中的某一列如下图所示,如何将该列的时间(用B代替整列)整体加一分钟呢?方法很简单,在空白单元格填写时间格式图中A所示 ...

  3. Webpack学习-Loader

    什么是Loader? 继上两篇文章webpack工作原理介绍(上篇.下篇),我们了解到Loader:模块转换器,也就是将模块的内容按照需求装换成新内容,而且每个Loader的职责都是单一,只会完成一种 ...

  4. 推荐好用的css调试工具,两个

    一:Emmet LiveStyle(http://livestyle.io/) CSS,LESS和SCSS的第一个双向实时编辑工具. 官网说只适用与谷歌跟sublime,可以自行测试   1.subl ...

  5. Python2.7.13下载安装全过程(Windows版)

    前提:    我下载的Python是windows版本的,演示过程是在win10 64位操作系统上安装的. 1.下载 进入官网https://www.python.org/,找到Dowdloads,根 ...

  6. Springmvc对就jdbc封装的操作

    解释: JdbcTemplate 封装常用的JDBC方法 HibernateTemplate  封装常用Hibernate方法 JdbcDaoSupport  JDBC数据访问对象的基类 Hibern ...

  7. linux挂载数据盘步骤

    Linux添加新硬盘自动挂载硬盘的具体步骤 1.插入新硬盘,启动Linux服务器,使用fdisk -l 查看硬盘 #fdisk -l Disk /dev/sdb: 100GB, *********** ...

  8. Android使用Jenkins自动化构建测试打包apk

    Jenkins这东西搭建起来真是一点也不省心啊,看着别人的教程摸着石头过河,配置的东西有点多啊,稍有不慎,就构建不成功啦!即使步骤跟别人一样也会报各种乱七八糟的错误啊哈哈~~这东西只能佛系搭建~~在经 ...

  9. 【算法】单源最短路——Dijkstra

    对于固定起点的最短路算法,我们称之为单源最短路算法.单源最短路算法很多,最常见的就是dijkstra算法. dijkstra主要用的是一种贪心的思想,就是说如果i...s...t...j是最短路,那么 ...

  10. 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 ...