canvas 菜鸟入门笔记

之前就知道有canvas画布,但是一直都没有用的机会,so...一直也没学习过,今天就开始菜鸟的canvas学习~

<canvas></canvas>是个双标签 ,标签中间可以放替换内容--如果浏览器不兼容画布的话,就会显示中间的替代内容(i9之前的版本的不支持的!)

<canvas>有width height id 属性 (默认不设置宽高的时候显示300px宽和150px高)

canvas画布其实就是纯js画的,canvas元素有很多方法 

getContext() 的方法,用来获得渲染上下文和它的绘画功能。

<!DOCTYPE html>
<html lang="en">
<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>canvas创建</title>
    <style>
        canvas{
            border: 1px solid rgb(19, 18, 18);
        }
    </style>
</head>
<body>
    <canvas id="demo1" width="400px" height="400px"></canvas>
    <script  type="text/javascript">
    //获取元素dom
    let demo1=document.querySelector('#demo1')
    //指定画布是2d形式
    let ctx= demo1.getContext('2d')
    </script>
</body>
</html>

简单的画布就出现了~

接下来用canvas先做一个表格背景,对canvas知识运用~

<!DOCTYPE html>
<html lang="en">
<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>canvas的使用</title>
    <style>
      html,
      body,
      .container{
        height: 100%;
        width: 100%;
       }
       .container{
       display: flex;
       justify-content: center;
       align-items: center;
       }
        canvas{
            border: 1px solid rgb(19, 18, 18);
        }
       
    </style>
</head>
<body>

    <div class="container">
    <canvas id="demo2" width="400px" height="400px"></canvas>
    </div>
    <script  type="text/javascript">
    //获取元素dom
    let demo2=document.querySelector('#demo2')
    //指定画布是2d形式
    let ctx= demo2.getContext('2d')
    //创建网格线
    //ctx指定画布,stepX是线与线x间距 stepY是线与线y间距 color是线的颜色 lineWidth是线的宽度
    function drawGrid(ctx,stepX, stepY, color, lineWidth){
         // // 设置绘制颜色
            ctx.strokeStyle = color;
            // 创建垂直格网线路径
            for(let i = stepX; i < demo2.width; i += stepX){
              // 设置绘制线段的宽度
            ctx.lineWidth = lineWidth;
            //开启路径
            ctx.beginPath()
            
            //笔触的位置-moveTo经常是画一些不连续的线
            ctx.moveTo(i, 0);
            //绘制一条从当前位置到指定x以及y位置的直线。
             ctx.lineTo(i,demo2.height);
            ctx.stroke()
            }
            // 创建水平格网线路径
            for(let j = stepY; j < demo2.height; j += stepY){
                // 设置绘制线段的宽度
            ctx.lineWidth = lineWidth;
                //开启路径
                ctx.beginPath()
                ctx.moveTo(0, j);
                ctx.lineTo(demo2.width, j);
                ctx.stroke()
            }
        }
        //调用封装好的表格工具
        drawGrid(ctx,20, 20, '#ccc', 0.5);

    </script>
</body>
</html>

效果图

 当然我封装的是一个表格的工具函数,在写组件的时候,可以传入需要网格的画布 ,水平和垂直的间隔 ,颜色,线条的宽 度,这些可以根据需要自己定制o~

这里有个小注意点,width和height是写在canvas标签上的,不要写到style上,不然网格会非常的模糊!

小示例 用画布画一个钟表

在开始画之前我们必须了解一下canvas的坐标空间,哪里是原点,x轴,y轴

小红点是坐标(0,0)也就是原点,水平向右是x轴,垂直向下是y轴

效果图

 完整代码

<!DOCTYPE html>
<html lang="en">
<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>canvas画钟</title>
    <style>
      html,
      body,
      .container{
        height: 100%;
        width: 100%;
       }
       .container{
       display: flex;
       justify-content: center;
       align-items: center;
       }
        canvas{
            border: 1px solid rgb(19, 18, 18);
        }
       
    </style>
    <script></script>
</head>
<body>

<div class="container">
    <canvas id="demo3" width="600px" height="600px"></canvas>
</div>
<script  type="text/javascript">
//获取元素dom
let demo2=document.querySelector('#demo3')
//指定画布是2d形式
let ctx= demo3.getContext('2d')
ctx.save();
// ---------------------------------------------------------------------------------网格背景
//创建网格线
function drawGrid(ctx,stepX, stepY, color, lineWidth){
        ctx.save()
    // // 设置绘制颜色
       ctx.strokeStyle = color;
       // 创建垂直格网线路径
       for(let i = stepX; i < demo2.width; i += stepX){
         // 设置绘制线段的宽度
       ctx.lineWidth = lineWidth;
       //开启路径
       ctx.beginPath()
       
       //笔触的位置-moveTo经常是画一些不连续的线
       ctx.moveTo(i, 0);
       //绘制一条从当前位置到指定x以及y位置的直线。
        ctx.lineTo(i,demo2.height);
       ctx.stroke()
       }
       // 创建水平格网线路径
       for(let j = stepY; j < demo2.height; j += stepY){
           // 设置绘制线段的宽度
       ctx.lineWidth = lineWidth;
           //开启路径
           ctx.beginPath()
           ctx.moveTo(0, j);
           ctx.lineTo(demo2.width, j);
           ctx.stroke()
       }
        ctx.restore()
   }

