Canvas

目录

一、基本图形绘制

1.1、矩形绘制

1.2、圆弧绘制

1.3、线段绘制

1.4、贝尔赛曲线绘制气泡框和爱心

1.5、画布清除

二、样式控制

2.1、颜色设置

2.2、线性渐变与径向渐变

2.3、pattern印章填充样式

2.4、线段和虚线样式

2.5、绘制图片、视频添加水印

2.6、文字绘制与对齐

2.7、旋转、位移、缩放

三、高级应用

3.1、合成图像模式实现刮刮卡

3.2、裁剪路径

3.3、状态的保存与恢复

一、基本图形绘制

文档:在mdn搜canvas: https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API

画布创建与上下文对象

 <canvas id="MyCanvas" width="600" height="400"></canvas>

1.找到画布

var context = document.getElementById("MyCanvas");

2.获取画笔,上下文对象

var ctx = context.getContext("2d");

1.1、矩形绘制

填充绘制矩形fillRect(位置x,位置y,宽度,高度)

  ctx.fillRect(100, 200, 300, 300)

路径绘制矩形strokeRect(位置x,位置y,宽度,高度)

  ctx.strokeRect(100, 50, 200, 80)

1.2、圆弧绘制

绘制圆弧arc(圆心x,圆心y,半径,开始角度,结束角度,逆时针or顺时针(默认顺时针false))+stroke()

备注:Math.PI / 2==>90度   Math.PI * 2==>360度

ctx.arc(300, 200, 50, 0, Math.PI / 2, true);

ctx.stroke()

扩展:纯色笑脸

左边为基础班,右边为改进版,其中moveTo()可以绘制一条不连续的路径。

1.3、线段绘制

 lineTo(终点的x轴坐标, 终点的y轴坐标)

1.4、贝尔赛曲线绘制气泡框和爱心

ctx.beginPath();
        ctx.moveTo(200, 300)
 // 曲线从moveTo()指定的点开始:(200, 300)。控制点位于 (150, 300)。曲线在 (150, 200) 处结束。
        ctx.quadraticCurveTo(150, 300, 150, 200)
        ctx.quadraticCurveTo(150, 100, 300, 100)
        ctx.quadraticCurveTo(450, 100, 450, 200)
        ctx.quadraticCurveTo(450, 300, 250, 300)
        ctx.quadraticCurveTo(250, 350, 150, 350)
        ctx.quadraticCurveTo(200, 350, 200, 300)
ctx.stroke()
ctx.closePath();
ctx.beginPath();
        ctx.moveTo(300, 200);
        ctx.bezierCurveTo(350, 150, 400, 200, 300, 250);
        ctx.bezierCurveTo(200, 200, 250, 150, 300, 200);
ctx.stroke()
ctx.closePath();

//========================封装路径:Path2D=============

var heartPath=new Path2D()
        heartPath.moveTo(300, 200);
        heartPath.bezierCurveTo(350, 150, 400, 200, 300, 250);
        heartPath.bezierCurveTo(200, 200, 250, 150, 300, 200);
ctx.stroke(heartPath)
ctx.fill(heartPath);//黑色填充

1.5、画布清除

 ctx.clearRect(0, 0, context.clientWidth, context.clientHeight)//一键清除

扩展:渐渐消失

 let height = 0;
        let t1 = setInterval(() => {
            height++;
            ctx.clearRect(0, 0, context.clientWidth, height);
            if (height > context.clientHeight) {
                clearInterval(t1)
            }
}, 10)

 补充:ctx.beginPath(); ctx.closePath();//完成路径的分段

绘制效果展示:

二、样式控制

2.1、颜色设置

        ctx.strokeStyle = 'red';//颜色设置

        ctx.fillStyle = "green";//填充的颜色设置

        ctx.fill(heartPath);//填充设置

2.2、线性渐变与径向渐变

线性渐变:createLinearGradient

径向渐变:createRadialGradient

//==============线性渐变=================
   let index = 0;
