制作Canvas画板

画板预览

源码地址
canvas的使用查mdn文档就可以了
下面主要讲的是实现画板的思路,以及我的踩坑记录

先不用canvas标签

先用div,首先知道用户点了哪里
使用console.log调试

<div id="canvas"></div>
xxx.onClick = (e) => {console.log(e)//e.clientX//e.clientY
}

在点击的地方出现圆点

let div = document.createElement('div')
div.style.position = 'absolute'
div.style.left = e.clientX + 'px'
div.style.top = e.clientY + 'px'
div.style.border = '1px solid red'
div.style.weight = '5px'
div.style.height = '5px'
div.style.borderRadius = '50%'
div.style.backgroundColor = 'black'
xxx.appendChild(div)

把点连起来,点变成线
现在是直接操作dom(操作div的),性能差

改进:使用canvas。

<canvas id="canvas"></canvas>

canvas是inline元素
display: block;
再把宽高设置成页面这么大即可

var ctx = canvas.getContext("2d");ctx.fillStyle = "rgb(200,0,0)";ctx.fillRect (10, 10, 55, 50);

上面这个是canvas画出一个形状,前面两个参数是起始位置,后面两个是宽高

canvas的宽高是在一开始就确定的,

<canvas id="canvas" width="100" height="100"></canvas>

如果后面css还有宽高,就会覆盖这个宽高,但是就相当于缩放了,放大的话就会变模糊。所以最开始写宽高就会写好(用js获取用户屏幕的宽高)

var canvas = document.getElementById("canvas")
const mainWidth = parseInt(main.clientWidth * 0.95);
const mainHeight = parseInt(main.clientHeight );
canvas.width = `${mainWidth}`;
canvas.height = `${mainHeight}`;
canvas.style.width = `${mainWidth}px`;
canvas.style.height = `${mainHeight}px`;

注意:获取的是文档的宽高,获取body是不行的,因为body的高度是由内容撑起来的,没有内容,高度就没有

下面是做点击就打点的操作

canvas.onClick = (e) => {ctx.fillRect(e.clientX - 5, e.clientY - 5, 10, 10)
}

这个是canvas的api

变换鼠标事件
onClick->onmousemove
使用一个变量来看鼠标是否是按下,按下时鼠标移动就继续划线,鼠标松开时就不划线

let painting = falsecanvas.onmousedown = () => {painting = true
}
canvas.onmousemove = () => {painting = false
}
canvas.onClick = (e) => {if(painting === true) {ctx.fillRect(e.clientX - 5, e.clientY - 5, 10, 10)}
}

这样就实现了鼠标按下就画线,鼠标松开就停

画圆点

ctx.beginPath();
ctx.arc(50, 50, 50, 0, 2 * Math.PI, false);
ctx.stroke();
ctx.arc(50, 50, 50, 0, 2 * Math.PI, false);
ctx.arc(e.clientX, e.clientY,10, 0, 2 * Math.PI, false);

前两个参数是起始位置,第三个是半径,后面两个是角度

ctx.fill()//实心,填充颜色

再把边框去掉
ctx.strokeStyle = 'none'
现在就可以慢速的画了,为什么是慢速呢,因为是拼凑的,画快了就断掉了,当速度快一点时,就变成点的形状了

怎么样支持手机,但是手机没有鼠标事件,所以就要判断是手机还是pc。
js detect touch support

var isTouchDevice = 'ontouchstart' in document.documentElement;

判断isTouchDevice是true或者false,就能知道是手机还是pc

难点

这个在手机上是支持的,在电脑上是不支持的,就可以判断是手机还是电脑(搜了半天),(就是上面这个)

手机上ontouchstart就是触屏事件,参数e里面就是有touches,里面包含了我们需要的x和y(位置)
手机上就没有按下,起来的事件,就直接是触摸事件

现在是点,把点变成线就可以了
在canvas里面搜直线,这个是三角形,也就是三个点,画直线的画就要两个点就够了,去掉第三个点即可

//描边三角形ctx.beginPath();ctx.moveTo(125, 125);ctx.lineTo(125, 45);ctx.lineTo(45, 125);ctx.closePath();ctx.stroke();//上面的就是三个点,然后把三个点连起来

两个点连上就变成直线了,记住上一个点,然后连起来就好起来了

记住上一次的点,然后把现在的点和上一次的点连起来,就可以了,第一个点没有上一个点,所以从第二个点开始。

把线变粗
ctx.lineWidth = 10

难点

画出来的线又很粗糙

解决:js canvas line join
把line和line之间的链接变成圆弧
ctx.lineCap = "round"

