H5--Canvas使用以及API

Canvas前端绘图工具,Canvas API 提供了一个通过JavaScript 和 HTML的<canvas>元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。

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

标签属性:

8b43dc0f2d904e2d8983626929876574.png

 获取画笔:

const ctx = canvas.getContext('2d');

API:

线条相关:

d9e73e1a2332448cb82c5a5d694b128d.png

绘制矩形:

f44186fbc03f427582e8264f1bf53b35.png

路径

a83c4e4d60e44d758a62d4b6053b8afb.png

绘制路径

bc394b3fbbe24b998599d25a9f10b230.png

填充和描边

ed5563baeef4486298db864251e36f7c.png

 渐变
返回的CanvasGradient对象的addColorStop(offset, color)添加渐变颜色

1a8ebc06ff47454caaee8ce0db0f9df0.png

绘制文本

fc0e69b8f3e8472484ba5dcc31fb7db1.png

文本样式

3c6555e03e7d485e8f776ffb4a6a5a6b.png

 阴影

44cd134544424bac9280d7f7105278d0.png

 变换

145e0a36aceb48dea22ece7505cb0140.png

合成

eb82cb7c67cd4469a06bb80a33e4aea9.png

绘制图像

f070a0e690d64cee9f324c2638d3fc95.png

像素控制

0b2d2332c2744352bd712c2a9e6a44d5.png

canvas状态

ee71e39fb0534de8bbb4489a66616a0d.png

下面实践下看看:

签名

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
     <canvas id="canvas" width="400" height="400"/>

</body>
<script type="text/javascript">
    canvas.style.background="pink" //设置背景颜色为粉色
    let ctx = canvas.getContext('2d') //获取画笔
    ctx.save() //保存当前的画笔状态
    ctx.strokeStyle="blue" //设置画笔颜色为蓝色
    ctx.lineWidth="2" //线条的宽度为2
    ctx.beginPath() //开始一个新的路径
    ctx.strokeRect(100,100,100,100) //绘制矩形100x100
    ctx.restore() //恢复画笔,此时画笔为黑色了
    ctx.moveTo(100,100) //画笔移至坐标(100,100)
    ctx.arc(200,200,100,0,Math.PI*2/3,true) //绘制圆弧,原心坐标(200,200),半径100,起始弧度为0,结束弧度为2/3
    ctx.stroke() //画弧
    //随鼠标按下有绘制痕迹
    canvas.onmousedown = function(e){ 
        ctx.save() //保存画笔状态
        ctx.strokeStyle="green" //配置画笔颜色为绿色
        ctx.beginPath() //开始新的路径
        //使用鼠标相对浏览器的x,y减去画布距离浏览器的x,y获取到在画布里鼠标的坐标。
        ctx.moveTo(e.clientX-canvas.offsetLeft,e.clientLeft-canvas.offsetTop)//移动到鼠标按下的坐标处
        console.log(canvas.offsetLeft,canvas.offsetTop);
        //鼠标移动时候画线到鼠标所到位置
        document.onmousemove=function(e){
            ctx.lineTo(e.clientX-canvas.offsetLeft,e.clientY-canvas.offsetTop)
            ctx.stroke() //画图
            ctx.restore() //恢复画笔状态
        }
        document.onmouseup=function(){
            document.onmousemove = document.onmouseup=null //画完结束恢复鼠标移动的鼠标事件
        }
        return
    }
    
</script>
</html>

旋转放大缩小:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <canvas id="canvas" width="300" height="300"></canvas>
</body>
<script type="text/javascript">
    let flag=0 
    let scale = 0 //放大的比例
    let flagScale=0
    canvas.style.background="pink"
    let ctx = canvas.getContext("2d")
    ctx.save()
    ctx.translate(150,150)//画笔平移到坐标(150,150)
    ctx.beginPath() //开始新的路径
    ctx.fillRect(-50,-50,100,100) //以(150,150为矩形中心画矩形)
    ctx.restore()
    //设置计时器自动调整放大和缩小
    setInterval(()=>{
        flag++
        ctx.clearRect(0,0,canvas.width,canvas.height) //清除画布
        ctx.save()
        ctx.translate(150,150)
        ctx.rotate(flag*Math.PI/180) //旋转一定的角度
        //scale最大为100,超过100那么开始缩小,到0开始增大
        if(scale==100){
            flagScale=-1
        }else if(scale==0){
            flagScale=1
        }
        scale+=flagScale
        ctx.scale(scale/50,scale/50)
        ctx.beginPath()
        ctx.fillRect(-50,-50,100,100)
        ctx.restore()
    },1000/60)
</script>
</html>

