canvas画布标签详解

介绍

作用:用于绘制图像。 元素本身并没有绘制能力(它仅仅是图形的容器)

<canvas> 标记和 SVG 以及 VML 之间的差异?

<canvas> 标记和 SVG 以及 VML 之间的一个重要的不同是,<canvas> 有一个基于 JavaScript 的绘图 API,而 SVG 和 VML 使用一个 XML 文档来描述绘图。

这两种方式在功能上是等同的,任何一种都可以用另一种来模拟。从表面上看,它们很不相同,可是,每一种都有强项和弱点。例如,SVG 绘图很容易编辑,只要从其描述中移除元素就行。

要从同一图形的一个 <canvas> 标记中移除元素,往往需要擦掉绘图重新绘制它。

 基本API讲解:

<body>
    <!-- 创建一个画布-->
	<canvas id="can" width="500px" height="500px" style="border: 1px solid red;">aa</canvas>
</body>

<script>
	var canvas = document.getElementById('can');  // 获取画布
    var context = canvas.getContext('2d');  // 相对于准备画笔

    /* 绘制矩形 */
    context.fillStyle = 'red'  // 填充颜色
    context.fillRect(10,30,100,100)  // 画出一个有填充颜色的矩形框(默认黑色)
    context.strokeStyle='green'  // 设置线的颜色
    context.strokeRect(50,50,150,150)  // 画出一个无填充颜色的矩形框
    context.scale(2,2)  // 缩放。(x倍数,y倍数)
    context.save()  // 保存当前画布的状态
    context.restore() // 返回上一次save()状态
    context.clearRect(20,40,30,20)  //清空给矩形内的指定像素。(x,y,w,h)


    /* 不规则图形 */
    context.beginPath()    // 创建一个新路径
    context.moveTo(100,50)   //定义初始位置的 (向右增大,向下增大)
    context.lineTo(80,150)   //连接端点的 (定义一个点到初始点)
    context.lineTo(40,150)   //连接端点的 (定义一个点到初始点)
    lineCap='round'   //端点形状
    context.strokeStyle='green'   // 线的颜色
    context.lineWidth='5';   //路径(线)的大小
    context.closePath()  // 封闭路径(线)
    context.stroke()  // 路径转为轮廓(线显示或描边)
    context.fill()  // 填充颜色。需要设置这个才能fillStyle填充颜色
    

    /* 圆形 */
    context.beginPath()    // 创建一个新路径
    context.arc(60,60,50,0,Math.PI*2,false)  //(x,y,圆的大小,开始角,结束角,顺时针false逆时针true。可省略)
    context.closePath()  // 封闭路径(线)
    context.stroke()   // 路径转为轮廓(线显示或描边)

	
    /* 处理图像 */
    let image = new Image();
    image.src = './3.jpg'
    image.onload = function(){
        context.drawImage(image,100,100) //图像操作能力。可以用于动态的图像合成
    }
    let img = canvas.toDataURL('image/jpg') // 把图像转化为base64格式。(图片类型,图片的质量【0-1】默认值是0.92)
    console.log(img);
	
</script>

drawImage 方法有三种形态:

  • drawImage(image, dx, dy) 在画布指定位置绘制原图
  • drawImage(image, dx, dy, dw, dh) 在画布指定位置上按原图大小绘制指定大小的图
  • drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) 剪切图像,并在画布上定位被剪切的部分

参数    描述
image    规定要使用的图像、画布或视频
sx    可选。开始剪切图片的 x 坐标位置
sy    可选。开始剪切图片的 y 坐标位置
sw    可选。被剪切图像的宽度(就是裁剪之前的图片宽度,这里的宽度若小于图片的原宽。则图片多余部分被剪掉;若大于,则会以空白填充)
sh    可选。被剪切图像的高度(就是裁剪之前的图片高度)
dx    在画布上放置图像的 x 坐标位置
dy    在画布上放置图像的 y 坐标位置
dw    可选。要使用的图像的宽度(就是裁剪之后的图片高度,放大或者缩放)
dh    可选。要使用的图像的高度(就是裁剪之后的图片高度,放大或者缩放)

精选小练习

1、基础练习:

<body>
    <canvas id="can" width="400px" height="300px" style="border: 1px solid red;"></canvas><br>
    <button id="btnRect">绘制矩形</button>
    <button id="scale">扩大2倍</button>
    <button id="save">保存状态</button>
    <button id="restore">恢复上一次状态</button>
</body>

