canvas 画点_JavaScript实践之Canvas(画板)

模拟画板进行画点

方法:DIV

通过div来进行模拟画板

CSS

 <style>
 * {
 margin: 0;
 padding: 0;
 box-sizing: border-box;
        }
 #canvas {
 border: 1px solid red;
 height: 100vh;
        }
 </style>

body

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

JS

<script>
 canvas.onmousemove = (e) => {
 console.log(e.clientX)
 console.log(e.clientY)
 //console.log 调试大法 获取目标位置
 let div = document.createElement('div')
 div.style.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>
通过 console.log来获取鼠标点击时/鼠标移动时的位置信息

console.log(e.clientX)

console.log(e.clientY)

079e2fa62274ef187f6cc680c87e3056.png

079e2fa62274ef187f6cc680c87e3056.png

ü 通过let div = document.createElement('div')创建一个div元素

let div = document.createElement('div')

声明 文档(当前网页) 创建 元素/标签 ‘元素名’

含义:在文档中创建一个div标签,并且赋予给左边的div变量,这样我们可以直接通过变量(div)来调整样式

ü 在最后一定要添加 canvas.appendChild(div)

canvas.appendChild(div)

Id标签 添加 孩子 元素 注:不加引号‘’

给canvas(id)添加孩子div,只有这样div才能添加到HTML中去

默认所有的东西都是在内存中的,需要进行调用/添加才可进行使用

ü 通过div.style.position = 'absolute'首先设置div元素的层叠关系(位置)为absolut绝对定位(最上方)

回顾下div的层叠世界

ü 通过div.style.left = e.clientX + 'px'调整div的位置

div.style.top = e.clientY + 'px'

注意:一定要加+'px',不然只会在控制台显示,不会有像素的变化

ü 通过div.style.width = '6px'调制div的宽高比

div.style.height = '6px'

注:都需要加style,因为都是通过JS添加的CSS属性

ü 通过div.style.marginLeft = '-3px'调整div处于鼠标箭头的正中心

div.style.marginTop = '-3px'

079e2fa62274ef187f6cc680c87e3056.png

ü 通过div.style.borderRadius = '50%' 圆角(把矩形变成圆形)

079e2fa62274ef187f6cc680c87e3056.png

ü 通过div.style.backgroundColor = 'black' 填充颜色

注:Color可省略

ü 以上样式都是通过JS基于CSS样式属性上进行添加的,所有不要忘记添加stylep哦,

总结:以上操作都是通过JS操作DOM上添加节点,JS的单线程(重复一遍的执行)非常的慢,所有下面我们用更为方便的canvas来制作画板

Canvas

画点(矩形)

CSS

*{
 margin: 0;
 padding: 0;
 box-sizing: border-box;
}
#canvas{
 /* border: 1px solid red; */
 display: block;
}

HTML

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

Js

 <script>
 let canvas = document.getElementById('canvas');
 
 canvas.width = document.documentElement.clientWidth;
 canvas.height = document.documentElement.clientHeight;
 let ctx = canvas.getContext('2d');
 ctx.fillStyle = 'black';
 
let painting = false;
 
 canvas.onmousedown = (e) => {
 painting = true;
                           }
 canvas.onmousemove = (e) => {
 if (painting === true) {
                      ctx.fillRect(e.clientX-5,e.clientY-5,10,10)
 
                } else {
 console.log('什么也不做')
                }
            }
 canvas.onmouseup = () => {
 painting = false;
            }   
 </script>

注:canvas不是DIV,类似于img(在HTML设置宽高比,但在CSS中会覆盖原有尺寸,其优先级更高)

ü 通过ctx.fillStyle = 'black';//调整颜色

ü 通过 ctx.fillRect(e.clientX-5,e.clientY-5,10,10)控制矩形的样式

当canvas在HTML确定好尺寸,再通过CSS强行修改的,画板中元素会失真(被拉伸),类似于img;所以CSS中不能设置width/height;

Canvas的默认尺寸为inline(尽可能的窄),blcok(尽可能的宽)

我们就需要屏幕的大小(自适应)来决定

好的习惯:先进行网上查询,“JS 如何获取屏幕尺寸(宽高)”

通过console.log(document.documentElement.clientWidth)打印屏幕宽度

通过console.log(document.documentElement.clientHeight)打印屏幕高度

注意:不要通过document.body.clientHeight来获取 屏幕高度;body的高度是由其内容决定的,获取的是body的高度并不是屏幕(文档)的高度,所以要用document.documentElement.clientHeight

canvas.width = document.documentElement.clientWidth;

canvas.height = document.documentElement.clientHeight;

Canvas的width等于屏幕的宽

Canvas的Height等于屏幕的高

