开发Canvas 绘画应用(三):实现对照绘画
需求分析
在我的毕设中,提出了视图引导的概念,由两部分功能组成:
(1)可以对照着图片进行绘画,即将图片以半透明的方式呈现在绘图板上,然后用户可以对照着进行绘画;
(2)可以直接将简笔画图片直接拖拽到画布上进行检索。
那么,在这里,我们先实现第一种功能——图片对照绘画。最终想要的实现效果是:当点击图片时,图片边框会呈现蓝色,表示选中状态,同时会在画布上以半透明方式呈现该图片,再点击图片,边框和底板图片都消失,即可以切换显示状态。
a. 点击前:
b. 点击后:
c. 取消点击:
实现思路
我们来分析一下,这种半透明底板方式是如何实现的?
1)首先,需要利用分层来实现图片参照效果:即设置两个 Canvas,上层的 Canvas 仍旧用来绘画,而下层的 Canvas 则作为底板显示图片,这里需要用到 canvas 的绘制图像 API——drawImage()
。
context.drawImage(iamge, srcX, srcY, srcWidth, srcHeight, desX, desY, desWidth, desHeight)
2)其次,为了出现半透明的效果,需要设置上层 canvas 的透明度,这里需要用到 canvas 的图片合成,即通过设置 globalAlpha
属性指定所有绘制的透明度。
两个应用到2D上下文中所有绘制操作的属性:
globalAlpha
:属于[0, 1],用于指定所有绘制的透明度。globalCompositionOperation
:表示后绘制的图形怎样与先绘制的图形结合,其属性值是字符串。
代码实现
该阶段我们需要添加2个模块:一个是视图模块(viewer.js),用于放置我们的参照图片(蜜蜂线画图图片);另一个是底板模块(basePlate.js),用于显示底板。
另外,此处增加的两个 Canvas 其实前期的画板设置是相同的,因此我们将设置单独拎到一个 cvaConfig.js
文件中,以便代码重用,然后 painter.js
和 basePlate.js
只要继承 cvaConfig.js
就行了。
☞ index.html
<img src="asset/img/bee.png" class="view">
<canvas class="painter" id="js-painter"></canvas>
<canvas class="baseplate" id="js-baseplate"></canvas>
☞ cvaConfig.js
export default class CvaConfig {
constructor() {
this.config = {
cvaW: 600,
cvaH: 500,
cvaBg: '#fff',
lineWidth: 2,
lineJoin: 'round',
strokeStyle: 'red'
};
}
// 画板宽高设置
// 注意此处不能在 css 中设置,像素会失真,会导致不能获取正确的坐标
setCvaWH() {
this.cva.setAttribute('width', this.config.cvaW);
this.cva.setAttribute('height', this.config.cvaH);
return this;
}
// 画板背景设置
setCvaBg() {
this.ctx.fillStyle = this.config.cvaBg;
this.ctx.fillRect(0, 0, this.config.cvaW, this.config.cvaH);
return this;
}
// 画笔设置
setPen() {
this.ctx.lineWidth = this.config.lineWidth;
this.ctx.lineJoin = this.config.lineJoin;
this.ctx.strokeStyle = this.config.strokeStyle;
return this;
}
}
☞ viewer.js
export default class Viewer {
constructor(options) {
this.options = options;
this.init();
}
initSelectors() {
this.view = $('.view');
return this;
}
initEvents() {
this.view.on('touchstart', $.proxy(this.touchF, this));
this.view.on('touchmove', $.proxy(this.touchF, this));
this.view.on('touchend', $.proxy(this.touchF, this));
}
touchF(e) {
e.preventDefault(); // 阻止浏览器默认行为
switch (e.type) {
case 'touchstart':
break;
case 'touchmove':
break;
case 'touchend':
this.setStyle($(e.target)); // 切换视图显示状态
this.setBasePlate(e.target); // 切换底板显示状态
break;
}
}
/**
* 切换视图显示状态,表示是否点击
* @param {[type]} $el 点击的jQuery目标对象
*/
setStyle($el) {
$el.toggleClass('blue-border');
}
/**
* 通过点击图视图调用basePlate的接口切换底板显示状态
* @param {[type]} el 点击的原生js目标对象
*/
setBasePlate(el) {
// 视图选中时传入图片
if ($(el).hasClass('blue-border')) {
this.options.setBasePlate(el);
} else { // 未选中不传图片
this.options.setBasePlate();
}
}
init() {
this.initSelectors().initEvents();
}
}
☞ basePlate.js
basePlate 中功能性的只有一个用来设置底板的函数,通过在点击 viewer 时进行调用:
import CvaConfig from './cvaConfig.js';
export default class basePlate extends CvaConfig {
constructor() {
super();
this.init();
}
initSelectors() {
this.cva = document.getElementById('js-baseplate');
this.ctx = this.cva.getContext('2d');
return this;
}
// 设置底板
setBasePlate(image) {
if (image) { // 如果有图片,在底板上显示图片
this.ctx.drawImage(image, 0, 0, this.config.cvaW, this.config.cvaH);
} else { // 设置空底板
this.setCvaBg();
}
}
init() {
this.initSelectors();
this.setCvaWH().setCvaBg();
}
}
☞ painter.js
painter 中设置其透明度:
// 设置画布背景及透明度
_setBg() {
this.ctx.globalAlpha = 0.7;
this.setCvaBg();
return this;
}
OK,参照绘画功能就实现啦,接下去要实现视图引导的第二个功能:通过直接拖拽图片进行检索。当然,我们这里不涉及跟服务端进行交涉,因此只实现前端的拖拽图片功能,这部分会用到一些坐标判断,正好趁此机会好好整理一下。利用拖拽可以实现很多效果,还是挺好玩哒~~加油加油~q(≧▽≦q)
敬请关注下一篇:开发Canvas 绘画应用(四):实现拖拽绘画
✈ Github:paintApp
✎ 参考:
开发Canvas 绘画应用(三):实现对照绘画的更多相关文章
- 开发Canvas 绘画应用(二):实现绘画
开发Canvas 绘画应用(一):搭好框架 中我们已经把基本框架及基础功能实现了,现在要实现本应用的重点:绘画功能. 首先分析一下,我们要实现绘画,需要具备的理论知识如下: (1)获取触摸点的坐标 类 ...
- 开发Canvas 绘画应用(四):实现拖拽绘画
在开发Canvas绘画应用(三):实现对照绘画中,我们实现了视图引导的第一部分,这一篇我们来完成第二部分,即将图片直接拖到画布上进行绘画. ✁ 拖放如何实现? [拖放的基本概念]:创建一个绝对定位的元 ...
- 开发Canvas 绘画应用(一):搭好框架
毕业汪今年要毕业啦,毕设做的是三维模型草图检索,年前将算法移植到移动端做了一个小应用(利用nodejs搭的服务),正好也趁此机会可以将前端的 Canvas 好好学一下~~毕设差不多做完了,现将思路和代 ...
- 一步一步开发Game服务器(三)加载脚本和服务器热更新(二)完整版
上一篇文章我介绍了如果动态加载dll文件来更新程序 一步一步开发Game服务器(三)加载脚本和服务器热更新 可是在使用过程中,也许有很多会发现,动态加载dll其实不方便,应为需要预先编译代码为dll文 ...
- [课程设计]Scrum 3.1 多鱼点餐系统开发进度(第三阶段项目构思与任务规划)
Scrum 3.1 多鱼点餐系统开发进度(第三阶段项目构思与任务规划) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选题:餐厅到 ...
- iOS开发Swift篇—(三)字符串和数据类型
iOS开发Swift篇—(三)字符串和数据类型 一.字符串 字符串是String类型的数据,用双引号""包住文字内容 let website = "http://www ...
- Scrum 3.1 多鱼点餐系统开发进度(第三阶段项目构思与任务规划)
Scrum 3.1 多鱼点餐系统开发进度(第三阶段项目构思与任务规划) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选题:餐厅到 ...
- ASP.NET自定义控件组件开发 第一章 第三篇
原文:ASP.NET自定义控件组件开发 第一章 第三篇 第三篇:第一章的完结篇 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待 ...
- iOS 开发问题集锦(三)
iOS 开发问题集锦(三) 介于群里大部分童鞋都是新手,为了大家能够更好的提问,并且提的问题能更好的得到回答,下面写几点提问时的注意事项: 1.认真对待你的问题,在提问题前有过认真的思考: 2.先在 ...
随机推荐
- 版本控制,django缓存,跨域问题解决
复习 分页: 1. 简单分页 2. 偏移分页 3. 加密分页 解析器:客户处理前端提交来的数据 urlencode: body体中的数据格式: key=value& formdata编码:为区 ...
- 通过编写一个简单的日志类库来加深了解C#的文件访问控制
在程序的开发调试过程及发布运行后的状态监控中,日志都有着极其重要的分量,通过在关键逻辑节点将关键数据记录到日志文件当中能帮助我们尽快找到程序问题所在.网上有不少专业成熟的日志组件可用,比如log4ne ...
- apk文件二维码微信无法识别 APP在微信中二维码扫描无法下载的解决方案
现在微信分享的功能很多,从分享的链接下载apk安卓包是很正常的,但是微信不让下载apk包,只能通过浏览器来下载,但是这要给用户一个提示吧,不然用户不知道 下面我们来实现,引导用户通过浏览器来下载apk ...
- ffmpeg的使用说明
ffmpeg的使用说明 借鉴博客:https://www.cnblogs.com/DragonFire/p/9208195.html 一.FFmpeg链接: 链接:https://pan.baidu. ...
- 网络请求get和post的区别
网络请求get和post的区别 其实本文更应该放在HTTP相关的分类,但是目前我并没有开设这一个分类专栏,so临时储存在HTML分类吧 Get和post是HTTP请求的两种基本方式 get是从服务器上 ...
- vue-cli axios跨域 + 反向代理模拟http请求host+referer
axios跨域 配置config->index.js中的proxyTable,内容如下: proxyTable: { // 跨域请求 '/api': { // 注意此处可设置为 '*' 代表不限 ...
- python之路-python2.x与python3.x区别
Python崇尚优美.清晰.简单,是一个优秀并广泛使用的语言. Python2.x 与 Python3.x的区别: python2.x:源码混乱,重复代码较多,冗余. python3.x:源码规范,崇 ...
- 考研计算机复试(C语言复试笔试题)(精华题选)
1.以下选择中,正确的赋值语句是(C) A.a=1,b=2 B.j++ C.a=b=5; D.y=(int)x 解析:选项A.B.D都无分号 变量 = 表达式;//赋值语句是一定带分号的 int a= ...
- maven的依赖特性
若排版紊乱可查看我的个人博客原文地址 maven的依赖特性很多很杂,这里大概总结一下,maven的依赖特性主要是依赖范围和传递依赖,前者会影响后者,这篇文章会介绍传递依赖的传递原则,出现冲突传递依赖默 ...
- springboot快速开发(简单web)
这是一个springboot基础配置文件介绍的demo.只涉及到 控制层与前端的简单交互,用于验证代码的畅通. spring-boot pom.xml解释 <?xml version=&quo ...