绘制钟表:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <canvas id="canvas" width="400" height="400" />
</body>
<script type="text/javascript">
    canvas.style.backgroundColor = "pink"
    let ctx = canvas.getContext("2d")
    // setInterval(()=>{
    //     ctx.clearRect(0,0,canvas.width,canvas.height)//每秒清除画布
    //     move() //绘制钟表
    // },1000)
    move() //初始化钟表
    function move(){
        ctx.save()
        ctx.lineWidth = "8"
        ctx.strokeStyle = "black"
        ctx.lineCap = "round"
        ctx.translate(200, 200)
        ctx.rotate(-90 * Math.PI / 180) //逆时针旋转90度,修改了坐标的方向右上为正
        ctx.beginPath()

        ctx.save()
        ctx.strokeStyle = "blue"
        ctx.lineWidth = "14"
        ctx.beginPath()
        ctx.arc(0, 0, 140, 0, 360 * Math.PI / 180)//画圆弧,最外层的圆半径为140
        ctx.stroke()
        ctx.restore()
        //时针刻度
        ctx.save()
        for (let i = 0; i < 12; i++) {
            ctx.rotate(30 * Math.PI / 180) //将圆盘分割成12份为时针的刻度
            ctx.beginPath()
            ctx.moveTo(100, 0) //距离圆环40处
            ctx.lineTo(120, 0) //画长度20
            ctx.stroke()
        }
        ctx.restore()
        // 分针刻度
        ctx.save()
        ctx.lineWidth = "4"
        for (let i = 0; i < 60; i++) { //将圆盘分割成60份为分针的刻度
            if (i % 5 != 0) { //避开5的倍数绘制,因为已经存在了时针的刻度
                ctx.beginPath()
                ctx.moveTo(117, 0)
                ctx.lineTo(120, 0)
                ctx.stroke()
            }
            ctx.rotate(6 * Math.PI / 180) //每次旋转6度
        }
        ctx.restore()
        //获取当前时间以便绘制指针的位置
        let seconds = new Date().getSeconds()
        let minutes = new Date().getMinutes() + seconds / 60
        let hour = new Date().getHours() + minutes / 60
        hour = hour > 12 ? hour - 12 : hour

        //时针
        ctx.save()
        ctx.lineWidth = 14
        ctx.rotate(hour * 30 * Math.PI / 180)
        ctx.beginPath()
        ctx.moveTo(-20, 0)
        ctx.lineTo(80, 0)
        ctx.stroke()
        ctx.restore()
        //分针
        ctx.save()
        ctx.lineWidth=10
        ctx.rotate(minutes * 6 * Math.PI / 180)    
        ctx.beginPath()
        ctx.moveTo(-28,0)
        ctx.lineTo(112,0)
        ctx.stroke()
        ctx.restore()
        //秒针
        ctx.save()
        ctx.strokeStyle="#D40000"
        ctx.rotate(seconds * 6 * Math.PI / 180)    
        ctx.lineWidth=6
        ctx.beginPath()
        ctx.moveTo(-30,0)
        ctx.lineTo(83,0)
        ctx.stroke()
        ctx.restore()

        ctx.save()
        ctx.fillStyle="#D40000"
        ctx.beginPath()
        ctx.moveTo(0,0)
        ctx.arc(0,0,10,0,360*Math.PI/180)
        ctx.fill()
        ctx.restore()

        ctx.save()
        ctx.lineWidth=6
        ctx.strokeStyle="#D40000"
        ctx.rotate(seconds * 6 * Math.PI / 180)

        ctx.beginPath()
        ctx.arc(96,0,10,0,360*Math.PI/180)
        ctx.stroke()

        ctx.restore()
        ctx.restore()
    }
</script>

</html>

canvas 搭配video

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <video id="video" loop autoplay src="https://imgs-qn.51miz.com/preview/video/00/00/12/72/V-127220-21D61AFB.mp4" width="0" height="0"></video>
    <canvas id="canvas" width="300" height="200"></canvas>
</body>
<script type="text/javascript">
    let ctx = canvas.getContext('2d')
    video.addEventListener("loadeddata", function () {
        console.log(123)
        setInterval(function(){
            ctx.drawImage(video, 0, 0, canvas.width, canvas.height) 
        })
    })
</script>

</html>

写入图片:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <canvas id="canvas" width="400" height="400" />
</body>
<script type="text/javascript">
    canvas.style.background = "pink"
    let ctx = canvas.getContext("2d")
    let img = new Image() //创建image对象
    img.src = "img.jpg" //添加资源路径
    img.onload=()=>{
        ctx.drawImage(img, 0, 0,canvas.width, canvas.height)        
    }
</script>

</html>

canvas实现刮刮卡的效果:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<style>
    *{
        margin: 0;
        padding: 0
    }
    html,body{
        height:100%;
        overflow: hidden;
    }
    #canvas{
        position: absolute;
        top:0;
        left:0;
        transition:1s
    }
    .wrap,.wrap>div{
        height: 100%
    }
    .wrap>div{
        background-image: url("./img2.jpg");
        background-size: 100% 100%;
    }
