使用全新 Snap.svg 的样式与属性(基础 - 第2部分)

发布: (2025年12月16日 GMT+8 03:52)
7 min read
原文: Dev.to

Source: Dev.to

引言

这是我们 Snap.svg 系列的 第二篇教程。在第一部分我们学习了如何使用 g()g_a()Snap.FORCE_AFTER 构建层级化的 SVG 结构。现在我们要通过以下内容让这些形状 更好看

  • 使用 attr() 设置 fillstrokeopacity 等可视属性
  • 使用 setStyle() 直接在 style 属性上应用内联样式
  • 理解 样式优先级层级(内联样式 > CSS > 属性)
  • 使用 addClass()removeClass()toggleClass() 管理 CSS 类
  • 使用 getId() 自动生成并获取元素 ID
  • 构建一个响应用户点击的交互式调色板

核心思想是 Snap.svg 为属性和样式的应用提供 细粒度控制,并为每种方式提供明确的方法。

已分叉并扩展的 Snap.svg:
获取库的方式:

1. 理解样式优先级层级

在深入代码之前,先了解浏览器在多个来源定义同一属性时如何决定使用哪种样式。优先级顺序为:

  1. 内联 style 属性(最高优先级)
  2. CSS 规则(来自 <style> 标签或外部样式表)
  3. SVG 表现属性(例如 fill="red"

这意味着:

  • setStyle()(内联样式)会覆盖任何 CSS 规则或属性。
  • CSS 规则会覆盖表现属性。
  • 表现属性是基线,优先级最低。

Snap.svg 遵循此层级,并提供相应的方法来显式操作每一层。

2. 使用 attr() 进行基本属性样式

attr() 方法既是 getter 又是 setter。它会智能地决定是将值设为表现属性,还是路由到 style 属性。表现属性优先级最低,但是最常用的 SVG 样式方式。

示例:使用属性绘制彩色矩形

// basic-attr.js
var s = Snap("#mySvg");

// 创建一个组来容纳形状
var group = s.g().attr({ id: "attrGroup" });

// 矩形 1:通过 attr() 使用对象语法设置填充和描边
group
  .rect(20, 20, 80, 60)
  .attr({
    fill: "#3498db",        // 蓝色填充
    stroke: "#2c3e50",      // 深色边框
    strokeWidth: 2
  });

// 矩形 2:使用键‑值语法的 attr()(另一种写法)
var rect2 = group.rect(120, 20, 80, 60);
rect2.attr("fill", "#e74c3c");           // 设置填充
rect2.attr("opacity", 0.7);              // 设置透明度
rect2.attr("stroke", "#c0392b");
rect2.attr("strokeWidth", 3);
rect2.attr("strokeDasharray", "5,3");    // 虚线:5px 实线,3px 间隔

// 矩形 3:无填充,粗圆角描边
group
  .rect(220, 20, 80, 60)
  .attr({
    fill: "none",
    stroke: "#2ecc71",
    strokeWidth: 4,
    strokeLinecap: "round",  // 圆形端点
    strokeLinejoin: "round"   // 圆形拐角
  });

// 矩形 4:准备使用渐变(目前使用纯色)
group
  .rect(320, 20, 80, 60)
  .attr({
    fill: "#f39c12",
    stroke: "#e67e22",
    strokeWidth: 2,
    rx: 10,                  // 圆角
    ry: 10
  });

输出: 四个并排的矩形,每个矩形的填充、描边和透明度设置均通过属性实现。

attr() 既是 Getter 又是 Setter

// Setter
element.attr("fill", "red");                     // 单个属性
element.attr({ fill: "red", opacity: 0.5 });    // 多个属性

// Getter
var currentFill = element.attr("fill");
var currentOpacity = element.attr("opacity");

使用 attr_force() 强制为纯表现属性

attr() 可能会将某些属性路由到 style,以便更好地与 CSS 交互。如果你需要 强制 将值保持为表现属性(即保留在标记中),请使用 attr_force()

// 智能 attr() – 可能路由到 style 或 attribute
element.attr("fill", "blue");

// 强制为表现属性
element.attr_force("fill", "blue");  // 确保生成表现属性

何时使用 attr_force()

  • 当下游 SVG 操作需要表现属性时。
  • 当你希望 CSS 能轻易覆盖该值(属性的优先级最低)。
  • 当使用需要表现属性的 SVG 编辑器或工具时。

常用属性

  • 填充: fill – 颜色、渐变、图案或 "none"
  • 描边: strokestrokeWidthstrokeDasharraystrokeLinecapstrokeLinejoin
  • 透明度: opacity(0 – 1)、fillOpacitystrokeOpacity
  • 几何: 元素特有的 xywidthheightrxryrcxcy

3. 使用 setStyle() 设置内联样式 – 多种输入方式

setStyle() 方法直接在元素的 style 属性上设置属性,拥有 最高的层级优先级。它接受多种输入格式。

多种使用 setStyle() 的方式

// inline-style.js
var s = Snap("#mySvg");
var group = s.g().attr({ id: "styleGroup" });

// 创建用于演示的圆形
var circle1 = group.circle(60, 140, 30);
var circle2 = group.circle(160, 140, 30);
var circle3 = group.circle(260, 140, 30);
var circle4 = group.circle(360, 140, 30);

// 方法 1:对象形式,包含多个属性
circle1.setStyle({
  fill: "red",
  stroke: "#c0392b",
  strokeWidth: 3,
  opacity: 0.8
});

// 方法 2:键‑值语法设置单个属性
circle2.setStyle("fill", "green");
circle2.setStyle("strokeWidth", "2");
circle2.setStyle("stroke", "#27ae60");

// 方法 3:CSS 字符串(类似于内联 style 属性)
circle3.setStyle("fill: blue; stroke: navy; stroke-width: 2;");

// 方法 4:混合使用 – 先用对象设置一个属性,再用键‑值
circle4.setStyle({ fill: "orange" });
circle4.setStyle("stroke", "darkorange");

// 所有圆形的内联样式都会覆盖任何 CSS 或属性设置

灵活性的理解

// 对象记法(最常用)
element.setStyle({
  fill: "purple",
  strokeWidth: 4,
  opacity: 0.5
});

// 键‑值对(适用于单个属性)
element.setStyle("fill", "purple");
element.setStyle("strokeWidth", 4);
element.setStyle("opacity", 0.5);

// CSS 字符串(从 CSS 复制时很方便)
element.setStyle("fill: purple; stroke-width: 4; opacity: 0.5");

// 注意:CSS 属性使用连字符(stroke-width),而对象属性使用驼峰式(strokeWidth)

演示样式覆盖

setStyle() 设置的内联样式会优先于 attr() 设置的属性:

// 先使用属性
var rect = s.rect(50, 200, 100, 50).attr({
  fill: "#3498db",
  stroke: "#2c3e50",
  strokeWidth: 2
});

// 再应用覆盖填充的内联样式
rect.setStyle("fill", "orange");

// 结果:矩形显示为橙色,尽管之前通过属性设置了蓝色填充。
Back to Blog

相关文章

阅读更多 »