SVG

SVG 是一种基于 XML 的矢量 2D 图形格式,支持交互性和动画。Parcel 包含对 SVG 的支持,作为单独的文件,嵌入在 HTML 中,或作为 JSX 导入到 JavaScript 文件中。

依赖项

#

Parcel 检测 SVG 中大多数对其他文件的引用(例如 <script><image><use>)并对其进行处理。这些引用被重写,以便它们链接到正确的输出文件。

文件名相对于当前 SVG 文件解析,但您也可以使用 绝对波浪号 指定符。有关详细信息,请参阅 依赖解析

样式表

#

可以通过 SVG 文档中的 xml-stylesheet 处理指令引用外部样式表。您可以引用 CSS 文件,或任何编译为 CSS 的其他文件,例如 SASSLessStylus

example.svg
<?xml-stylesheet href="style.css" ?>
<svg viewBox="0 0 240 20" xmlns="http://www.w3.org/2000/svg">
<text>Red text</text>
</svg>
style.css
text {
fill: red;
}

有关 Parcel 如何处理 CSS 的详细信息,请参阅 CSS 文档。

脚本

#

<script> 元素可用于从 SVG 引用脚本文件。您可以引用 JavaScript 文件,或任何编译为 JavaScript 的其他文件,例如 TypeScriptJSXCoffeeScript

type="module" 属性应用于指示文件是 ES 模块CommonJS 文件。如果省略,则引用的文件将被视为经典脚本。有关此的更多信息,请参阅 经典脚本。ES 模块尚未在 SVG 中得到原生支持,因此 Parcel 将所有 JavaScript 编译为经典脚本,即使它们是作为模块编写的。

注意:SVG 使用 href 属性而不是 src 属性用于 <script> 元素。

example.svg
<svg viewBox="0 0 240 80" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" fill="red" />
<script type="module" href="interactions.js" />
</svg>
interactions.js
let circle = document.querySelector('circle');
circle.addEventListener('click', () => {
circle.setAttribute('fill', 'blue');
});

有关 <script> 元素的更多信息,请参阅 MDN 文档,有关 Parcel 如何处理 JavaScript 的详细信息,请参阅 JavaScript 文档。

图像

#

可以使用 <image> 元素将光栅图像或其他 SVG 嵌入 SVG 文件中。Parcel 识别 hrefxlink:href 属性。

<image href="image.jpg" width="100" height="50" />

Parcel 的图像转换器还可以通过使用 查询参数 来调整图像大小和转换图像。

<image href="image.jpg?as=webp" width="100" height="50" />

注意:通过 <image> 元素引用的 SVG 不会加载外部资源(如样式表、字体和其他图像),并且脚本和交互性被禁用。

有关 Parcel 如何处理图像的详细信息,请参阅 图像 文档。

#

SVG 文件可以使用 <a> 元素链接到其他网页或文件。Parcel 支持 hrefxlink:href 属性。

<a href="circle.html">
<circle cx="50" cy="40" r="35" />
</a>

虽然从 SVG 文件引用的其他资产默认情况下将在其编译后的文件名中包含 内容哈希,但 <a> 元素引用的文件不会。这是因为这些 URL 通常是人类可读的,并且需要随着时间的推移保持稳定的名称。捆绑包命名可以通过 命名器插件 覆盖。

外部引用

#

Parcel 支持通过许多其他元素上的 hrefxlink:href 属性进行外部引用。有关详细信息,请参阅 MDN 文档

<use href="fox.svg#path" stroke="red" />
<text>
<textPath href="fox.svg#path">
Quick brown fox jumps over the lazy dog.
</textPath>
</text>

还支持通过 url() 函数在表示属性(如 fillstrokeclip-path 以及许多其他属性)中引用的外部资源。

<circle
cx="50" cy="40" r="35"
fill="url(external.svg#gradient)" />

内联脚本和样式

#

<script><style> 标记的文本内容也像独立文件一样进行处理,生成的捆绑包被插入回 SVG 文件中。使用 type="module" 属性(如上所述)来启用从内联脚本导入其他模块。

example.svg
<svg viewBox="0 0 240 80" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" />
<style>
@import './style.scss';
</style>
<script type="module">
import {setup} from './interactions.ts';
let circle = document.querySelector('circle');
setup(circle);
</script>
</svg>
style.scss
$fill: blue;

circle {
fill: $fill;
}
interactions.ts
export function setup(element: SVGElement) {
element.addEventListener('click', () => {
element.setAttribute('fill', 'red');
});
}

通过 @import 引用的 CSS 文件,以及通过 import 引用的 JavaScript 将被捆绑到编译后的 SVG 文件中。有关如何引用外部文件,请参阅 样式表脚本

内联 style 属性

#

可以使用任何 SVG 元素上的 style 属性来定义 CSS 样式。Parcel 将处理内联 CSS,并将结果插入回 style 属性中。这包括遵循引用的 URL,以及为目标浏览器转换现代 CSS。

<circle
cx="50" cy="40" r="35"
style="fill: url(external.svg#gradient)" />

HTML 中的 SVG

#

HTML 中的 SVG 可以作为外部文件引用,也可以直接嵌入到 HTML 文档中。

外部 SVG

#

