Canvas 和 SVG 的高级使用与性能优化

在前端开发中,Canvas 和 SVG 是两种强大的绘图技术。本文将深入探讨如何在实际应用中使用 Canvas 和 SVG 绘制基本图形、添加交互事件、实现动画效,特别是如何优化性能和实现高级功能。

实际应用

如何在 Canvas 上绘制一个矩形?

使用 getContext('2d') 获取 2D 绘图上下文,然后使用 fillRect(x, y, width, height) 方法绘制矩形。

示例代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Canvas Rectangle</title>
    <style>
        #myCanvas {
            border: 1px solid black;
        }
    </style>
</head>
<body>
    <h1>Canvas Rectangle</h1>
    <canvas id="myCanvas" width="200" height="200"></canvas>
    <script>
        const canvas = document.getElementById('myCanvas');
        const ctx = canvas.getContext('2d');
        ctx.fillRect(10, 10, 100, 50);
    </script>
</body>
</html>

效果:

如何在 SVG 中绘制一个圆形?

使用 <circle cx="50" cy="50" r="40" /> 元素,其中 cxcy 定义圆心坐标,r 定义半径。

示例代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SVG Circle</title>
</head>
<body>
    <h1>SVG Circle</h1>
    <svg width="200" height="200">
        <circle cx="50" cy="50" r="40" fill="blue" />
    </svg>
</body>
</html>

效果:

如何在 Canvas 上绘制文本?

使用 fillText(text, x, y) 方法,其中 text 是要绘制的文本,xy 是文本的起始坐标。

示例代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Canvas Text</title>
</head>
<body>
    <canvas id="myCanvas" width="400" height="400" style="border:1px solid #000000;"></canvas>
    <script>
        const canvas = document.getElementById('myCanvas');
        const ctx = canvas.getContext('2d');
        ctx.fillStyle = 'black';
        ctx.font = '20px Arial';
        ctx.fillText('Hello Canvas', 50, 200);
    </script>
</body>
</html>

如何在 SVG 中添加交互事件?

可以直接在 SVG 元素上添加事件监听器,例如 <rect onclick="handleClick()" />

示例代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SVG Interaction</title>
    <script>
        function handleClick() {
            alert('Rectangle clicked!');
        }
    </script>
</head>
<body>
    <svg width="400" height="400" style="border:1px solid #000000;">
        <rect x="50" y="50" width="150" height="100" fill="blue" onclick="handleClick()" />
    </svg>
</body>
</html>

效果:

性能优化

如何优化 Canvas 的绘图性能?

  1. 使用离屏 Canvas:进行复杂图形的预渲染,减少重绘次数。
  2. 使用 requestAnimationFrame,而不是SetInterval:进行动画更新,提供更平滑的动画效果。
  3. 减少重绘区域:只重绘需要更新的区域,而不是整个画布。
  4. 批量绘制:将多个绘图操作合并为一个批量操作,减少绘图调用的开销。

示例代码

javascript 复制代码
function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // 绘制图形
    // ...
    requestAnimationFrame(draw);
}
requestAnimationFrame(draw);

其他例子在这里有讲:juejin.cn/post/744071...

如何优化 SVG 的渲染性能?

  1. 减少 DOM 元素的数量:尽量减少 SVG 中的元素数量。
  2. 使用 <use> 元复用图形:避免重复定义相同的图形。
  3. 避免频繁的 DOM 操作:尽量减少对 SVG DOM 的频繁操作。
  4. 使用 CSS 动画代替 JavaScript 动画:提高动画性能。

示例代码

html 复制代码
<svg width="400" height="400" style="border:1 solid #000000;">
    <defs>
        <circle id="myCircle" cx="50" cy="50" r="40" fill="red" />
    </defs>
    <use xlink:href="#myCircle" x="0" y="0" />
    <use xlink:href="#myCircle" x="100" y="100" />
</svg>

高级使用场景

如何在 Canvas 上实现动画效果?

使用 requestAnimationFrame 方法进行动画帧的更新,在每一帧中清除画布并重新绘制图形。

示例代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Canvas Animation</title>
</head>
<body>
    <canvas id="myCanvas" width="400" height="400" style="border:1px solid #000000;"></canvas>
    <script>
        const canvas = document.getElementById('myCanvas');
        const ctx = canvas.getContext('2d');
        let x = 0;

        function draw() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.fillStyle = 'blue';
            ctx.fillRect(x, 50, 50, 50);
            x += 1;
            if (x > canvas.width) x = 0;
            requestAnimationFrame(draw);
        }

        requestAnimationFrame(draw);
    </script>
</body>
</html>

如何在 SVG 中实现渐变效果?

使用 <linearGradient><radialGradient> 元素定义渐变,然后在图形元素中使用 fill="url(#gradientId)" 应用渐变。

示例代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SVG Gradient</title>
</head>
<body>
    <h1>SVG Gradient</h1>
    <svg width="200" height="200">
        <defs>
            <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
                <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
                <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
            </linearGradient>
        </defs>
        <rect width="200" height="200" fill="url(#grad1)" />
    </svg>
</body>
</html>

效果:

如何在 Canvas 上处理图像?

使用 drawImage(image, x, y, width, height) 方法绘制图像,可以进行裁剪、缩放等操作。

示例代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Canvas Image</title>
</head>
<body>
    <canvas id="myCanvas" width="400" height="400" style="border:1px solid #000000;"></canvas>
    <script>
        const canvas = document.getElementById('myCanvas');
        const ctx = canvas.getContext('2d');
        const img = new Image();
        img.onload = function() {
            ctx.drawImage(img, 50, 50, 300, 300);
        };
        img.src = 'https://example.com/image.jpg';
    </script>
</body>
</html>

如何在 SVG 中使用滤镜效果?

使用 <filter> 元素定义滤镜效果,然后在图形元素中使用 filter="url(#filterId)" 应用滤镜。

示例代码

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SVG Filter</title>
</head>
<body>
    <h1>SVG Filter</h1>
    <svg width="200" height="200">
        <defs>
            <filter id="blurFilter">
                <feGaussianBlur in="SourceGraphic" stdDeviation="5" />
            </filter>
        </defs>
        <rect width="200" height="200" fill="blue" filter="url(#blurFilter)" />
    </svg>
</body>
</html>

效果:

相关推荐
乐多_L42 分钟前
使用vue3框架vue-next-admin导出表格excel(带图片)
前端·javascript·vue.js
南望无一1 小时前
React Native 0.70.x如何从本地安卓源码(ReactAndroid)构建
前端·react native
Mike_188702783511 小时前
1688代采下单API接口使用指南:实现商品采集与自动化下单
前端·python·自动化
鲨鱼辣椒️面1 小时前
HTML视口动画
前端·html
一小路一1 小时前
Go Web 开发基础:从入门到实战
服务器·前端·后端·面试·golang
堇舟1 小时前
HTML第一节
前端·html
纯粹要努力1 小时前
前端跨域问题及解决方案
前端·javascript·面试
小刘不知道叫啥1 小时前
React源码揭秘 | 启动入口
前端·react.js·前端框架
kidding7231 小时前
uniapp引入uview组件库(可以引用多个组件)
前端·前端框架·uni-app·uview
合法的咸鱼2 小时前
uniapp 使用unplugin-auto-import 后, vue文件报红问题
前端·vue.js·uni-app