当前位置: 首页 > article >正文

详细讲一下Canvas标签的基础使用和应用场景

最近收到私信,发现很多同学对Canvas标签非常不熟悉,甚至连听都没听过,这篇文章就带大家好好了解一下这个原生标签Canvas。

1.基础设置

<!-- 创建Canvas元素 -->
<!-- width和height设置画布大小,不要用CSS设置,会导致画面模糊 -->
<canvas id="myCanvas" width="500" height="300"></canvas>

<script>
// 获取Canvas元素
const canvas = document.getElementById('myCanvas');
// 获取绘图上下文,'2d'表示二维绘图
const ctx = canvas.getContext('2d');
</script>

2. 基础图形绘制

/**
 * 基础图形绘制类
 * 包含最常用的绘图方法
 */
class BasicDrawing {
    constructor(canvasId) {
        // 初始化画布和上下文
        this.canvas = document.getElementById(canvasId);
        this.ctx = this.canvas.getContext('2d');
    }

    // 绘制矩形
    drawRectangle() {
        // 设置填充颜色
        this.ctx.fillStyle = 'red';
        
        // 绘制填充矩形
        // 参数含义:x坐标, y坐标, 宽度, 高度
        this.ctx.fillRect(10, 10, 100, 80);

        // 设置边框颜色
        this.ctx.strokeStyle = 'blue';
        // 设置边框宽度
        this.ctx.lineWidth = 2;
        
        // 绘制边框矩形
        this.ctx.strokeRect(130, 10, 100, 80);
    }

    // 绘制圆形
    drawCircle() {
        // 开始一个新的绘制路径
        this.ctx.beginPath();
        
        // 绘制圆形
        // 参数:圆心x, 圆心y, 半径, 开始角度, 结束角度
        this.ctx.arc(50, 50, 30, 0, Math.PI * 2);
        
        // 设置填充颜色
        this.ctx.fillStyle = 'green';
        // 填充
        this.ctx.fill();
    }

    // 绘制线条
    drawLine() {
        this.ctx.beginPath();
        // 移动到起点
        this.ctx.moveTo(10, 10);
        // 画线到终点
        this.ctx.lineTo(200, 200);
        
        // 设置线条颜色
        this.ctx.strokeStyle = 'black';
        // 设置线条宽度
        this.ctx.lineWidth = 2;
        // 绘制线条
        this.ctx.stroke();
    }
}

// 使用示例
const drawing = new BasicDrawing('myCanvas');
drawing.drawRectangle();

3. 动画效果

/**
 * 简单动画示例
 * 展示如何制作移动的小球
 */
class SimpleAnimation {
    constructor(canvasId) {
        this.canvas = document.getElementById(canvasId);
        this.ctx = this.canvas.getContext('2d');
        
        // 小球的初始位置和速度
        this.x = 50;
        this.y = 50;
        this.speed = 2;
        this.radius = 20;
    }

    // 绘制小球
    drawBall() {
        this.ctx.beginPath();
        this.ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
        this.ctx.fillStyle = 'red';
        this.ctx.fill();
    }

    // 更新小球位置
    update() {
        // 移动小球
        this.x += this.speed;

        // 如果碰到边界就反弹
        if (this.x + this.radius > this.canvas.width || this.x - this.radius < 0) {
            this.speed = -this.speed;
        }
    }

    // 开始动画
    animate() {
        // 清除整个画布
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
        
        // 绘制和更新
        this.drawBall();
        this.update();

        // 请求下一帧动画
        // requestAnimationFrame比setTimeout更适合动画
        requestAnimationFrame(() => this.animate());
    }
}

// 使用示例
const animation = new SimpleAnimation('myCanvas');
animation.animate();

4.简单的画板功能

/**
 * 简单画板
 * 允许用户用鼠标在画布上绘画
 */
class SimpleDrawingBoard {
    constructor(canvasId) {
        this.canvas = document.getElementById(canvasId);
        this.ctx = this.canvas.getContext('2d');
        
        // 是否正在绘制
        this.isDrawing = false;
        
        // 初始化画板设置
        this.initializeBoard();
    }

    // 初始化画板
    initializeBoard() {
        // 设置线条样式
        this.ctx.strokeStyle = 'black';
        this.ctx.lineWidth = 2;
        this.ctx.lineCap = 'round'; // 让线条末端圆润

        // 添加鼠标事件监听
        this.canvas.addEventListener('mousedown', (e) => this.startDrawing(e));
        this.canvas.addEventListener('mousemove', (e) => this.draw(e));
        this.canvas.addEventListener('mouseup', () => this.stopDrawing());
        this.canvas.addEventListener('mouseout', () => this.stopDrawing());
    }

    // 开始绘制
    startDrawing(e) {
        this.isDrawing = true;
        // 移动到鼠标位置
        this.ctx.beginPath();
        this.ctx.moveTo(
            e.clientX - this.canvas.offsetLeft,
            e.clientY - this.canvas.offsetTop
        );
    }