function render() {
            ctx.clearRect(0, 0, 600, 400);
            index += 0.01;
            if (index > 1) {
                index = 0
            }
            let linearGradient = ctx.createLinearGradient(100, 200, 400, 500)
            linearGradient.addColorStop(0, 'red')
            linearGradient.addColorStop(index, 'pink')
            linearGradient.addColorStop(1, 'blue')
            ctx.fillStyle = linearGradient
            ctx.fillRect(100, 200, 300, 300)
            requestAnimationFrame(render)
        }
requestAnimationFrame(render)
//==============径向渐变模拟3D球=================
let radiaGradient = ctx.createRadialGradient(250, 150, 10, 300, 200, 100)
        radiaGradient.addColorStop(0, 'pink')
        radiaGradient.addColorStop(1, 'red')
        ctx.fillStyle = radiaGradient;
        ctx.arc(300, 200, 100, 0, Math.PI * 2)
        ctx.fill()

2.3、pattern印章填充样式

createPattern创建图片,放置原理和css一样

var img = new Image()
        img.src = './pat.png'
        img.onload=function(){
            // createPattern的重复方式repeat,no-repeat,repeat-x,repeat-y
            var pattern=ctx.createPattern(img,'no-repeat')
            ctx.fillStyle=pattern
            ctx.fillRect(0,0,600,400)
}

2.4、线段和虚线样式

lineCap(线条端点样式):butt平齐  round半圆  square正方形

lineJoin(设置2个线段连接处的样式):mitter外侧相连的角 round角磨圆  bevel

虚线:以数组形式setLineDash

  let index = 0
function render() {
            ctx.clearRect(0, 0, 600, 400)
            index++
            if (index > 40) {
                index = 0
            }
            ctx.moveTo(150, 150)
            ctx.lineTo(300, 200)
            ctx.lineTo(450, 150)
            ctx.lineWidth = 10
            // 线条端点样式:butt平齐  round半圆  square正方形
            ctx.lineCap = 'square'
            // 设置2个线段连接处的样式,mitter外侧相连的角 round角磨圆  bevel
            ctx.lineJoin = 'mitter'
            // 对斜接面进行限制
            // ctx.miterLimit = 5
            ctx.setLineDash([40, 20])
            ctx.lineDashOffset = index
            ctx.stroke()
            requestAnimationFrame(render)
        }
render()

2.5、绘制图片、视频添加水印

第一种:基于画布的坐标,不管原图大小;

第二种:基于画布的坐标,可设置要展示的原图大小;

第三种:基于画布的坐标,在原图的大小上进行截取,并展示在画布上;

drawImage(image, dx, dy);
drawImage(image, dx, dy, dWidth, dHeight);
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

let img=new Image()
        img.src='./bigs.png'
        img.onload=function(){
            ctx.drawImage(img,0,0)
            ctx.drawImage(img,0,0,600,400)
            // 原图片大小:1200x700
            ctx.drawImage(img,400,230,400,230,0,0,600,400)
        }

给视频添加水印,无非就是同时将视频与图片同时放在画布上,都是用drawImage方法渲染的

<canvas id="MyCanvas" width="600" height="400"></canvas>
<video src="./line.mp4" controls width="200" height="200" hidden></video>
<button id="btn">播放/暂停</button>
    <script>
        // 1.找到画布
        var context = document.getElementById("MyCanvas");
        // 2.获取画笔,上下文对象
        var ctx = context.getContext("2d");
        var video = document.querySelector("video")
        // 点击按钮==视频播放
        var btn = document.querySelector("#btn")
        btn.onclick = function () {
            if (video.paused) {
                video.play()
                render()
            }else{
                video.pause()
            }

        }
        let img=new Image()
        img.src="./pat.png"
        function render() {
            ctx.drawImage(video, 0, 0, 600, 400)
            // 添加水印
            ctx.drawImage(img, 500, 350, 100, 50)
            requestAnimationFrame(render)
        }

    </script>

2.6、文字绘制与对齐

填充文字: fillText(文本,起点x,起点y,文字最大宽度)

气泡文字: strokeText(文本,起点x,起点y,文字最大宽度)