通过let painting = false; painting = false配合鼠标事件onmousemove/onmouseup来控制开启和停止画线

通过fillStyle控制填充的颜色

canvas不会通过Js新建DOM节点,只是告诉画板进行像素绘制,所以不会有延迟的出现

onmousedown为开启(绿灯)

painting=true

onmouseup为关闭(红灯)

painting=false

注意if(===){}一定时三个符号进行判断

消除锯齿并画圆形

 <script>
 let canvas = document.getElementById('canvas');
 
 canvas.width = document.documentElement.clientWidth;
 canvas.height = document.documentElement.clientHeight;
 let ctx = canvas.getContext('2d');
 ctx.fillStyle = 'black';
 ctx.strokeStyle='none';
let painting = false;
 
 canvas.onmousedown = (e) => {
 painting = true;
                           }
 canvas.onmousemove = (e) => {
 if (painting === true) {
       ctx.beginPath();
                ctx.arc(e.clientX,e.clientY, 5, 0, 2 * Math.PI);
                ctx.stroke();
                ctx.fill();
 
                } else {
       console.log('什么也不做')
                }
            }
 canvas.onmouseup = () => {
 painting = false;
            }   
 </script>

通过ctx.arc(e.clientX,e.clientY, 5, 0, 2 * Math.PI)控制圆形的样式

通过 ctx.fill()调用之前声明fillStyle颜色

fill()方法填充当前图像(路劲),默认颜色为黑色
注:fillStyle属性用来填充另一种颜色/渐变
注:如果路径未关闭,那么fill()方法会以路径结束点到开始点添加一条线,以关闭路径,然后填充该路径

API在前端中含义

api全程为application interface(接口),前端所说的api,通常指的是JavaScript封装的一些功能

api可以理解为一个功能

function add(a,b){
return a+b;
}
//简单的求和api

疑问:function f(a){}中a是怎么来的

function fn(a){
console.log(a)
}
f(1)
f(2)

当声明一个函数和参数后,当别人调用的时候,传给a什么值就是什么值

onmousemove是怎么来的

当用户鼠标动的时候,浏览器会调用onmousemove,把canvas.onmousemove(事件相关信息)传回给你(包装成'e'),所以事件相关信息的取值什么都可以,最终用收到才会看见画线过程

注意:不可以在canvas标签上直接写width=100vw;height=100vh因为这是CSS单位,不是HTML的
拓展:querySelector()方法返回文档中批评为指定CSS选择器的一个元素

在移动端上调试

常识:手机上没有鼠标,所以要首先确定浏览器是否支持触屏(监听触屏事件)
var isTouchDevice = 'ontouchstart' in document.doucumentElement;
console.log(isTouchDevice) //声明后需要console.log测试下是否支持:移动端显示true;pc端显示false

CSS

*{
 margin: 0;
 padding: 0;
 box-sizing: border-box;
}
#canvas{
 /* border: 1px solid red; */
 display: block;
}

HTML

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

Js

let canvas = document.getElementById('canvas');

        canvas.width = document.documentElement.clientWidth;
        canvas.height = document.documentElement.clientHeight;

        let ctx = canvas.getContext('2d');
        ctx.fillStyle = 'black';

        let isTouchDevice = 'ontouchstart' in document.documentElement;

        let painting = false;
        // let last

        if (isTouchDevice) {

            canvas.ontouchmove = (a) => {
                let x = a.touches[0].clientX;
                let y = a.touches[0].clientY;
                ctx.beginPath();
                ctx.arc(x, y, 5, 0, 2 * Math.PI);
                ctx.stroke();
                ctx.fill();
            } else {
            canvas.onmousedown = (e) => {
                painting = true;
            } 
    
            canvas.onmousemove = (e) => {
                if (painting === true) {
                      ctx.beginPath();
                      ctx.arc(x,y,10,0,2*Math.PI)
                      ctx.stroke();
                      ctx.fill();
                  }
             }

            canvas.onmouseup = () => {
                painting = false;
            }
        }
注意:移动端与PC端的不同,触摸手指个数。

可以通过console.log(e.touches[0])先确定是否可以获取x和y的值,console.log(x,y)可以包含两个数值

通过let x=e.toaches[0].clientX 和 let y=e.toaches[0].clientY 设置触摸的位置属性(x,y)

移动端会自动监听是否触摸开启和关闭。bug:在微信浏览器有bug,在向下划动时,屏幕会跟着动

画线

canvas mdn查阅资料

CSS

*{
 margin: 0;
 padding: 0;
 box-sizing: border-box;
}
#canvas{
 /* border: 1px solid red; */
 display: block;
}

HTML

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

Js

