热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

运用Canvas和JavaScript做一个画板

本文同步于个人博客:https:zhoushuo.meblog20180311drawing-borad前些天进修了HTML5的元素,本日就来实践一下,用canva

本文同步于个人博客:https://zhoushuo.me/blog/2018/03/11/drawing-borad/

前些天进修了HTML5元素,本日就来实践一下,用canvas做一个画板。

《运用Canvas和Javascript做一个画板》

起首说一下要完成的功用:

  • 切换画笔色彩
  • 调整笔刷粗细
  • 清空画布
  • 橡皮擦擦除
  • 打消操纵
  • 保留成图片
  • 兼容挪动端(支撑触摸)

好了,废话少说,先看终究结果:https://zhoushuozh.github.io/drawingborad

预备工作

起首,预备个容器,也就是画板了。

然后初始化js:

let canvas = document.getElementById("drawing-board");
let ctx = canvas.getContext("2d");

我想把画板做成全屏的,所以接下来设置一下canvas的宽高。

let pageWidth = document.documentElement.clientWidth;
let pageHeight = document.documentElement.clientHeight;
canvas.width = pageWidth;
canvas.height = pageHeight;

由于部份IE不支撑canvas,假如要兼容IE,我们能够建立一个canvas,然后运用excanvas初始化,针对IE加上exCanvas.js,这里我们临时先不斟酌IE。

完成一个简朴的画板

完成思绪:监听鼠标事宜,用drawCircle()要领把纪录的数据画出来。

  1. 设置初始化当前画布功用为画笔状况,painting = false
  2. 当鼠标按下时(mousedown),把painting设为true,示意正在画,鼠标没松开。把鼠标点纪录下来。
  3. 当按下鼠标的时刻,鼠标挪动(mousemove)就把点纪录下来并画出来。
  4. 假如鼠标挪动过快,浏览器跟不上绘画速率,点与点之间会产物间隙,所以我们须要将画出的点用线连起来(lineTo())。
  5. 鼠标松开的时刻(mouseup),把painting设为false

代码:

let painting = false;
let lastPoint = {x: undefined, y: undefined};
//鼠标按下事宜
canvas.Onmousedown= function (e) {
painting = true;
let x = e.clientX;
let y = e.clientY;
lastPoint = {"x": x, "y": y};
drawCircle(x, y, 5);
};
//鼠标挪动事宜
canvas.Onmousemove= function (e) {
if (painting) {
let x = e.clientX;
let y = e.clientY;
let newPoint = {"x": x, "y": y};
drawLine(lastPoint.x, lastPoint.y, newPoint.x, newPoint.y,clear);
lastPoint = newPoint;
}
};
//鼠标松开事宜
canvas.Onmouseup= function () {
painting = false;
}
// 画点函数
function drawCircle(x, y, radius) {
ctx.save();
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fill();
}
// 划线函数
function drawLine(x1, y1, x2, y2) {
ctx.lineWidth = 3;
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
ctx.closePath();
}

橡皮擦功用

完成思绪

  1. 猎取橡皮擦元素
  2. 设置橡皮擦初始状况,clear = false
  3. 监听橡皮擦click事宜,点击橡皮擦,转变橡皮擦状况,clear = true
  4. cleartrue时,挪动鼠标运用canvas剪裁(clip())擦除画布。

let eraser = document.getElementById("eraser");
let clear = false;
eraser.Onclick= function () {
clear = true;
};
...
if (clear) {
ctx.save();
ctx.globalCompositeOperation = "destination-out";
ctx.stroke();
ctx.closePath();
ctx.clip();
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.restore();
}
...

注重,在canvas中的裁剪和日常平凡的裁剪功用不一样在这里,裁剪是指在裁剪地区去显现我们所画的图

兼容挪动端

完成思绪:

  1. 推断装备是不是支撑触摸
  2. true,则运用touch事宜;false,则运用mouse事宜

代码:

...
if (document.body.ontouchstart !== undefined) {
// 运用touch事宜
anvas.Ontouchstart= function (e) {
// 最先触摸
}
canvas.Ontouchmove= function (e) {
// 最先滑动
}
canvas.Ontouchend= function () {
// 滑动完毕
}
}else{
// 运用mouse事宜
...
}
...

这里须要注重的一点是,在touch事宜里,是经由过程.touches[0].clientX.touches[0].clientY来猎取坐标的,这点要和mouse事宜区别开。

切换画笔色彩

完成思绪:

  1. 猎取色彩元素节点。
  2. 点击色彩返回其色彩值,并赋给画布的ctx.strokeStyle

代码:

let aColorBtn = document.getElementsByClassName("color-item");
for (let i = 0; i aColorBtn[i].Onclick= function () {
for (let i = 0; i activeColor = this.style.backgroundColor;
ctx.strokeStyle = activeColor;
}
}

清空画布

完成思绪:

  1. 猎取元素节点。
  2. 点击清空按钮清空canvas画布。

代码:

let reSetCanvas = document.getElementById("clear");
reSetCanvas.Onclick= function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
};

调整笔刷粗细

完成思绪:

  1. 建立input[type=range]
  2. 滑动range猎取其value值,并赋给ctx.lineWidth

代码:

let range = document.getElementById("range");
range.Onchange= function(){
lWidth = this.value;
};

保留成图片

完成思绪:

  1. 猎取canvas.toDateURL
  2. 在页面里建立并插进去一个a标签
  3. a标签href即是canvas.toDateURL,并增添download属性
  4. 点击保留按钮,a标签触发click事宜

代码:

let save = document.getElementById("save");
save.Onclick= function () {
let imgUrl = canvas.toDataURL("image/png");
let saveA = document.createElement("a");
document.body.appendChild(saveA);
saveA.href = imgUrl;
saveA.download = "zspic" + (new Date).getTime();
saveA.target = "_blank";
saveA.click();
};

打消

完成思绪:

  1. 预备一个数组纪录汗青操纵
  2. 每次运用画笔前将当前画图外表贮存进数组
  3. 点击打消时,恢复到上一步的画图外表

代码:

canvas.Ontouchstart= function (e) {
// 在这里贮存画图外表
this.firstDot = ctx.getImageData(0, 0, canvas.width, canvas.height);
saveData(this.firstDot);
...
}
let undo = document.getElementById("undo");
let historyDeta = [];
function saveData (data) {
(historyDeta.length === 10) && (historyDeta.shift()); // 上限为贮存10步,太多了怕挂掉
historyDeta.push(data);
}
undo.Onclick= function(){
if(historyDeta.length <1) return false;
ctx.putImageData(historyDeta[historyDeta.length - 1], 0, 0);
historyDeta.pop()
};

由于每次贮存都是将一张图片存入内存,对机能影响较大,所以在这里设置了贮存上限。

总结

这里用的知识点主要有:监听mousetouch事宜,以及canvasmoveTo()lineTo()stroke()clip()clearRect()等要领。实在另有许多结果能够完成,比如说喷雾结果,蜡笔结果,艺术画结果等等。往后有时间我会继承对这个画板举行优化,增添一些新的功用,同时迎接人人留言发问或许提出批评发起。

终究代码:https://github.com/zhoushuozh/drawingborad


推荐阅读
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 安卓select模态框样式改变_微软Office风格的多端(Web、安卓、iOS)组件库——Fabric UI...
    介绍FabricUI是微软开源的一套Office风格的多端组件库,共有三套针对性的组件,分别适用于web、android以及iOS,Fab ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
author-avatar
Seet琸琸
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有