</style>
<body>
    <div class="wrap">
        <canvas id="canvas"></canvas>
        <div></div>
    </div>
</body>
<script type="text/javascript">
    // 获取宽高,
    canvas.width=document.documentElement.clientWidth
    canvas.height=document.documentElement.clientHeight
    let ctx = canvas.getContext("2d")
    //获取canvas画的图片,父级元素的背景是底图
    let img =new Image()
    img.src="img.jpg"
    let imgData = ctx.getImageData(0,0,canvas.width,canvas.height)
    img.onload=function (){
        draw()
    }
    function draw(){
        ctx.drawImage(img,0,0,imgData.width,imgData.height) //绘画图片
        canvas.addEventListener("touchstart",(e)=>{ //点击到屏幕时触发
            console.log(e)
            let touchC= e.changedTouches[0]
            let x = touchC.clientX-canvas.offsetLeft
            let y = touchC.clientY-canvas.offsetTop
            ctx.lineWidth=20
            ctx.lineCap="round"
            ctx.lineJoin="round"
            ctx.globalCompositeOperation="destination-out"
            ctx.save()
            ctx.beginPath()
            ctx.moveTo(x,y)
            ctx.lineTo(x+1,y+1)
            ctx.stroke()
            ctx.restore()
        })
        canvas.addEventListener("touchmove",(e)=>{ //滑动时触发
            let touchC= e.changedTouches[0]
            let x = touchC.clientX-canvas.offsetLeft
            let y = touchC.clientY-canvas.offsetTop
            console.log(x,y)
            ctx.save()
            // ctx.arc(x,y,20,0,360*Math.PI/180)
            ctx.lineTo(x+1,y+1)
            ctx.stroke()
            ctx.restore()
        })
        canvas.addEventListener("touchend",(e)=>{ //离开屏幕时触发
            let flag =0
            let imgData = ctx.getImageData(0,0,canvas.width,canvas.height)
            let allPixle = imgData.width*imgData.height //获取图片像素
            for(let i=0;i<allPixle;i++){
                if(imgData.data[4*i+3]==0){
                    flag++
                }
            }
            if(flag>allPixle*1/2){ //滑过超过一半的话,隐藏画布
                canvas.style.opacity=0
            }
        })
        canvas.addEventListener("transitionend",function(){
            this.remove()//隐藏画布过渡时触发,删除画布
        })
    }
    ctx.save()
    ctx.beginPath()
    ctx.restore()
</script>
</html>

canvas马赛克:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <canvas id="canvas" />
</body>
<script type="text/javascript ">
    let ctx = canvas.getContext('2d')
    let oldImg = new Image()
    oldImg.src = "img2.jpg"
    oldImg.onload=()=>{
        canvas.width=oldImg.width*2
        canvas.height=oldImg.height
        draw()
    }
    function draw(){
        ctx.drawImage(oldImg,0,0)
        //获取原图的imageData
        let oldImgData = ctx.getImageData(0,0,oldImg.width,oldImg.height)
        // 创建新的图片数据,按照原图的尺寸
        let newImgData = ctx.createImageData(oldImg.width,oldImg.height)
        console.log(newImgData)
        let size = 20 //指定马赛克块的大小
        for(let i = 0;i<oldImgData.width/size;i++){
            for(let j =0;j<oldImgData.height/size;j++){
                // (i,j)每个马赛克的巨型坐标
                //获取原图颜色,在像素区域内随机选取一个颜色
                let color = getColor(oldImgData,i*size+Math.floor(Math.random()*size),j*size+Math.floor(Math.random()*size))
                //把整个20以内的所有像素全部设置为一样的颜色
                for(let a=0;a<size;a++){
                    for(let b=0;b<size;b++){
                        setColor(newImgData,i*size+a,j*size+b,color)
                    }
                }
            }
        }

        ctx.putImageData(newImgData,oldImg.width,0)
    }
    function getColor(imgData,x,y){ //每个像素是由rgba的形式出现
        let data = imgData.data
        let w = imgData.width
        let h = imgData.height
        let color = Array(4)
        //y*w+x是指该元素前有多少个像素,来定位当前的像素
        color[0]=data[(y*w+x)*4]
        color[1]=data[(y*w+x)*4+1]
        color[2]=data[(y*w+x)*4+2]
        color[3]=data[(y*w+x)*4+3]
        return color
    }
    function setColor(imgData,x,y,color){
        let data = imgData.data
        let w = imgData.width
        let h = imgData.height
        data[(y*w+x)*4]=color[0]
        data[(y*w+x)*4+1]=color[1]
        data[(y*w+x)*4+2]=color[2]
        data[(y*w+x)*4+3]=color[3]
    }
</script>

</html>

猜你喜欢

转载自blog.csdn.net/m0_59962790/article/details/130535604