开发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等 ...
随机推荐
- 通过编写一个简单的日志类库来加深了解C#的文件访问控制
在程序的开发调试过程及发布运行后的状态监控中,日志都有着极其重要的分量,通过在关键逻辑节点将关键数据记录到日志文件当中能帮助我们尽快找到程序问题所在.网上有不少专业成熟的日志组件可用,比如log4ne ...
- 算法和数据结构~各位排序算法的介绍与实现(C#)
排序是指将元素集合按照规定的顺序排列.通常有两种排序方法,升序排列和降序排列.例如,对整数集{5,2,7,1}进行升序排列,结果为{1,2,5,7},对其进行降序排列结果为{7,5,2,1}.总的来说 ...
- Vue混入
Vue 混入 混入 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式.混入对象可以包含任意组件选项.当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项. 数据对象合 ...
- 星星闪烁+多边形移动 canvas
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Django知识总结(二)
拾 ● 模型(M) 一 ● ORM(对象关系映射, Object Relational Mapping) 类----一张表 类的实例对象----表中的一条记录 映射关系 ①python的类名对应的SQ ...
- Oracle 使用序列实现自增列 及重置序列
序列是oracle用来生产一组等间隔的数值.序列是递增,而且连续的.oracle主键没有自增类型,所以一般使用序列产生的值作为某张表的主键,实现主键自增.序列的编号不是在插入记录的时候自动生成的,必须 ...
- SQL-52 获取Employees中的first_name,查询按照first_name最后两个字母,按照升序进行排列
题目描述 获取Employees中的first_name,查询按照first_name最后两个字母,按照升序进行排列CREATE TABLE `employees` (`emp_no` int(11) ...
- webStorm activeCode
https://blog.csdn.net/qq_33183172/article/details/81491183
- day-02
昨天吧 需要写一个财务管理制度 很是伤脑 我发现一旦用脑过度 就会极其想吃零食 所以 昨天吃了些零食 说这个呢 无非是想说 我昨天学习python的时间很少 而且昨晚安装python软件也出现问题了 ...
- vue搭建
~感觉再不学点新技能,马上就要被淘汰了== 1.先安装node,直接点击下一步就OK node官网 https://nodejs.org/en/ 2.安装完成之后,打开命令行工具,快捷键是cmd ...