百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

SVG.js:比 Snap.svg 还快 5x 的零依赖开源库!

myzbx 2025-04-27 15:05 22 浏览

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!

今天给大家带来的主题是SVG.js,即用于操作和为 SVG 添加动画的轻量级库。话不多说,直接进入正题。

1.什么是 SVG.js

SVG.js 是用于操作和为 SVG 添加动画的轻量级库。SVG.js 的特点是:没有任何外部依赖,同时体积非常小,提供几乎完整的 SVG 规范覆盖。最重要的是,SVG.js 速度非常快,虽然不如 Vanilla js ,但比其他同类替代方案,比如 Snap.svg 要快很多倍。

上图表示的 rects、fill、gradient 的含义如下:

  • rects:生成 10000 个 rects
  • fill:生成 10000 个填充颜色的矩形
  • gradient:生成 10000 个带有渐变填充的矩形

同时,SVG.js 非常易于阅读、语法整洁。 如果单独使用 JavaScript 创建和操作 SVG 代码会非常冗长。例如,下面代码示例仅仅创建一个简单的粉色方块:

// Vanilla js
var ns = "http://www.w3.org/2000/svg";
var div = document.getElementById("drawing");
var svg = document.createElementNS(ns, "svg");
svg.setAttributeNS(null, "width", "100%");
svg.setAttributeNS(null, "height", "100%");
div.appendChild(svg);
var rect = document.createElementNS(ns, "rect");
rect.setAttributeNS(null, "width", 100);
rect.setAttributeNS(null, "height", 100);
rect.setAttributeNS(null, "fill", "#f06");
svg.appendChild(rect);

SVG.js 提供了非常简洁易读的语法,下面代码执行与上面的 vanilla js 示例相同的操作:

// SVG.js
var draw = SVG().addTo("#drawing"),
  rect = draw.rect(100, 100).fill("#f06");

同时,使用 SVG.js 创建动画也非常简单,比如下面的例子实现了文字的复杂动画:

var input = document.querySelector("input[type=text]");
var draw = SVG().addTo("#drawing").viewbox(0, 0, 300, 140);
var text = draw.text(function (add) {
  add.tspan(input.value);
});

textPath = text.path("M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80");
textPath
  .animate(1000)
  .ease("<>")
  .plot("M10 80 C 40 150, 65 150, 95 80 S 150 10, 180 80")
  .loop(true, true);

input.addEventListener("keyup", updateText(textPath));

function updateText(textPath) {
  return function () {
    textPath.tspan(this.value);
  };
}

除了上面列举的 SVG.js 的功能外,SVG.js 还有一系列非常优秀的特性,比如:

  • 支持大小、位置、变换、颜色等动画
  • 得益于模块化结构,无痛扩展
  • 各种有用的插件可用
  • 具有移动、大小、中心等形状类型之间的统一 api
  • 将事件绑定到元素
  • 完全支持不透明蒙版和剪切路径
  • 文本路径,甚至动画
  • 元素组(element groups)
  • 动态渐变和图案
  • 非常完善的文档机制

在浏览器支持上,SVG.js 也做的非常不错,比如在桌面设备上:

  • Firefox 3+
  • Chrome 4+
  • Safari 3.2+
  • Opera 9+
  • IE9+

在移动设备上也非常不错,比如:

  • iOS Safari 3.2+
  • Android Browser 3+
  • Opera Mobile 10+
  • Chrome for Android 18+
  • Firefox for Android 15+

目前 SVG.js 在 Github 上通过 MIT 协议开源,有超过 10.3k 的 star、1.1k 的 fork、2.2k 的项目依赖量,代码贡献者 100+,妥妥的前端优质开源项目。

2.开始使用 SVG.js

2.1 准备工作

创建一个基本的 Html 标记并包含 svg.js 脚本:

<!DOCTYPE html>
<html>
<head>
  <title>SVG.js</title>
  <script src="https://cdn.jsdelivr.net/npm/@svgdotjs/svg.js@3.0/dist/svg.min.js"></script>
</head>
<body>

</body>
</html>

或者只在 javascript 应用程序中导入 svg.js:

import { SVG } from "@svgdotjs/svg.js";

注意:以前在全局 SVG 对象上可用的所有属性现在都需要导入,请参见下面的示例:

import {
  SVG,
  extend as SVGextend,
  Element as SVGElement,
} from "@svgdotjs/svg.js";

2.2 创建 SVG 文档

接下来,使用 SVG() 函数创建一个 SVG 文档并将其添加到 html 页面:

var draw = SVG().addTo("body").size(300, 300);
var rect = draw.rect(100, 100).attr({ fill: "#f06" });

可以将任何 css 选择器传递给 addTo 或节点。

<body>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    version="1.1"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    width="300"
    height="300"
  >
    <rect width="100" height="100" fill="#f06"></rect>
  </svg>
</body>