整个画板的实现过程

获取位置->打点->连线->断断续续->记住上一个点连起来->粗糙->变成圆弧就不粗糙了

使用了flex布局

使用正则表达式来替换颜色,把颜色转化为不同的格式

const color = getComputedStyle(e.target).backgroundColor;
获取当前的颜色

用了一个伪类来在显示的时候添加边框

颜色的部分使用了<input type="color"></input>

橡皮檫部分是使用了ctx.globalCompositeOperation = "destination-out";
去mdn上查就能查到这个属性的作用

铅笔是ctx.globalCompositeOperation = "source-over";

这两个相互切换是使用了classList,首先给这个添加selected这个类,加上标签,然后再用forEach和indexOf来判断eraser和source-over确定是铅笔还是橡皮

画布的高度

const mainWidth = parseInt(main.clientWidth * 0.95);
const mainHeight = parseInt(main.clientHeight );
canvas.width = `${mainWidth}`;
canvas.height = `${mainHeight}`;
canvas.style.width = `${mainWidth}px`;
canvas.style.height = `${mainHeight}px`;

鼠标绘图

main.addEventListener("mousedown", (e) => {painting = true;lastX = e.offsetX;lastY = e.offsetY;ctx.beginPath();ctx.arc(lastX, lastY, ctx.lineWidth / 2, 0, 2 * Math.PI);ctx.closePath();ctx.fill();
});
main.addEventListener("mousemove", (e) => {if (painting) {ctx.beginPath();ctx.moveTo(lastX, lastY);ctx.lineTo(e.offsetX, e.offsetY);ctx.closePath();ctx.stroke();lastX = e.offsetX;lastY = e.offsetY;}
});
main.addEventListener("mouseup", (e) => {painting = false;
});
// 鼠标移出画布停止绘画,防止再次进入产生连线
main.addEventListener("mouseout", (e) => {painting = false;
});

移动端绘图

// 触摸绘图
canvas.addEventListener("touchstart", (e) => {painting = true;lastX = e.touches[0].pageX - e.touches[0].target.offsetLeft;lastY = e.touches[0].pageY - e.touches[0].target.offsetTop;ctx.beginPath();ctx.arc(lastX, lastY, ctx.lineWidth / 2, 0, 2 * Math.PI);ctx.closePath();ctx.fill();
});
// 使用事件委托优化移动端绘图,在画布上触摸移动时阻止body默认事件(阻止浏览器的滑动)
document.body.addEventListener("touchmove",(e) => {if (painting && e.target.matches(`canvas`)) {e.preventDefault();ctx.beginPath();ctx.moveTo(lastX, lastY);ctx.lineTo(e.touches[0].pageX - e.touches[0].target.offsetLeft,e.touches[0].pageY - e.touches[0].target.offsetTop);ctx.closePath();ctx.stroke();lastX = e.touches[0].pageX - e.touches[0].target.offsetLeft;lastY = e.touches[0].pageY - e.touches[0].target.offsetTop;}},{ passive: false }
);
canvas.addEventListener("touchend", (e) => {painting = false;
});
// 触摸移出画布停止绘画,防止再次进入产生连线
canvas.addEventListener("touchcancel", (e) => {painting = false;
});

显示当前的颜色

currentColor.addEventListener("input", (e) => {ctx.strokeStyle = e.target.value;ctx.fillStyle = e.target.value;
});
thickness.addEventListener("input", (e) => {ctx.lineWidth = parseInt(e.target.value);
});

点击切换颜色

