如果是首次接触JS,并没有学语法结构的情况下,怎么思考或者利用工具文档,实现写一个画板的例子:
1、通过console.log得到鼠标的位置。然后创建一个div,在上面加css样式。首先是监听pc端onclick这个事件,然后去web页面点击,来模拟onclick这个事件,看console控制台的反馈,里面可以看懂的是x,y坐标,然后就利用这个相对位置;
2、在看懂的列表里,再找一个特殊的点(最左上角),出来坐标0,0 随便找一组clientX和clientY这一组描述坐标,写到代码里试试看,是不是想要的。
3、实现onclick事件后,有轨迹记录,先用方形box-border试一下,写上canvas.appendChild(div),去web页面onclick,就会有方形的点出现,然后调整点的样式居中,最后实现onclick事件发生后,实现web页面的点出现。每onclick一次,就会走一遍这个逻辑。
4、怎么实现线出现呢?可以先用div标签实现onmousemove这个动作,鼠标移到web页面是,会有卡顿的情况,这是跨线程工作,以上步骤的代码如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>画板</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="canvas"></div>
<script>
canvas.onmousemove = (e)=>{
console.log(e)
console.log(e.clientX)
console.log(e.clientY)
//console.log 调试大法
let div = document.createElement('div')
div.style.position = 'absolute' //让div的内联样式里面的position赋absolute
div.style.left =e.clientX + 'px'
div.style.top =e.clientY + 'px'
div.style.width ='6px'
div.style.height = '6px'
div.style.marginLeft = '-3px'
div.style.marginTop ='-3px'
div.style.borderRadius = '50%'
div.style.backgroundColor = 'black'
canvas.appendChild(div)
}
</script>
</body>
</html>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#canvas{
height: 100vh;
border: 1px solid red;
}
5、还有一种直接引用canvas这个自身的属性来实现上面的过程,
<body>
<canvas id="canvas"></canvas>
<script>
//看canvas怎么画线
</script>
加入此行代码后,web页面会出现侧面滚动条,是因为canvas默认是个inline元素,即便是在canvas标签中定义高度、宽度属性,还是会被css覆盖
6、去canvas用法文档里面搜索,‘一个简单的例子’,直接抄代码【CRM_C】绘制一个长方形,用这个例子来深入探索一下它是如何工作的?
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect (10, 10, 55, 50);
7、接着就研究这行代码能有什么作用,无非就是换值来试呗,试值后的结果表明: fillRect是填充矩形,后面四个值分别代表:这个矩形框的X轴起始坐标,Y轴起始坐标,宽度,高度
ctx.fillRect (10, 10, 55, 50);
8、目前存在一个问题,矩形框很模糊,这时去掉css里面的宽度,高度限制后,矩形框变清晰且变小了,也就是说在一开始写canvas的时候就要写好屏幕的尺寸,那怎么知道用户屏幕的宽度呢?用JS获取,Google一下:JS如何获取屏幕的宽度和高度。得到一个参数是网页可见区域宽:document.body.clientWidth.这样就可以用console.log(document.body.clientWidth)来打印一下结果呗。
得到的打印结果是958.经验证这是一个正确的参数,可以用google到的这两个参数:
var canvas = document.getElementById("canvas");
canvas.width = document.body.clientWidth
canvas.height = document.body.clientHeight
出现了高度异常的现象,这是因为body的高度由里面的内容确定的,在css里面加个body的border边框,高度不改变,就不能满足需求了,还得找别的方法...给个捷径直接给你参数吧:
var canvas = document.getElementById("canvas");
canvas.width = document.documentElement.clientWidth
canvas.height = document.documentElement.clientHeight
9、经过一番调整后,实现了onmousemove出现点,实现的代码如下:
canvas.onmousemove = (e) => {
console.log(e.clientX)
console.log(e.clientY)
ctx.fillRect (e.clientX -5, e.clientY -5, 10, 10);
}
10、以上9步实现了onmousemove这个基本条件,接下来还得优化一下,mousedown不按鼠标时的情形,要引用一个指示信号来让两种情况区别逻辑实现,在此之前加一个画圆的样式修改,
let ctx = canvas.getContext("2d");
let painting = false
ctx.fillStyle = "black";
ctx.strokeStyle = 'none'
canvas.onmousedown = () => {
painting = true
}
canvas.onmousemove = (e) => {
if (painting===true) {
ctx.beginPath();
//圆心x坐标,y坐标,半径,
ctx.arc(e.clientX, e.clientY, 10, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
}else{
console.log('什么都不做')
}
}
canvas.onmouseup = () => {
painting = false
}
11、接下来研究手机上的实现。先研究一下调整到手机屏幕大小的尺寸能否监听到鼠标事件,google到了JS手机是否支持触屏的一篇文档里介绍了打印这个动作的代码:
let isTouchDevice='ontouchstart' in document.documentElement;
console.log(isTouchDevice)
在web页面的手机和pc端切换刷新看到打印结果都是符合猜测的。
12、开始编写ontouch的逻辑实现:
先写出第一个版本,还没有在手机上实现触屏处点轨迹:
let ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.strokeStyle = 'none'
let painting = false
let isTouchDevice='ontouchstart' in document.documentElement;
if(isTouchDevice){
canvas.ontouchmove = (e)=>{
console.log(e)
}
}else{
canvas.onmousedown = () => {
painting = true
}
canvas.onmousemove = (e) => {
if (painting===true) {
ctx.beginPath();
ctx.arc(e.clientX, e.clientY, 10, 0, 2 * Math.PI);//圆心x坐标,y坐标,半径,
ctx.stroke();
ctx.fill();
}
}
canvas.onmouseup = () => {
painting = false
}
}
上例中,e这个动作拿的是单手触摸和多手指触摸的很多种情况,所以就要从所有打印的信息里,找多手指触摸的信息:
touches: TouchList {0: Touch, length: 1}
type: "touchmove"
13、最后实现了手机画图的代码如下:
let ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.strokeStyle = 'none'
let painting = false
let isTouchDevice='ontouchstart' in document.documentElement;
if(isTouchDevice) {
canvas.ontouchmove = (e) => {
let x = e.touches[0].clientX
let y = e.touches[0].clientY
ctx.beginPath();
ctx.arc(x, y, 10, 0, 2 * Math.PI);//圆心x坐标,y坐标,半径,
ctx.stroke();
ctx.fill();
}
}else{
canvas.onmousedown = () => {
painting = true
}
canvas.onmousemove = (e) => {
if (painting===true) {
ctx.beginPath();
ctx.arc(e.clientX, e.clientY, 10, 0, 2 * Math.PI);//圆心x坐标,y坐标,半径,
ctx.stroke();
ctx.fill();
}
}
canvas.onmouseup = () => {
painting = false
}
}
14、回头来看pc端的点怎么能更优化一下,先用的描绘三角形,简化为线段,再重新优化组成线的点,在遇到折线时的不连续,不圆润的问题,修改了一些属性:
ctx.fillStyle = "black";
ctx.strokeStyle = 'black'
ctx.lineWidth = 8;
ctx.lineCap='round'; //使线更圆润
15、再修改一下手机端的代码,重新画线,最终的完整代码为:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>画板</title>
<link rel="stylesheet" href="style.css"> //加一个css样式的链接
</head>
<body>
<canvas id="canvas" width="100" height="100"></canvas> //发现代码问题善于用console.log来验证
<script>
let canvas = document.getElementById("canvas"); //经过尝试<div>验证后,添加的canvas属性
canvas.width = document.documentElement.clientWidth //定义画布的宽度,有一个中间值推导而来
canvas.height = document.documentElement.clientHeight
let ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.strokeStyle = 'black'
ctx.lineWidth = 8;
ctx.lineCap='round'; //解决了在遇到折线时的不连续,不圆润的问题,在很多的属性里尝试
let painting = false
let last
let isTouchDevice='ontouchstart' in document.documentElement;
if(isTouchDevice) {
canvas.ontouchstart = (e) => {
let x = e.touches[0].clientX
let y = e.touches[0].clientY
last = [x,y]
}
canvas.ontouchmove = (e) => {
let x = e.touches[0].clientX
let y = e.touches[0].clientY
drawLine(last[0], last[1], x, y)
last = [x,y]
}
}else{
canvas.onmousedown = (e) => {
painting = true
last = [e.clientX, e.clientY]
}
canvas.onmousemove = (e) => {
if (painting===true) {
drawLine(last[0], last[1], e.clientX, e.clientY)
last = [e.clientX,e.clientY]
}
}
canvas.onmouseup = () => {
painting = false
}
}
function drawLine(x1,y1,x2,y2){
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke(); //描边是stroke;填充是fill
}
</script>
</body>
</html>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#canvas{
display: block;
}