SVG.js 不会自动设置文档的大小。因此,请确保使用适当的值调用 size()。 例如:要将大小设置为其父级的尺寸,可以使用以下命令:

var draw = SVG().addTo("#someId").size("100%", "100%");

2.3 等待 DOM 加载

这对许多人来说似乎是显而易见的,但仍然值得一提。如果在文档的头部包含 js 文件,请确保等待 DOM 加载完成:

SVG.on(document, "DOMContentLoaded", function () {
  var draw = SVG().addTo("body");
});

如果在页面底部包含 js,这不是问题。

2.4 纯 SVG 使用

SVG.js 也可以在 HTML DOM 之外工作,例如在 SVG 文档内:

<?xml version="1.0" encoding="utf-8" ?>
<svg id="drawing" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" >
  <script type="text/javascript" xlink:href="svg.min.js"></script>
  <script type="text/javascript">
    <![CDATA[
      var draw = SVG('#drawing')
      draw.rect(100,100).animate().fill('#f03').move(100,100)
    ]]>
  </script>
</svg>

2.5 使用 SVG() 函数

此函数不仅创建新文档,还可以从 dom 中检索 svg.js 对象或从 svg 片段创建新对象:

// new document
var draw = SVG();
// get rect from dom
var rect = SVG("#myRectId");
// or
var rect = SVG("rect");
// any css selector will do
var path = SVG("#group1 path.myClass");
// create new object from fragment
var circle = SVG("<circle>");
// convert node to svg.js object
var obj = SVG(node);

3.扩展 SVG.js

由于 SVG.js 的面向对象性质,对象/原型可以在任何级别上扩展。此外,所有 SVG.js 类都可以进行子类化以创建自定义元素。

3.1 SVG.extend()

SVG.js 具有模块化结构,可以在不同级别添加自定义方法。假设想要向所有形状类型添加一个方法,那么可以将方法添加到 SVG.Shape:

SVG.extend(SVG.Shape, {
  paintRed: function () {
    return this.fill("red");
  },
});

现在所有形状都可以使用 paintRed() 方法。假设想让椭圆上的 paintRed() 方法应用稍微不同的颜色,可以按照如下方式:

SVG.extend(SVG.Ellipse, {
  paintRed: function () {
    return this.fill("orangered");
  },
});

SVG.Ellipse 的完整继承栈是: SVG.Base > SVG.EventTarget > SVG.Dom > SVG.Element > SVG.Shape > SVG.Ellipse。 可以使用以下方法扩展 SVG 文档:

SVG.extend(SVG.Svg, {
  paintAllPink: function () {
    this.each(function () {
      this.fill("pink");
    });
  },
});

还可以一次扩展多个元素:

SVG.extend([SVG.Ellipse, SVG.Path, SVG.Polygon], {
  paintRed: function () {
    return this.fill("orangered");
  },
});

3.2 子类化 Subclassing

使用 SVG.js 创建自定义元素非常简单,假如想要一个圆角矩形,它总是与元素的高度成比例,新形状位于 SVG 命名空间中,称为 Rounded。 以下是实现这一目标的方法。