// ----------------------------------------------------表盘大圆

function bigclock() {  
    ctx.save()
    ctx.beginPath()
    // 画圆线使用arc(中心点X,中心点Y,半径,起始角度,结束角度)
    ctx.arc(0, 0, 200, 0, 2 * Math.PI)
    ctx.stroke() //画轮廓
    ctx.closePath()
    ctx.restore()
}
  
// -------------------------------------------------------画表心
function clockcenter(){
    ctx.save()
    ctx.beginPath()
    // 画圆线使用arc(中心点X,中心点Y,半径,起始角度,结束角度) Math.PI=3.14=180度
    ctx.arc(0, 0, 5, 0, 2 * Math.PI)
    ctx.fill()
    ctx.closePath()
    ctx.restore()
}

// -------------------------------------------------画时针
function drawHour(hour,minutes){
    ctx.save()
    ctx.rotate(2 * Math.PI / 12 * hour + 2 * Math.PI / 12 * (minutes / 60) )
    ctx.beginPath()
    ctx.moveTo(-1,0);
    ctx.lineTo(-10,-80);
    ctx.lineTo(0,-85);
    ctx.lineTo(10,-80);
    ctx.lineTo(1,0);
    // 设置线宽
    ctx.lineWidth = 1
    ctx.fillStyle="pink"
    ctx.fill() //画轮廓
    ctx.closePath()
    ctx.restore()
}

// --------------------------------------------------画分针
function drawMinu(minutes,seconds){
    ctx.save()
    ctx.rotate(2 * Math.PI / 60 * minutes + 2 * Math.PI / 60 * (seconds / 60) )
    ctx.beginPath()
    ctx.moveTo(-1,0);
    ctx.lineTo(-6,-140);
    ctx.lineTo(0,-145);
    ctx.lineTo(8,-140);
    ctx.lineTo(1,0);
    // 设置线宽
    ctx.lineWidth = 1
    ctx.fillStyle="red"
    ctx.fill() //画轮廓
    ctx.closePath()
    ctx.restore()
}

//---------------------------------------------------画秒针
function drawSecond(seconds) { 
    ctx.save()
    ctx.rotate(2 * Math.PI / 60 * seconds)
    ctx.beginPath()
    ctx.moveTo(-1,0);
    ctx.lineTo(-4,-170);
    ctx.lineTo(0,-175);
    ctx.lineTo(5,-170);
    ctx.lineTo(1,0);
    // 设置线宽
    ctx.lineWidth = 1
    ctx.fillStyle="blue"
    ctx.fill() //画轮廓
    ctx.closePath()
    ctx.restore()
    
 }

// -------------------------------------------------画小时的刻度
function hourkedu(){
    ctx.save()
    ctx.lineWidth = 5
    for (let i = 0; i < 60; i++) {
    ctx.rotate(2 * Math.PI / 12)
    ctx.beginPath()
    ctx.moveTo(193, 0)
    ctx.lineTo(200, 0)
    ctx.stroke()
    ctx.closePath()
    }
    ctx.restore()
}

// -------------------------------------------------画分针的刻度
function minukedu() {
    ctx.save()
    ctx.lineWidth = 2
    for (let i = 0; i < 60; i++) {
    ctx.rotate(2 * Math.PI / 60)
    ctx.beginPath()
    ctx.moveTo(195, 0)
    ctx.lineTo(200, 0)
    ctx.stroke()
    ctx.closePath()
    }
    ctx.restore()
  }

//  让表动起来
    setInterval(()=>{
    // -------------------------------------------------------获取当前时间
    let time = new Date()
    let hour = time.getHours() % 12//对当前时间取余 比如现在时间16点 对应的就是4点
    let minutes = time.getMinutes()
    let seconds = time.getSeconds()
    // 清除画布
    ctx.save()
    ctx.clearRect(0, 0, 600, 600)
    drawGrid(ctx,20, 20, '#ccc', 0.5);
    //找到画布的中心点
    ctx.translate(300,300)
    // 大表盘
    bigclock()
    // 画表心
    clockcenter()
    hourkedu()
    minukedu()

    drawHour(hour,minutes)
    drawMinu(minutes,seconds)
    drawSecond(seconds)
    ctx.restore() 
    },1000)
    </script>
</body>
</html>

注意:比较难理解的地方是ctx.save()和ctx.restore()

save()是保存当前状态,比如我们获取了画布dom,设置了2d模式,需要保存一下状态

resrore()则是回退到上一个状态

canvas画画就是用坐标画出一个图,然后很多图一层一层压在一起,,每次画一个图的时候都需要先保存当前状态,然后画完之后回退到画之前

在让表动起来的时候用的是setInterval,需要先保存当前状态,清除画布,画完之后,需要回退到上一个状态!!!!!这个非常重要

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值