javascript - 如何在 SVG 中使用和设置样式(选择器)嵌套符号
问题描述
我有以下内容:
<html>
<head>
<style>
html, body {
margin: 0;
padding: 0;
overflow: hidden;
}
grove > tree > triangle {
/* some triangle styles */
}
#grove1 > tree > triangle {
/* some triangle styles for grove 1 */
}
#grove2 > tree > triangle {
/* some triangle styles for grove 2 */
}
#grove3 > tree > triangle {
/* some triangle styles for grove 3 */
}
#grove3 > tree {
/* animate the tree */
}
</style>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3000 3000">
<defs>
<symbol id="triangle" viewBox="0 0 100 100">
<polygon points="0,100 50,0 100,100" class="triangle" />
</symbol>
<symbol id="tree" viewBox="0 0 100 100">
<use href="#triangle" width="100" height="100" />
</symbol>
<symbol id="grove" viewBox="0 0 100 100">
<use href="#tree" width="10" height="10" />
<use href="#tree" width="10" height="10" x="20" />
<use href="#tree" width="10" height="10" x="40" />
<use href="#tree" width="10" height="10" x="60" />
<use href="#tree" width="10" height="10" x="80" />
</symbol>
</defs>
<use id="grove1" href="#grove" x="10" y="10" height="10"/>
<use id="grove2" href="#grove" x="30" y="100" height="100"/>
<use id="grove3" href="#grove" x="50" y="600" height="600"/>
</svg>
</body>
</html>
请注意,符号嵌套了 3 层深。并且每个符号的尺寸定义都会发生变化。例如,在grove
符号中,viewBox
是 100x100,但它包含的树也有自己的 100x100 视图框。树木的大小与10x10
树林中的大小相同,因此它们具有不同的缩放系统。
基本上,我将这些符号组合成grove
符号,然后添加use
在 3 个不同位置使用的符号。每一个看起来都比前一个更大/更接近。或者这就是它应该如何工作。
问题是如何有效且正确地更改这些符号的颜色(最佳实践)。如果我可以做类似上面示例 CSS 的事情:
grove > tree > triangle {
/* some triangle styles */
}
或者,如果我必须以某种方式使用 JavaScript 来更改这种情况下的样式,或者根本不使用符号,或者为我想要的每种颜色变化创建符号(不知何故)。
请让我知道我应该如何构建这个 SVG 系统,以便我可以正确地设置每一块东西的样式(例如,每个“grove”及其内容)。
我想处理的另一个例子是,假设每棵树都有分支。我想要有 5 排树,就好像它是视差一样,并且每一排的距离都比前一排更远,因此它们变得越来越轻。所以我想将树枝和“叶子”(主树三角形)的颜色设置为随着它们向后移动而变得越来越轻。另外,也许我想稍微改变特定行的树木颜色。所以我应该能够做这样的事情:
#grove1 > tree > branch { /* style */ }
#grove1 > #tree1 { /* style */ }
#grove1 > #tree2 { /* style */ }
#grove1 > #tree2 > #branch1 { /* style */ }
#grove1 > #tree2 > #branch2 { /* style */ }
#grove1 > etc...
基本上如何单独设置嵌套符号的样式。如果不可能,那么我应该使用什么设计模式。
解决方案
样式可以继承到 a 的子项中,<use>
如下所示:
<html>
<head>
<style>
html, body {
margin: 0;
padding: 0;
overflow: hidden;
}
#grove {
/* some triangle styles */
}
#grove1 {
/* some triangle styles for grove 1 */
fill: red;
}
#grove2 {
/* some triangle styles for grove 2 */
fill: green;
}
#grove3 {
/* some triangle styles for grove 3 */
fill: gold;
}
#grove3 > tree {
/* animate the tree */
}
</style>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3000 3000">
<defs>
<symbol id="triangle" viewBox="0 0 100 100">
<polygon points="0,100 50,0 100,100" class="triangle" />
</symbol>
<symbol id="tree" viewBox="0 0 100 100">
<use href="#triangle" width="100" height="100" />
</symbol>
<symbol id="grove" viewBox="0 0 100 100">
<use href="#tree" width="10" height="10" />
<use href="#tree" width="10" height="10" x="20" />
<use href="#tree" width="10" height="10" x="40" />
<use href="#tree" width="10" height="10" x="60" />
<use href="#tree" width="10" height="10" x="80" />
</symbol>
</defs>
<use id="grove1" href="#grove" x="10" y="10" height="10"/>
<use id="grove2" href="#grove" x="30" y="100" height="100"/>
<use id="grove3" href="#grove" x="50" y="600" height="600"/>
</svg>
</body>
</html>
- 您可以设置样式
<symbol>
和它的孩子。 <use>
您可以设置元素的样式。但是,您不能拥有跨越
<use>
“边界”的选择器。#myuse > #mysymbol-child
不管用。您不能使用选择器来定位该符号的特定实例。除了
<use>
像我在我的例子中所做的那样继承。
符号是一个定义。如果你给它一个直接的风格,那么无论它有什么风格的符号,都会在任何地方使用。这包括动画之类的东西。如果您为元件设置动画,则它的所有实例都将以相同的方式设置动画。
推荐阅读
- spring-boot - 如何在 Spring Boot 嵌入式 tomcat 中启用连接池
- python - 如何从python列表的每个元素中删除前缀?
- powerbi - DAX 创建具有特定列名且没有行的空表
- android-studio - Android Studio 默认打开 iPhone XR 模拟器。如何改变它?
- c# - 错误 MSB6006“al.exe”退出,代码 -1073741819 - Visual Studio\2017\Community\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets
- azure - 如何使用天蓝色流分析计算每一行的百分比?
- ios - 当我从另一个视图回到视图时,TabBarController 消失
- sql - Regexp_extract 出现“-q_”后的所有内容
- python - 如何使用 imageio 修复 mimwrite raise RuntimeError("Zero images werewritten.")?
- javascript - 无法删除空格(在使用 lettering.js 拆分 div 之后)