• HTML5 Canvas 绘图教程二


    在本教程中,我们将探讨 canvas 的高级用法,包括复杂的绘图 API、坐标系统和变换操作、平滑动画技术以及复杂应用和游戏开发的实践。

    1. 绘图 API 高级方法

    1.1 二次贝塞尔曲线 (quadraticCurveTo)

    二次贝塞尔曲线需要两个点:一个控制点和一个结束点。

    // 获取 canvas 元素和 2d 上下文
    var canvas = document.getElementById('myCanvas');
    var ctx = canvas.getContext('2d');
    
    // 开始绘制路径
    ctx.beginPath();
    ctx.moveTo(50, 50); // 起点
    ctx.quadraticCurveTo(200, 100, 50, 200); // 控制点(200,100),结束点(50,200)
    ctx.strokeStyle = 'blue';
    ctx.stroke(); // 绘制路径
    
    1.2 三次贝塞尔曲线 (bezierCurveTo)

    三次贝塞尔曲线需要三个点:两个控制点和一个结束点。

    // 开始绘制路径
    ctx.beginPath();
    ctx.moveTo(50, 250); // 起点
    ctx.bezierCurveTo(150, 200, 200, 300, 300, 250); // 控制点1(150,200),控制点2(200,300),结束点(300,250)
    ctx.strokeStyle = 'red';
    ctx.stroke(); // 绘制路径
    

    2. 坐标系统和变换操作

    2.1 平移

    通过 translate 方法可以移动 canvas 的坐标系统。

    // 平移坐标系
    ctx.translate(100, 100);
    
    // 在新的坐标系中绘制矩形
    ctx.fillStyle = 'green';
    ctx.fillRect(0, 0, 50, 50);
    
    2.2 旋转

    通过 rotate 方法可以旋转 canvas 的坐标系统。

    // 重置变换矩阵
    ctx.resetTransform();
    // 平移到旋转中心
    ctx.translate(150, 150);
    // 旋转45度(弧度制,45度=PI/4)
    ctx.rotate(Math.PI / 4);
    
    // 绘制旋转后的矩形
    ctx.fillStyle = 'purple';
    ctx.fillRect(-25, -25, 50, 50); // 以旋转中心为原点绘制
    
    2.3 缩放

    通过 scale 方法可以缩放 canvas 的坐标系统。

    // 重置变换矩阵
    ctx.resetTransform();
    // 平移到缩放中心
    ctx.translate(250, 250);
    // 缩放
    ctx.scale(2, 2); // 宽高都缩放2倍
    
    // 绘制缩放后的矩形
    ctx.fillStyle = 'orange';
    ctx.fillRect(-25, -25, 50, 50); // 以缩放中心为原点绘制
    

    3. 平滑动画技术

    通过 requestAnimationFrame 方法可以实现平滑动画。

    3.1 简单动画示例
    var x = 0;
    
    function draw() {
        // 清除 canvas
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    
        // 绘制一个移动的矩形
        ctx.fillStyle = 'blue';
        ctx.fillRect(x, 50, 50, 50);
    
        // 更新 x 坐标
        x += 1;
    
        // 请求下一帧
        requestAnimationFrame(draw);
    }
    
    // 启动动画
    draw();
    

    4. 复杂应用和游戏开发

    4.1 碰撞检测

    在游戏开发中,碰撞检测是一个重要的概念。这里是一个简单的碰撞检测示例。

    var ballRadius = 10;
    var x = canvas.width / 2;
    var y = canvas.height - 30;
    var dx = 2;
    var dy = -2;
    
    function drawBall() {
        ctx.beginPath();
        ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
        ctx.fillStyle = "#0095DD";
        ctx.fill();
        ctx.closePath();
    }
    
    function draw() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        drawBall();
    
        // 碰撞检测
        if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
            dx = -dx;
        }
        if (y + dy > canvas.height - ballRadius || y + dy < ballRadius) {
            dy = -dy;
        }
    
        x += dx;
        y += dy;
    
        requestAnimationFrame(draw);
    }
    
    draw();
    
    4.2 简单的键盘控制游戏

    通过结合键盘事件处理,可以开发简单的键盘控制游戏。

    var paddleHeight = 10;
    var paddleWidth = 75;
    var paddleX = (canvas.width - paddleWidth) / 2;
    var rightPressed = false;
    var leftPressed = false;
    
    document.addEventListener("keydown", keyDownHandler, false);
    document.addEventListener("keyup", keyUpHandler, false);
    
    function keyDownHandler(e) {
        if (e.key == "Right" || e.key == "ArrowRight") {
            rightPressed = true;
        } else if (e.key == "Left" || e.key == "ArrowLeft") {
            leftPressed = true;
        }
    }
    
    function keyUpHandler(e) {
        if (e.key == "Right" || e.key == "ArrowRight") {
            rightPressed = false;
        } else if (e.key == "Left" || e.key == "ArrowLeft") {
            leftPressed = false;
        }
    }
    
    function drawPaddle() {
        ctx.beginPath();
        ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
        ctx.fillStyle = "#0095DD";
        ctx.fill();
        ctx.closePath();
    }
    
    function draw() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        drawPaddle();
    
        if (rightPressed && paddleX < canvas.width - paddleWidth) {
            paddleX += 7;
        } else if (leftPressed && paddleX > 0) {
            paddleX -= 7;
        }
    
        requestAnimationFrame(draw);
    }
    
    draw();
    
  • 相关阅读:
    JavaWeb篇_01——JavaEE简介【面试常问】
    网络原理---封装和分用
    Web开发-基础知识扫盲
    事务(包含ACID)
    混乱的代码是技术债吗
    Git上传文件代码到GitHub
    [附源码]计算机毕业设计SpringBoot四川景区管理系统
    如何突破测试/开发程序员思维?一种不一样的感觉......
    1688官方接口|接入参数|返回说明|供应链必备接口|跨境属性……
    psql 模式(SCHEMA)
  • 原文地址:https://blog.csdn.net/imdeity/article/details/139425148