ctx.strokeStyle = "pink"
ctx.font = "100px Microsoft YaHei"
        // 填充文字
        // fillText(文本,起点x,起点y,文字最大宽度)
ctx.fillText("Hello world!", 200, 300, 400)
        // 文本对齐选项(textAlign,start,end,left,right,center)
ctx.textAlign = 'center'
        // 文本基线对齐(textBaseline,middle,top,bottom,alphabetic)
ctx.textBaseline = 'middle'
        ctx.font = "50px serif";
ctx.strokeText("Hello world", 300, 200);
        ctx.arc(300, 200, 5, 0, 2 * Math.PI)
        ctx.fill()
    // 预测文本宽度
let text=ctx.measureText("你CDC")
        console.log(text);//width: 125

2.7、旋转、位移、缩放

rotate旋转(角度)、translate位移、scale缩放(倍数)

// scale缩放(倍数)
        ctx.fillRect(0, 0, 50, 50)
// translate位移
        ctx.translate(100, 100)
        ctx.scale(5, 2)
        ctx.fillRect(0, 0, 50, 50)
// rotate旋转
        ctx.rotate(Math.PI / 6)
        ctx.fillRect(0, 0, 500, 50)

三、高级应用

3.1、合成图像模式实现刮刮卡

<style>
    * {
        margin: 0;
        padding: 0;
    }

    #MyCanvas {
        border: 1px solid black;
        position: absolute;
        left: 0;
        top: 0;
        z-index: 10;
    }

    #ggk {
        width: 600px;
        height: 400px;
        font-size: 30px;
        font-weight: 900;
        text-align: center;
        line-height: 400px;
        overflow: hidden;
        position: absolute;
        left: 0;
        top: 0;
    }
</style>
    <div id="ggk">谢谢惠顾</div>
    <canvas id="MyCanvas" width="600" height="400"></canvas>
<script>
        // 1.找到画布
        var context = document.getElementById("MyCanvas");
        // 2.获取画笔,上下文对象
        var ctx = context.getContext("2d");
        let img = new Image()
        img.src = './mb.png'
        img.onload = function () {
            ctx.drawImage(img, 0, 0, 600, 400);//蒙版图片加载
        }
        // 刮刮卡
        var isDraw = false;
        context.onmousedown = function () {
            isDraw = true
        }
        context.onmouseup = function () {
            isDraw = false
        }
        context.onmousemove = function (e) {
            if (isDraw) {
                var x = e.pageX
                var y = e.pageY
                ctx.globalCompositeOperation = "destination-out"
                ctx.arc(x, y, 20, 0, 2 * Math.PI)
                ctx.fill()
            }
        }
        // 抽中
        let random = Math.random()
        if(random<0.1){
            var ggkDiv=document.querySelector("#ggk")
            ggkDiv.innerHTML="恭喜您中奖了!"
        }
</script>

3.2、裁剪路径

clip(路径值)

        var heartPath = new Path2D()
        heartPath.moveTo(300, 200);
        heartPath.bezierCurveTo(350, 150, 400, 200, 300, 250);
        heartPath.bezierCurveTo(200, 200, 250, 150, 300, 200);
ctx.clip(heartPath)
        ctx.fill(heartPath)
let img = new Image()
img.src = './bigs.png'
img.onload = function () {
            ctx.drawImage(img, 0, 0, 600, 400)
            ctx.lineWidth = 10
            ctx.stroke(heartPath)
        }

3.3、状态的保存与恢复

save():保存   restore():恢复

 这个操作就像“栈”一样,最后一次保存的是绿色,所以先恢复的是绿色

        ctx.fillStyle = 'red'
        ctx.fillRect(0, 0, 50, 50)
ctx.save();//红色保存
        ctx.fillStyle = 'green'
        ctx.fillRect(50, 50, 50, 50)
ctx.save();//绿色保存
        ctx.fillStyle = 'blue'
        ctx.fillRect(100, 100, 50, 50)
ctx.restore();//绿色恢复
        ctx.fillRect(150,150, 50, 50)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值