// 点击色块改变画笔颜色,将色块背景色赋值给 currentColor.value (RGB 转为 HEX )
brushColor.addEventListener("click", (e) => {if (e.target.matches("li")) {let color16 = "#";const color = getComputedStyle(e.target).backgroundColor;[...color.matchAll(/\d{1,3}/g)].forEach((item) => {const str = parseInt(item).toString(16);color16 += str.length === 2 ? str : "0" + str; // 确保六位数 HEX 颜色值});ctx.strokeStyle = color16;ctx.fillStyle = color16;currentColor.value = color16;}
});

画笔和橡皮的切换

// 点击图标切换铅笔橡皮,使用 globalCompositeOperation 设置绘图类型
type.addEventListener("click", (e) => {if (e.target.matches("img")) {const li = e.target.parentNode;type.childNodes.forEach((node) =>node.classList ? node.classList.remove("selected") : undefined);li.classList.add("selected");if (Array.from(li.classList).indexOf("eraser") >= 0) {text.textContent = "橡皮";ctx.globalCompositeOperation = "destination-out";} else {text.textContent = "铅笔";ctx.globalCompositeOperation = "source-over";}}
});

canvas画板总结相关推荐

  1. 使用signature在移动端做电子签名canvas画板随触摸滚屏的bug

    在做移动端项目的时候,如果页面需要滚动,而页面上有signature实现的电子签名,就会发现手写的时候canvas画板会随着手指的滑动而滚动,导致不能正常签名. 解决办法:在canvas标签上注册一个 ...

  2. 实现一个canvas画板

    <canvas>是HTML5新增的元素,可用于通过使用JavaScript中的脚本来绘制图形.例如,它可以用于绘制图形,制作照片,创建动画,甚至可以进行实时视频处理或渲染. --摘自MDN ...

  3. canvas画板涂鸦动画进度条动画

    目录 什么是 canvas 画板涂鸦动画 进度条动画 写在最后 什么是 canvas canvas 是 HTML5 新定义的标签,通过使用脚本(通常是 JavaScript)绘制图形.允许脚本语言动态 ...

  4. 南宁小程序开发,挑战百日学习计划第47天(canvas画板工具1)

    南宁小程序开发:www.nasiot.com canvas画板工具 ,一定要在canvas里面写width height 否则会导致画线被强制放大 <canvas id="c" ...

  5. 移动端canvas画板绘图工具

    移动端canvas画板绘图工具 原生js canvas画板可在移动端使用,使用鼠标或者手指触屏绘画各种图形效果. 演示地址 下载地址

  6. canvas画板绘制多图和绘制文字及下载

    ** canvas画板绘制多图和绘制文字及下载 有要求需要做宣传图,加文字动态排版,以及,二维码排版,还要完成后下载的功能,然后研究了一下午,写了一个供大家学习 上效果图 上代码: <!DOCT ...

  7. html canvas生成图片,html5 canvas画板涂鸦生成图片代码

    特效描述:html5 canvas 画板涂鸦 生成图片代码.html5画板涂鸦 代码结构 1. HTML代码 清 空 生成图片 var canvas,board,img; canvas = docum ...

  8. HTML5 canvas画板的制作

    canvas画板的制作   今天看了一些canvas视频的教程,有制作画板的过程,但是我有给出他们的简洁版和使用版本,能让用户看出画直线的路径,也就是当你拉一条直线的时候就和绘图工具一样,都能很好使用 ...

  9. html5 canvas 画板 demo,html5 canvas 简单画板实现代码

    canvas简单画板 #can{ width:600px; height:500px; border:1px solid #ccc; margin-top:0px; margin-left:20px; ...

最新文章

  1. 机器学习算法1_线性回归
  2. Diomidis Spinellis:有效的调试
  3. 【异常】 ‘ascii‘ codec can‘t decode byte 0xe8 in position 2: ordinal not in range(128)
  4. C++中指针*与指针引用*的区别说明
  5. python调用打印机驱动下载_selenium的Python使用(一)浏览器驱动的安装及使用
  6. webStorm activeCode
  7. 机器人出魔切还是三相_英雄联盟:辅助也要去上单,机器人布里茨玩法介绍
  8. android布局的属性,android
  9. 编程基础(三)——体系结构之三
  10. 小波包8层分解与重构MATLAB代码,谐波小波包分解与重构程序谁有呢?
  11. 剑指offer之编程是一种习惯
  12. 考研高危人群!你是否还在危险的边缘试探?
  13. 2015英语命题规律
  14. 名字中间一条线怎么弄_网名怎么加横线啊 网名中间加一条横线
  15. MPX + Vant Weapp 在微信小程序中实现Picker选择器
  16. 58 同城移动端 Passport SDK 的设计与技术细节
  17. python发送邮件封装
  18. 中小企业数字化转型的痛点分析
  19. Couldn‘t find ffmpeg or avconv - defaulting to ffmpeg, but may not work快速解决办法
  20. 【每日新闻】身份证照可“自拍”上传 解决又一民生痛点

热门文章

  1. Spring Boot 学习之路之 Spring Security(二)加入mybatis
  2. oracle比较两个时间
  3. 使用imageIO获取和修改图片的exif信息
  4. 关于C语言二级机考软件环境的一些问题
  5. 推荐算法(一)——音乐歌单智能推荐
  6. 鼠标划过显示鼠标移出隐藏效果
  7. Ubuntu18.04下 安装SMPlyer视频播放器 设置倍速播放
  8. 微信公众号Makrdown编辑器,语法你懂吗?
  9. 计算机毕业设计JavaBS高校教师考勤系统(源码+系统+mysql数据库+lw文档)
  10. PPT文字过少时,如何排版比较好