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

深入 SVG:矢量图形、滤镜与动态交互开发指南

1.SVG 详细介绍

SVG(Scalable Vector Graphics) 是一种基于 XML 的矢量图形格式,用于描述二维图形。


1. 命名空间 (Namespace)

  • 命名空间 URIhttp://www.w3.org/2000/svg

  • 用途:在 XML 或 XHTML 中区分不同标记语言的元素。

  • 声明方式

    <svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><!-- SVG 内容 -->
    </svg>

2. SVG API

  • DOM API:通过 JavaScript 操作 SVG 元素。

    • 创建元素:document.createElementNS(namespaceURI, tagName)

    • 示例:

      const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
      svg.setAttribute("width", "100");
      svg.setAttribute("height", "100");
      document.body.appendChild(svg);
  • SVG DOM 接口:如 SVGElementSVGRectElementSVGPathElement 等,提供特定元素的属性和方法。

  • 动画 API:支持 SMIL(已部分弃用)、CSS 动画或 JavaScript 动画库(如 GSAP)。


3. 常用 SVG 代码示例

示例 3.1 - 基本形状

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SVG 基本形状</title>
</head>
<body><svg width="400" height="300"><!-- 矩形 --><rect x="10" y="10" width="50" height="30" fill="blue" stroke="black" stroke-width="2"/><!-- 圆形 --><circle cx="100" cy="50" r="30" fill="red"/><!-- 椭圆 --><ellipse cx="200" cy="50" rx="40" ry="20" fill="green"/><!-- 线条 --><line x1="10" y1="100" x2="150" y2="100" stroke="purple" stroke-width="3"/><!-- 折线 --><polyline points="10,150 50,120 90,180" fill="none" stroke="orange"/><!-- 多边形 --><polygon points="200,150 250,120 300,180" fill="yellow" stroke="brown"/></svg>
</body>
</html>

示例 3.2 - 路径(Path)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SVG 路径</title>
</head>
<body><svg width="200" height="200"><path d="M10 80 Q 100 10 190 80 T 370 80"fill="none" stroke="black" stroke-width="2"/></svg>
</body>
</html>

示例 3.3 - 文本

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SVG 文本</title>
</head>
<body><svg width="300" height="100"><text x="20" y="30" font-family="Arial" font-size="20" fill="navy">SVG 文本示例</text></svg>
</body>
</html>

示例 3.4 - 渐变与图案

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SVG 渐变与图案</title>
</head>
<body><svg width="200" height="200"><defs><linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#ff0000"/><stop offset="100%" stop-color="#0000ff"/></linearGradient><pattern id="pattern1" width="20" height="20" patternUnits="userSpaceOnUse"><rect width="10" height="10" fill="#00ff00"/></pattern></defs><rect x="10" y="10" width="100" height="100" fill="url(#grad1)"/><circle cx="150" cy="150" r="30" fill="url(#pattern1)"/></svg>
</body>
</html>

示例 3.5 - 滤镜效果

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SVG 滤镜</title>
</head>
<body><svg width="200" height="200"><defs><filter id="blur"><feGaussianBlur in="SourceGraphic" stdDeviation="5"/></filter><filter id="shadow"><feDropShadow dx="5" dy="5" stdDeviation="3" flood-color="rgba(0,0,0,0.5)"/></filter></defs><rect x="20" y="20" width="100" height="100" fill="teal" filter="url(#shadow)"/><circle cx="150" cy="150" r="30" fill="red" filter="url(#blur)"/></svg>
</body>
</html>

示例 3.6 - 动画

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SVG 动画</title><style>.pulse {animation: pulse 1s infinite;}@keyframes pulse {0% { r: 10; }50% { r: 20; }100% { r: 10; }}</style>
</head>
<body><!-- SMIL 动画(部分浏览器已弃用) --><svg width="200" height="200"><circle cx="50" cy="50" r="20" fill="blue"><animate attributeName="cx" from="50" to="150" dur="2s" repeatCount="indefinite"/></circle></svg><!-- CSS 动画 --><svg width="200" height="200"><circle class="pulse" cx="100" cy="100" r="10" fill="green"/></svg>
</body>
</html>