</html>
<!-- <script>
    // 写法一
    window.addEventListener('load', init, false)

    function $(aa) {
        return document.getElementById(aa)
    }

    let ctx

    function init() {
        var canvas = document.getElementById('can')
        ctx = canvas.getContext('2d')
        btnRect = $("btnRect");
        cale = $("scale");
        save = $('save');
        restore = $("restore");
        btnRect.addEventListener("click", randomX, false);
        // btnRect.addEventListener("click", randomX(), false); 这样写,相当于在这里直接调用了
        scale.addEventListener("click",ScaleBox,false);
        save.addEventListener("click", saveBox, false);
        restore.addEventListener("click", restoreBox, false);
    }

    function randomX() {
        var x = parseInt(Math.random() * 100);
        var y = parseInt(Math.random() * 100);
        ctx.fillStyle = 'rgba(11,22,185,1)';
        ctx.fillRect(x, y, 50, 50);
    }
    function ScaleBox() {
        ctx.scale(2, 2);
    }
    function saveBox() {
        ctx.save();
    }
    function restoreBox() {
        ctx.restore();
    }
</script>
 -->

<script>
    // 写法二。触发:绘制矩形---保存状态---扩大两倍---返回上一层状态
    function $(id) {
        return document.getElementById(id)
    }
    var canvas = document.getElementById('can')
    var ctx = canvas.getContext('2d')

    let RANDOM = 200 // 随机数最大值

    $('btnRect').addEventListener('click', () => {
        let x = parseInt(Math.random() * RANDOM)
        let y = parseInt(Math.random() * RANDOM)
        ctx.fillRect(x, y, 50, 50)
    })

    $('scale').addEventListener('click', () => {
        RANDOM = 150
        ctx.scale(2, 2)
    })

    $('save').addEventListener('click', () => {
        ctx.save() // 保存当前状态
    })

    $('restore').addEventListener('click', () => {
        console.log('restore');
        // RANDOM = 200
        ctx.restore()
        // ctx.save()  // 保存当前状态
    })

</script>

2、小练习二:小球触碰边缘弹射

<body>
    <canvas id="can" width="350px" height="250px" style="border: 1px solid red;">aa</canvas>
</body>

<!-- <script>  写法一:
    var canvas = document.getElementById('can');
    var ctx = canvas.getContext('2d');

    var x = 10
    var y = 10
    var RANDOM = 10
    var WIDTH = canvas.width    // Z整个画布的宽度 
    var HEIGHT = canvas.height  // 整个画布的高度
    var direction = 1  // 方向
    var xx = 1  // x的正方向
    var yy = 1  // y的正方向

    setInterval(() => {
        if (x < RANDOM || x >= WIDTH - RANDOM) {
            console.log(xx, x);
            // 执行 x>=WIDTH-RANDOM。 正数*负数=负数(-1)
            // 执行 x < RANDOM。      负数*负数=正数(1)
            xx *= -1
        }
        if (y < RANDOM || y >= HEIGHT - RANDOM) {
            yy *= -1
        }

        x = x + xx
        y = y + yy
        ctx.clearRect(0, 0, WIDTH, HEIGHT)  // 清空画布
        ctx.beginPath()
        ctx.arc(x, y, RANDOM, 0, Math.PI * 2, false) //
        ctx.closePath()  // 封闭路径(线)
        ctx.fillStyle = 'red'
        ctx.fill()
    }, 10)
</script> -->

<script>  // 写法二
    var canvas = document.getElementById('can');
    var ctx = canvas.getContext('2d');

    var x = 10
    var y = 10
    var RANDOM = 10
    var WIDTH = canvas.width    // Z整个画布的宽度 
    var HEIGHT = canvas.height  // 整个画布的高度
    var direction = 1  // 方向
    setInterval(() => {
        if (direction == 1) { // 运动方向
            x++
            y++
            if(y >= HEIGHT-RANDOM){  // 小球移动到最下面时(底部),进入判断
                direction = 2
            }
            if(x >= WIDTH-RANDOM){
                direction = 4
            }
        } else if (direction == 2) {
            x++
            y--
            if(x >= WIDTH-RANDOM){
                direction = 3
            }
            if(y <= RANDOM){
                direction = 1
            }
        } else if (direction == 3) {
            x--
            y--
            if(y <= RANDOM){
                direction = 4
            }
            if(x <= RANDOM){
                direction = 2
            }
        } else if (direction == 4) {
            x--
            y++
            if(x <= RANDOM){
                direction = 1
            }
            if(y >= HEIGHT-RANDOM){
                direction = 3
            }
        }
        ctx.clearRect(0, 0, WIDTH, HEIGHT)  // 清空画布
        ctx.beginPath()
        ctx.arc(x, y, RANDOM, 0, Math.PI * 2, false) //
        ctx.closePath()  // 封闭路径(线)
        ctx.fillStyle = 'red'
        ctx.fill()
    }, 1)
</script>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值