开发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等 ...
随机推荐
- 使用PHP添加圆形头像
首先来看一下PHP怎样生成一个圆形透明的图片 function circle($url){ $w = 430; $h=430; // original size $path = dirname(__F ...
- 开源HUSTOJ
hustoj -- 请一定认真看完本页再动手安装,以免无谓的折腾!====== 根据你选择的发行版不同,从下面三个脚本里选一个来用. <b>不要相信百度来的长篇大论的所谓教程,那些都是好几 ...
- 2072. Kirill the Gardener 3
http://acm.timus.ru/problem.aspx?space=1&num=2072 回忆一下 #include <iostream> #include <st ...
- JavaScript中事件委托(事件代理)详解
在JavaScript的事件中,存在事件委托(事件代理),那么什么是事件委托呢? 事件委托在生活中的例子: 有三个同事预计会在周一收到快递.为签收快递,有两种办法:一是三个人在公司门口等快递:二是委托 ...
- asp解码.net传参
get传参时 asp默认使用gbk解码?了解的朋友指点下,谢谢 .net向asp传参时注意urlencode加密编码使用gb2312 附:任何语言的数据交互都要确保接收双方的编码一致
- mybatis Interceptor拦截器代码详解
mybatis官方定义:MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis ...
- 代码规范mark一下
转自于:https://github.com/zh-google-styleguide/zh-google-styleguide/blob/master/google-python-styleguid ...
- Java利用cors实现跨域请求
由于ajax本身实际上是通过XMLHttpRequest对象来进行数据的交互,而浏览器出于安全考虑,不允许js代码进行跨域操作,所以会警告 网站开发,在某些情况下需要用到跨域. 什么是跨域? 跨域,指 ...
- [SCOI2003]字符串折叠
一道蛮好玩的区间DP...其实只要做好check...然后统计答案就好了...QAQ... 呆码: #include<iostream> #include<cstdio> #i ...
- [转]sqlldr 导入乱码,Oracle客户端字符集问题
1,查Oracle数据库创建时候的字符集:oracle服务器端执行 SQL> select name, value$ from sys.props$ where name like 'NLS%' ...