示例 3.7 - 交互性(JavaScript)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SVG 交互</title>
</head>
<body><svg width="200" height="200"><rect id="btn" x="50" y="50" width="100" height="50" fill="gray"/><script>document.getElementById('btn').addEventListener('click', function() {this.setAttribute('fill', '#' + Math.floor(Math.random()*16777215).toString(16));});</script></svg>
</body>
</html>

示例 3.8 - 视口与 viewBox

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SVG 视口</title>
</head>
<body><svg width="200" height="200" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet"><circle cx="50" cy="50" r="40" fill="orange"/></svg>
</body>
</html>

示例 3.9 - 复用元素

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SVG 复用元素</title>
</head>
<body><svg width="300" height="100"><defs><symbol id="icon" viewBox="0 0 24 24"><path d="M12 2L3 9v12h18V9l-9-7z"/></symbol></defs><use href="#icon" x="10" y="10" width="30" height="30" fill="purple"/><use href="#icon" x="100" y="10" width="30" height="30" fill="pink"/></svg>
</body>
</html>

4.SVG 中常见图形元素的属性总结 

1. 矩形 <rect>

属性列表

属性含义示例值
x矩形左上角的 x 坐标"10"
y矩形左上角的 y 坐标"10"
width矩形的宽度"50"
height矩形的高度"30"
rx圆角矩形的水平圆角半径(可选)"5"
ry圆角矩形的垂直圆角半径(可选)"5"
fill填充颜色"blue""#00FF00"
stroke边框颜色"black"
stroke-width边框宽度"2"
stroke-dasharray虚线边框样式(如 "5,3" 表示 5px 实线 + 3px 空白)"5,3"
opacity透明度(0-1)"0.5"
<rect x="10" y="10" width="50" height="30" rx="5" fill="blue" stroke="black" stroke-width="2"/>

2. 圆形 <circle>