SVG.Rounded = class extends SVG.Rect{
  // 创建按比例缩放圆角的方法
  size: function(width, height) {
    return this.attr({
      width:  width
    , height: height
    , rx:     height / 5
    , ry:     height / 5
    })
  }
})
// 添加创建圆角矩形的方法
SVG.extend(SVG.Container,  {
  // 创建圆形元素
  rounded: function(width, height) {
    return this.put(new SVG.Rounded).size(width, height)
  }
}

3.3 插件生态

SVG.js 的插件生态非常完善,下面是一些官方提供的优秀插件。

  • svg.colorat.js:svg.colorat.js 是 SVG.js 的扩展,允许开发者从特定给定位置的渐变中选择颜色。
  • svg.draggable.js:使元素可拖动
  • svg.easing.js:支持更多动画缓动方法。
  • svg.filter.js:向元素添加 svg 过滤器。
  • svg.math.js:支持 SVG 的数学扩展
  • svg.panzoom.js:svg.js 的插件,它为视图框元素启用平移。
  • svg.path.js:支持手动绘制路径
  • svg.shapes.js:支持更多基于多边形的形状。
  • svg.topath.js:将任何其他形状转换为 path 路径。
  • svg.topoly.j:将路径转换为多边形或折线。
  • ngx-svg:ngx-svg 是 Angular 2+ 的一个库,它使得在 Angular 中使用 SVG.js 库变得容易。

4.本文总结

本文主要和大家介绍下 SVG.js,即用于操作和为 SVG 添加动画的轻量级库。相信通过本文的阅读,大家对 SVG.js 会有一个初步的了解。

因为篇幅有限,文章并没有过多展开,如果有兴趣,可以在我的主页继续阅读,同时文末的参考资料提供了大量优秀文档以供学习。最后,欢迎大家点赞、评论、转发、收藏!


参考资料

https://github.com/svgdotjs/svg.js/

https://svgjs.dev/docs/3.0/getting-started/#create-an-svg-document

https://svgjs.dev/docs/3.0/extending/#subclassing

https://svgjs.dev/docs/3.0/plugins/ngx-svg/

https://svgjs.dev/docs/3.0/compatibility/

https://github.com/adobe-webplatform/Snap.svg/

相关推荐

零基础入门AI智能体:详细了解什么是变量类型、JSON结构、Markdown格式

当品牌跳出固有框架,以跨界联动、场景创新叩击年轻群体的兴趣点,一场关于如何在迭代中保持鲜活的探索正在展开,既藏着破圈的巧思,也映照着与新一代对话的密码。在创建AI智能体时,我们会调用插件或大模型,而在...

C# 13模式匹配:递归模式与属性模式在真实代码中的性能影响分析

C#13对模式匹配的增强让复杂数据处理代码更简洁,但递归模式与属性模式的性能差异一直是开发者关注的焦点。在实际项目中,选择合适的模式不仅影响代码可读性,还可能导致执行效率的显著差异。本文结合真实测试...

零基础快速入门 VBA 系列 6 —— 常用对象(工作簿、工作表和区域)

上一节,我介绍了VBA内置函数以及如何自动打字和自动保存文件。这一节,我们来了解一下Excel常用对象。Excel常用对象Excel有很多对象,其中最常用也最重要的包括以下3个:1.Workbo...

不同生命数字的生肖龙!准到雷普!

属龙的人总在自信爆棚和自讨苦吃之间反复横跳?看完这届龙宝宝的日常我悟了。属龙的人好像天生自带矛盾体:领导力超强可人缘时好时坏,工作雷厉风行却总在爱情里翻车。关键年份的龙性格差异更大——76年龙靠谱但不...

仓颉编程语言基础-面向对象编程-属性(Properties)

属性是仓颉颉中一种强大的机制,它允许你封装对类(或接口interface、结构体struct、枚举enum、扩展extend)内部状态的访问。它看起来像一个普通的成员变量(字段),但在其背后,它通过...

Python中class对象/属性/方法/继承/多态/魔法方法详解

一、基础入门:认识类和对象1.类和对象的概念在Python中,类(class)是一种抽象的概念,用于定义对象的属性和行为,而对象(也称为实例)则是类的具体表现。比如,“汽车”可以是一个类,它有...

VBA基础入门:搞清楚对象、属性和方法就成功了一半

如果你刚接触VBA(VisualBasicforApplications),可能会被“对象”“属性”“方法”这些术语搞得一头雾水。但事实上,这三个概念是VBA编程的基石。只要理解它们之间的关系,...

P.O类型文推荐|年度编推合集(一百九十五篇)

点击左上方关注获取更多精彩推文目录2019年度编推35篇(1V1)《悖论》作者:流苏.txt(1V1)《桂花蒸》作者:大姑娘浪.txt(1V1)《豪门浪女》作者:奚行.txt...

Python参数传递内存大揭秘:可变对象 vs 不可变对象

90%的Python程序员不知道,函数参数传递中可变对象的修改竟会导致意想不到的副作用!一、参数传递的本质:对象引用传递在Python中,所有参数传递都是对象引用的传递。这意味着函数调用时传递的不是对...

JS 开发者必看!TC39 2025 最新动向,这些新语法要火?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。TC39第...

2025 年值得尝试的 5 个被低估的 JavaScript 库

这些JavaScript库可能不会在社交媒体或HackerNews上流行起来,但它们会显著提高您的工作效率和代码质量。JavaScript不再只是框架。虽然React、Vue和Sv...

Python自动化办公应用学习笔记30—函数的参数

一、函数的参数1.形参:o定义:在函数定义时,声明在函数名后面括号中的变量。o作用:它们是函数内部的占位符变量,用于接收函数被调用时传入的实际值。o生命周期:在函数被调用时创建,在函数执...

16种MBTI人格全解析|测完我沉默了三秒:原来我是这样的人?

MBTI性格测试火了这么久,你还不知道自己是哪一型?有人拿它当社交话题,有人拿它分析老板性格,还有人干脆当成择偶参考表。不废话,今天我一次性给你整理全部16种MBTI人格类型!看完你不仅能知道自己是谁...

JS基础与高级应用: 性能优化

在现代Web开发中,性能优化已成为前端工程师必须掌握的核心技能之一。本文从URL输入到页面加载完成的全过程出发,深入分析了HTTP协议的演进、域名解析、代码层面性能优化以及编译与渲染的最佳实践。通过节...

爱思创CSP-J/S初赛模拟赛线上开赛!助力冲入2024年CSP-J/S复赛!

CSP-J/S组初赛模拟赛爱思创,专注信奥教育19年,2022年CSP-J/S组赛事指定考点,特邀NOIP教练,开启全真实CSP-J/S组线上初赛模拟大赛!一、比赛对象:2024年备考CSP-J/S初...