    // 绘制
    draw(e) {
        if (!this.isDrawing) return;
        
        // 画线到当前鼠标位置j
        this.ctx.lineTo(
            e.clientX - this.canvas.offsetLeft,
            e.clientY - this.canvas.offsetTop
        );
        this.ctx.stroke();
    }

    // 停止绘制
    stopDrawing() {
        this.isDrawing = false;
    }

    // 清除画布
    clear() {
        this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    }
}

// 使用示例
const drawingBoard = new SimpleDrawingBoard('myCanvas');

// 添加清除按钮
const clearButton = document.createElement('button');
clearButton.textContent = '清除画布';
clearButton.onclick = () => drawingBoard.clear();
document.body.appendChild(clearButton);

5.图片处理

/**
 * 图片处理类
 * 展示如何在Canvas中处理图片
 */
class ImageProcessor {
    constructor(canvasId) {
        this.canvas = document.getElementById(canvasId);
        this.ctx = this.canvas.getContext('2d');
    }

    // 加载并显示图片
    loadImage(imageUrl) {
        // 创建新的图片对象
        const img = new Image();
        
        // 图片加载完成后的处理
        img.onload = () => {
            // 将图片绘制到画布上
            this.ctx.drawImage(img, 0, 0, this.canvas.width, this.canvas.height);
        };
        
        // 设置图片源
        img.src = imageUrl;
    }

    // 添加简单的灰度效果
    applyGrayscale() {
        // 获取画布上的图像数据
        const imageData = this.ctx.getImageData(
            0, 0, 
            this.canvas.width, 
            this.canvas.height
        );
        const data = imageData.data;

        // 处理每个像素
        for (let i = 0; i < data.length; i += 4) {
            // 计算灰度值
            const gray = (data[i] + data[i + 1] + data[i + 2]) / 3;
            
            // 设置RGB值为灰度值
            data[i] = gray;     // R
            data[i + 1] = gray; // G
            data[i + 2] = gray; // B
            // data[i + 3] 是透明度,保持不变
        }

        // 将处理后的图像数据放回画布
        this.ctx.putImageData(imageData, 0, 0);
    }
}

// 使用示例
const processor = new ImageProcessor('myCanvas');
processor.loadImage('path/to/image.jpg');

// 添加灰度效果按钮
const grayscaleButton = document.createElement('button');
grayscaleButton.textContent = '添加灰度效果';
grayscaleButton.onclick = () => processor.applyGrayscale();
document.body.appendChild(grayscaleButton);


 

使用建议:

1.性能优化

  • 避免在循环中重复获取canvas和context
  • 使用requestAnimationFrame而不是setInterval
  • 适当使用缓存

2.常见问题解决

  • 画布模糊:使用正确的尺寸设置
  • 图片跨域:确保图片允许跨域访问
  • 性能问题:控制重绘频率

3.适用场景

  • 简单游戏开发
  • 图表绘制
  • 图片处理
  • 签名板
  • 动画效果

4. 初学者注意事项

  • 先掌握基础图形绘制
  • 理解坐标系统
  • 多练习动画效果
  • 从简单项目开始

5.进阶方向

  • 复杂动画效果
  • 碰撞检测
  • 粒子效果
  • 3D效果(使用WebGL)

http://www.kler.cn/a/468801.html

相关文章:

  • 【C++面向对象——类的多态性与虚函数】编写教学游戏:认识动物(头歌实践教学平台习题)【合集】
  • 【学习笔记】数据结构(十)
  • 小程序26-事件绑定和事件对象
  • 【FlutterDart】 listView.builder例子二(14 /100)
  • 产品经理-竞品分析
  • 前端学习DAY31(子元素溢出父元素)
  • 集成方案:基于慧集通的某客户多系统间集成简略方案(致远OA、NCC高级版、三方物业系统、发票税务系统等)
  • 模拟出一个三维表面生成表面点,计算体积,并处理边界点
  • 系统架构师考试-CBSE基于构件的软件工程
  • 前端开发语言涉及到 的注解(Annotations)
  • vue3 vite 使用 代理转发
  • 阿赵的MaxScript学习笔记分享十六《MaxScript和WinForm交互》
  • 【Python系列】Python 中的 `enumerate` 函数及其应用
  • 基于区块链的共享算力系统概念方案
  • Django Admin 以管理 AWS Lambda 函数
  • 深度信念网络 (Deep Belief Network, DBN) 算法详解与PyTorch实现
  • 性能测试04|JMeter:连接数据库、逻辑控制器、定时器
  • Linux中操作中的无痕命令history技巧
  • Sonic:开源Go语言开发的高性能博客平台
  • 第五届神经网络、信息与通信工程国际学术会议(NNICE 2025)
  • Java与AI:构建智能应用的强大组合
  • git使用指南-实践-搭建git私服
  • 【最新版】智慧小区物业管理小程序源码+uniapp全开源
  • 【每日学点鸿蒙知识】模拟器开启网络、长时任务、兼容性测试支持、丢帧定位、SO中访问rawfile等
  • 操作系统大题整理
  • 【Android项目学习】2.抖音二级评论