属性含义示例值
cx圆心的 x 坐标"100"
cy圆心的 y 坐标"50"
r圆的半径"30"
fill填充颜色"red"
stroke边框颜色(同 <rect>"black"

示例

<circle cx="100" cy="50" r="30" fill="red"/>

3. 椭圆 <ellipse>

属性含义示例值
cx椭圆中心的 x 坐标"200"
cy椭圆中心的 y 坐标"50"
rx水平半径"40"
ry垂直半径"20"
fill填充颜色"green"

示例

<ellipse cx="200" cy="50" rx="40" ry="20" fill="green"/>

4. 线条 <line>

属性含义示例值
x1y1起点坐标"10""100"
x2y2终点坐标"150""100"
stroke线条颜色(必须设置)"purple"
stroke-width线条宽度"3"

示例

<line x1="10" y1="100" x2="150" y2="100" stroke="purple" stroke-width="3"/>

5. 折线 <polyline>

属性含义示例值
points一系列坐标点(格式:x1,y1 x2,y2..."10,150 50,120 90,180"
fill填充颜色(通常设为 "none""none"
stroke线条颜色"orange"

示例

<polyline points="10,150 50,120 90,180" fill="none" stroke="orange"/>

6. 多边形 <polygon>

属性含义示例值
points闭合路径的坐标点(同 <polyline>"200,150 250,120 300,180"
fill填充颜色"yellow"
stroke边框颜色"brown"

示例

<polygon points="200,150 250,120 300,180" fill="yellow" stroke="brown"/>

7. 路径 <path>

属性含义示例值
d路径指令(见下方说明)"M10 80 Q 100 10 190 80"
fill填充颜色("none" 表示不填充)"none"
stroke路径线条颜色"black"

路径指令(d 属性)

  • M x,y:移动到 (x,y)

  • L x,y:画线到 (x,y)

  • Q x1,y1 x,y:二次贝塞尔曲线

  • Z:闭合路径

示例

<path d="M10 80 Q 100 10 190 80 T 370 80" fill="none" stroke="black"/>

8. 文本 <text>

属性含义示例值
xy文本基线起点坐标"20""30"
font-family字体"Arial"
font-size字体大小"20"
fill文本颜色"navy"
text-anchor文本对齐(start/middle/end"middle"

示例

<text x="20" y="30" font-family="Arial" font-size="20" fill="navy">SVG Text</text>

9.通用属性

所有图形元素均可使用以下属性:

属性含义
fill填充颜色(支持颜色名、HEX、RGB等)
stroke边框颜色
stroke-width边框宽度
opacity整体透明度(0-1)
transform变换(如 rotate(45)scale(2)

10.属性总结

  • 基本图形<rect><circle><ellipse><line><polyline><polygon>

  • 高级路径<path> 通过指令实现任意形状。

  • 文本<text> 支持样式和定位。

  • 通用样式fillstrokeopacity 等可跨元素复用。

5.使用 SVG 绘制的移动端常见返回按钮

方案 1:直接使用 <path> 绘制

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SVG 返回按钮</title><style>body {display: flex;justify-content: center;align-items: center;height: 100vh;margin: 0;}.back-button {width: 40px;height: 40px;cursor: pointer;}.back-button:hover path {fill: #007AFF; /* 悬停时变色 */}</style>
</head>
<body><!-- 返回按钮 SVG --><svg class="back-button" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"fill="#000000"  <!-- 默认黑色 -->stroke="none"/></svg>
</body>
</html>

关键点说明

  1. 路径 (d 属性)

    • M20 11:移动到起点 (20, 11)。

    • H7.83:水平画线到 x=7.83。

    • l5.59-5.59:相对绘制斜线(箭头头部)。

    • L12 4:绝对坐标画线到 (12, 4)。

    • l-8 8 8 8:绘制箭头尾部两段线。

    • 1.41-1.41:调整箭头头部细节。

    • H20v-2z:闭合路径。

  2. 交互效果

    • 通过 CSS 悬停 (:hover) 改变颜色。

    • cursor: pointer 表示可点击。

方案 2:使用 <symbol> 复用(适合多个按钮)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SVG 复用返回按钮</title><style>body {display: flex;gap: 20px;justify-content: center;align-items: center;height: 100vh;margin: 0;}.back-button {width: 40px;height: 40px;cursor: pointer;}.back-button:hover use {fill: #FF3B30; /* 悬停红色 */}</style>
</head>
<body><!-- 定义符号 --><svg style="display: none;"><symbol id="back-arrow" viewBox="0 0 24 24"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></symbol></svg><!-- 复用按钮 --><svg class="back-button"><use href="#back-arrow" fill="#000000"/></svg><svg class="back-button"><use href="#back-arrow" fill="#007AFF"/></svg>
</body>
</html>

优势

  • 复用性:通过 <symbol> 定义一次,多处通过 <use> 引用。

  • 灵活样式:每个实例可独立设置颜色/大小。

方案3:其他变体(简洁箭头)

如果需要一个更简单的箭头样式,可以修改 d 属性:

<path d="M15 18l-6-6 6-6" fill="none" stroke="#000" stroke-width="2"/>

效果: 样式的细线箭头。

6.SVG 和 Canvas 的区别

SVG 和 Canvas 是两种完全不同的网页图形技术,它们在实现方式、适用场景和性能特点上有显著差异。以下是它们的核心区别:


1. 基础概念

特性SVGCanvas
类型矢量图形(基于 XML)位图(基于 JavaScript API)
渲染方式保留模式(Retained Mode)立即模式(Immediate Mode)
DOM 支持是(每个图形是 DOM 元素)否(只是一个画布像素区)
分辨率无关是(无限缩放不失真)否(放大后像素化)

2. 技术细节对比

SVG

工作原理
通过 XML 描述图形,浏览器解析后生成可操作的 DOM 节点。

<svg width="100" height="100"><circle cx="50" cy="50" r="40" fill="red"/>
</svg>
  • 特点

    • 支持 CSS 样式和动画。

    • 内置事件处理(如 onclick)。

    • 适合静态或交互复杂的图形(如图标、图表)。

Canvas

工作原理
通过 JavaScript 动态绘制像素,无持久化对象。

const ctx = canvas.getContext('2d');
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(50, 50, 40, 0, Math.PI * 2);
ctx.fill();
  • 特点

    • 高性能,适合频繁重绘(如游戏、动态数据可视化)。

    • 需要手动管理状态和重绘。

    • 无内置事件系统,需通过数学计算实现交互。

3. 性能与适用场景

场景SVGCanvas
图形复杂度适合少量复杂图形(如矢量图标)适合大量简单图形(如粒子效果)
动态更新频率低(DOM 操作成本高)高(直接操作像素)
交互需求内置事件支持(如点击、悬停)需手动计算交互区域
动画CSS/SMIL 动画或 JS 控制属性必须通过 JS 逐帧重绘
典型应用地图、UI 图标、可缩放图表游戏、实时数据可视化、图像处理

4. 代码示例对比

绘制一个可点击的圆形

SVG 实现(自带事件):

<svg width="100" height="100"><circle cx="50" cy="50" r="40" fill="red" onclick="alert('Clicked!')"/>
</svg>

Canvas 实现(需手动检测点击):

<canvas id="canvas" width="100" height="100"></canvas>
<script>const canvas = document.getElementById('canvas');const ctx = canvas.getContext('2d');// 绘制圆ctx.fillStyle = 'red';ctx.beginPath();ctx.arc(50, 50, 40, 0, Math.PI * 2);ctx.fill();// 手动检测点击canvas.addEventListener('click', (e) => {const x = e.offsetX, y = e.offsetY;const distance = Math.sqrt((x - 50) ** 2 + (y - 50) ** 2);if (distance <= 40) alert('Clicked!');});
</script>

5. 选择建议

  • 用 SVG 如果

    • 需要矢量缩放(如响应式设计)。

    • 图形需要单独交互或动画。

    • 图形数量较少(避免 DOM 性能问题)。

  • 用 Canvas 如果

    • 需要高性能渲染(如 60fps 动画)。

    • 处理像素级操作(如滤镜、图像分析)。

    • 图形数量极多(如上万元素的可视化)。

6. 进阶对比

高级功能SVGCanvas
文本渲染完美支持(可选中、样式丰富)基础支持(需手动处理换行等)
图像处理有限(通过 <image> 标签)强大(像素操作、WebGL 扩展)
内存占用较高(DOM 节点开销)较低(纯像素缓冲区)
学习曲线简单(声明式语法)较陡(需理解绘图 API)

7.总结

  • SVG 是声明式的矢量图形,适合交互复杂、需要缩放的场景。

  • Canvas 是命令式的位图绘制,适合高性能、动态渲染的场景。

根据项目需求混合使用两者(例如用 SVG 做 UI,Canvas 渲染背景动画)往往是最佳实践。

 7.SVG兼容问题汇总

1. 浏览器兼容性问题

1.1 旧版浏览器(IE 8 及以下)

  • 问题

    • IE 8 及更早版本完全不支持 SVG

    • IE 9-11 部分支持,但存在 Bug(如滤镜效果、CSS 动画)。

  • 解决方案

    • 使用 Polyfill(如 SVG for Everybody)或转换为 PNG 备用。

    • 通过 <img> 引入 SVG 时,添加 onerror 回退:

      <img src="image.svg" onerror="this.src='fallback.png'" />

1.2 Android 4.3 及以下

  • 问题

    • 部分 SVG 特性(如 viewporttransform)支持不完整。

  • 解决方案

    • 避免复杂变换,使用简化 SVG 代码。

2. 功能兼容性问题

2.1 SVG 滤镜(<filter>

  • 问题

    • 部分浏览器(如旧版 Firefox)对 feBlendfeColorMatrix 等滤镜效果支持不完整。

  • 解决方案

    • 使用 CSS 滤镜(如 filter: blur(5px))作为备用。

    • 测试效果并简化滤镜链。

2.2 SVG 动画

  • 问题

    • SMIL 动画(如 <animate>)在 Chrome 45+ 已弃用,但部分浏览器仍支持。

    • CSS 动画对 transform 属性的支持不一致。

  • 解决方案

    • 改用 CSS 动画或 JavaScript 动画库(如 GSAP、Snap.svg)。

    • 检测 SMIL 支持并回退:

      if (!document.createElementNS('http://www.w3.org/2000/svg', 'animate').toString().includes('SVGAnimateElement')) {console.log('SMIL 不支持');
      }

2.3 字体与文本

  • 问题

    • <text> 元素在跨平台渲染时可能出现字体不一致或换行错误。

  • 解决方案

    • 使用 textPath 或手动换行(<tspan>)。

    • 将文本转换为路径(设计工具中操作)。

3. 嵌入方式的兼容性

3.1 <img> 标签引入 SVG

  • 问题

    • 无法通过 CSS 修改 SVG 内部样式。

    • 部分浏览器禁用 SVG 内联脚本。

  • 解决方案

    • 改用 <object> 或内联 SVG:

      <object data="image.svg" type="image/svg+xml"></object>

3.2 CSS 背景图

  • 问题

    • 旧版 iOS Safari 可能无法正确缩放 SVG 背景。

  • 解决方案

    • 显式设置 background-size

      .element {background: url('image.svg');background-size: 100% 100%;
      }

4. 交互与脚本问题

4.1 事件绑定

  • 问题

    • 动态创建的 SVG 元素在旧版 Android 中可能无法触发事件。

  • 解决方案

    • 使用事件委托(委托到父级 SVG 或 HTML 元素)。

4.2 动态修改 SVG

  • 问题

    • 直接修改 d 属性(如 <path>)在 IE 中可能不触发重绘。

  • 解决方案

    • 强制重绘:

      path.setAttribute('d', newValue);
      path.style.transform = 'scale(1)'; // 触发重绘

5. 其他常见问题

5.1 尺寸与视口

  • 问题

    • 未设置 viewBox 时,某些浏览器可能无法正确缩放 SVG。

  • 解决方案

    • 始终显式定义 viewBox 和 width/height

      <svg width="100" height="100" viewBox="0 0 100 100">...</svg>

5.2 外链资源

  • 问题

    • 外部 SVG 文件中的 <use href="external.svg#icon"> 在 Firefox 中可能受限。

  • 解决方案

    • 使用内联 SVG 或工具链(如 Webpack)将 SVG 打包为数据 URI。

svg兼容性总结

  • 主要问题:旧版浏览器(IE/旧移动端)、滤镜/动画支持、动态交互。

  • 检测函数:

    // Can I Use 也可以直接看
    if (Modernizr.svg) {console.log('SVG 支持');
    }
  • 通用建议

    1. 优先使用内联 SVG 以最大化控制权。

    2. 复杂场景提供 PNG 回退。

    3. 测试目标平台的关键功能(如动画、滤镜)。

通过预处理工具(如 SVGO 优化代码)和渐进增强策略,可以显著降低 SVG 的兼容性风险。

 


http://www.mrgr.cn/news/95858.html

相关文章:

  • Python进阶编程总结
  • 定长内存池原理及实现
  • 【Linux知识】RPM软件包安装命令行详细说明
  • MoManipVLA:将视觉-语言-动作模型迁移到通用移动操作
  • Rust从入门到精通之精通篇:21.高级内存管理
  • Tasklet_等待队列_工作队列
  • ngx_http_core_location
  • SVN常用命令
  • 团体协作项目总结Git
  • 基于Ebay拍卖网站成交价格的影响因素分析
  • python工厂模式
  • 2025前端面试题(vue、react、uniapp、微信小程序、JS、CSS、其他)
  • 吾爱出品,文件分类助手,高效管理您的 PC 资源库
  • 内核编程十二:打印task_struct中的数据
  • 单片机和微控制器知识汇总——《器件手册--单片机、数字信号处理器和可编程逻辑器件》
  • Mycat安装验证流程整理
  • 【Pandas】pandas Series to_csv
  • Vue 3 组件高级语法
  • 【c++入门系列】:引用以及内联函数详解
  • 【Golang】补充:占位符、转义字符、错误处理