可以通过多种方式从 HTML 引用 SVG 文件。最简单的方法是使用 <img> 元素,并使用 src 属性引用 SVG 文件。Parcel 将遵循引用并处理 SVG 及其所有依赖项。

<img src="logo.svg" alt="logo" />

如果您的 SVG 是静态的,这种方法非常有效。如果 SVG 引用外部资源(如其他 SVG、图像、字体、样式表或脚本),或包含任何交互性,则它将不起作用。您也不能通过 HTML 页面中的 CSS 更改 SVG 的样式,也不能使用 JavaScript 操作 SVG 的 DOM,并且 SVG 中的任何文本都无法被用户选中。

可以使用 <object> 元素将外部 SVG 嵌入 HTML,并启用外部引用、脚本、交互性和文本选择。使用 data 属性引用 SVG 文件。

<object data="interactive.svg" title="Interactive SVG"></object>

这也允许您通过 <object> 元素上的 getSVGDocument() 方法访问 SVG DOM。

let object = document.querySelector('object');
let svg = object.getSVGDocument();
let circle = svg.querySelector('circle');
circle.setAttribute('fill', 'red');

但是,使用 <object> 元素嵌入的 SVG 无法通过 HTML 页面上的 CSS 进行样式化。

内联 SVG

#

SVG 可以直接内联到 HTML 中,而不是作为单独的文件引用。这允许 HTML 页面上的 CSS 对 SVG 元素进行样式化。Parcel 以与 SVG 位于单独文件中相同的方式支持嵌入式 SVG 中的外部引用。

<!DOCTYPE html>
<html>
<body>
<svg width="100" height="100">
<circle cx="50" cy="50" r="50" />
</svg>
<style>
circle {
fill: blue;
}

circle:hover {
fill: green;
}
</style>
</body>
</html>

CSS 中的 SVG

#

可以使用 url() 函数从 CSS 文件引用 SVG。与 <img> 元素一样,背景图像中的 SVG 不支持外部资源(如样式表),并且脚本和交互性被禁用。

.logo {
background: url('logo.svg');
}

您还可以使用数据 URL 将小型 SVG 嵌入 CSS 文件中。使用 data-url: 方案执行此操作,Parcel 将构建 SVG 并将结果内联到编译后的 CSS 中。有关详细信息,请参阅 包内联

.logo {
background: url('data-url:logo.svg');
}

JavaScript 中的 SVG

#

SVG 文件可以作为外部 URL 从 JavaScript 引用,也可以作为字符串内联,或者转换为 JSX 以在 React 等框架中渲染。

URL 引用

#

Parcel 支持使用 URL 构造函数引用 SVG 文件。此示例使用结果使用 JSX 渲染 <img> 元素。这与上面 外部 SVG 中描述的方式相同。如果 SVG 是交互式的或具有外部资源,您可以使用 <object> 元素。

const logo = new URL('logo.svg', import.meta.url);

export function Logo() {
return <img src={logo} alt="logo" />;
}

有关详细信息,请参阅 JavaScript 文档中的 URL 依赖项

作为字符串内联

#

SVG 可以通过使用 bundle-text: 方案导入它来作为字符串内联到 JavaScript 中。

import svg from 'bundle-text:./logo.svg';

let logo = document.createElement('div');
logo.innerHTML = svg;
document.body.appendChild(logo);

有关详细信息,请参阅 包内联

作为 React 组件导入

#

@parcel/transformer-svg-react 插件可用于将 SVG 文件作为 React 组件导入。这使用 SVGR 将 SVG 文件转换为 JSX。它还使用 SVGO 优化 SVG 以减小文件大小。

此插件未包含在默认的 Parcel 配置中,因此您需要安装它并将其添加到您的 .parcelrc 中。

yarn add @parcel/transformer-svg-react --dev

您可以配置您的 .parcelrc 将所有 SVG 转换为 JSX,或者使用命名管道来创建一个 URL 方案,您可以从 JavaScript 导入语句中引用它。这种方法允许从 JavaScript 引用的 SVG 文件被转换为 JSX,但其他地方引用的 SVG 保持为 SVG 文件。使用 "..." 语法在将 SVG 转换为 JSX 之前先运行默认的 SVG 转换器。

.parcelrc
{
"extends": "@parcel/config-default",
"transformers": {
"jsx:*.svg": ["...", "@parcel/transformer-svg-react"]
}
}
example.jsx
import Icon from "jsx:./icon.svg";

export const App = () => <Icon />;

生产

#

在生产模式下,Parcel 包含优化以减小代码的文件大小。有关此工作原理的详细信息,请参阅 生产

缩小

#

在生产模式下,Parcel 会自动缩小您的代码以减小捆绑包的文件大小。默认情况下,Parcel 使用 SVGO 执行 SVG 缩小。

要配置 SVGO,您可以在项目根目录中创建一个 svgo.config.json 文件。要查看 SVGO 的所有可用配置选项,请参阅 官方文档

svgo.config.json
{
"plugins": [
{
"name": "preset-default",
"params": {
"overrides": {
"inlineStyles": false
}
}
}
]
}

注意svgo.config.jssvgo.config.mjssvgo.config.cjs 也支持基于 JavaScript 的配置,但在可能的情况下应避免使用,因为它会降低 Parcel 缓存的有效性。请改用基于 JSON 的配置格式。