let canvas = document.getElementById('canvas');

        canvas.width = document.documentElement.clientWidth;
        canvas.height = document.documentElement.clientHeight;

        let ctx = canvas.getContext('2d');
        ctx.fillStyle = 'black';
        ctx.lineWidth = 5;
        ctx.lineCap = "round";

        let isTouchDevice = 'ontouchstart' in document.documentElement;

        let painting = false;
        // let last

        function drawline(x1, y1, x2, y2) {
            ctx.beginPath();
            ctx.moveTo(x1, y1);
            ctx.lineTo(x2, y2);
            ctx.stroke();
        }

        if (isTouchDevice) {

            canvas.ontouchstart = (a) => {

                let x = a.touches[0].clientX;
                let y = a.touches[0].clientY;
                last = [x, y]
                console.log(x, y);
                ctx.beginPath();
                ctx.arc(x, y, 5, 0, 2 * Math.PI);
                ctx.stroke();
                ctx.fill();

            }
            canvas.ontouchmove = (a) => {
                let x = a.touches[0].clientX;
                let y = a.touches[0].clientY;
                drawline(last[0], last[0], 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];

                } else {
                    console.log('什么也不做')
                }
            }
            canvas.onmouseup = () => {
                painting = false;
            }
        }

    </script>

通过以下代码控制是否画线

ctx.beginPath();   
ctx.moveTo(x1, y1); 
ctx.lineTo(x2, y2);     
ctx.stroke();

通过写成一个函数drawLine(0,0,500,500)传四个参数来可以用来调用其代码

function drawline(x1, y1, x2, y2) {
       ctx.beginPath();
       ctx.moveTo(x1, y1); 
       ctx.lineTo(x2, y2); 
       ctx.stroke();        
}

通过let last 声明变量,用来表示记录上次的起点位置

通过设置第一个点(鼠标按下)

 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];

原理:当第3个点移动时,出现di3个点时,Js会诚信被调用一般,last=[e.clientX,e.clientY]则会把第2个点当作起始点,一次类推,这样就实现了画线(而不会出现始终从第一点开始的bug)

注:Js不会调用DOM,而是直接告诉canvas

注:last[0]是二位数组中的第一个元素,以此类推

通过ctx.lineWidth = 5控制线条粗心

通过ctx.lineCap = "round";控制两端为圆头

常识:注意凡是移动端都需要考虑几点触控(几个手指)

可以console.log获取位置信息(touches[0]是一个手指,一点触控)

console.log( a.touches[0].clientX)
console.log(a.touches[0].clientY)

移动端(触摸事件)

按下手指(第一次位置)

ontouchstart

拖拽/移动手指(第二次位置开始)

ontouchmove

完成触屏/结束(最后一次位置记录)

ontouchend

触屏取消

ontouchcancel(电话/弹出信息触发取消,一般会在ontouchcancel暂停/存档操作)

注:移动端默认移走手指则关闭关闭,所以不用设置

PC端(鼠标事件)

按下鼠标

onmousedown

移动鼠标

onmousemove

松开鼠标

onmouseup

移动到元素外

onmouseout

移动到指定元素

onmouseover

拓展:函数基本概念

函数声明

function fn() {}
使用function关键字声明一个函数,在指定一个函数名,叫做函数声明

函数表达式

var fnName= function(){}
使function关键字声明一个函数,但为给函数命名,最后将匿名函数赋予一个变量,叫做函数表达式,这也是最常见的函数表达式

注:匿名函数有很多作用,赋予一个变量则创建函数,赋予一个事件则时间处理程序或创建闭包等等

函数声明和函数表达式不同之处在于

一、JavaScript引擎在解析 JavaScript代码时会函数声明提升当前执行环境(作用域)上的函数声明

而函数表达式必须等到JavaScript引擎执行到它所在的行时,才会从上而下一行一行的解析函数表达式

二、函数表达式后面可以加括号,立即调用该函数。函数声明不可以,只能以fnName()形式调用函数

在function前面加!、+、-甚至时逗号等都可以起到函数定义后立即执行的效果,而()、!、+、-、=等运算符,都将函数声明转换成函数表达式

消除了JavaScript引擎灯识别函数表达式和函数声明的歧义,告诉JavaScript引擎这是一个函数表达式,不是函数声明,可以在后面加括号,并立即执行函数的代码

举例:

function t1(age){
      console.log(age);      //2:收到传给参数后,打印23
  var age=function age(){
      console.log(age);      //4:通过age()调用得到;注:此处age()中age为变量不是函数名
  }                       
  age();
  console.log(age);          //7:通过第7行console.log(age)打印得到,此处的age来说也是变量
}
t1(23);
________
23                           //2
f age(){                     //4
console.log(age);
}
f age(){                     //7
console.log(age);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值