새로운 Snap.svg를 사용한 스타일링 및 속성 (기초 - 파트 2)
Source: Dev.to
Introduction
이 글은 Snap.svg 시리즈의 두 번째 튜토리얼입니다. 첫 번째 파트에서는 g(), g_a(), Snap.FORCE_AFTER를 사용해 계층적인 SVG 구조를 만드는 방법을 배웠습니다. 이제는 다음과 같이 모양을 보기 좋게 만들기 위해 배워보겠습니다:
attr()를 이용해fill,stroke,opacity등 시각 속성을 설정하기setStyle()로style속성에 직접 인라인 스타일 적용하기- 스타일 우선순위 계층(인라인 스타일 > CSS > 속성) 이해하기
addClass(),removeClass(),toggleClass()로 CSS 클래스를 관리하기getId()로 요소 ID를 자동 생성·조회하기- 사용자 클릭에 반응하는 인터랙티브 색상 팔레트 만들기
핵심은 Snap.svg가 세밀한 제어를 제공한다는 점이며, 각각의 접근 방식에 맞는 명확한 메서드를 제공한다는 점입니다.
Forked + extended Snap.svg:
Access to the library:
1. Understanding the Style Precedence Hierarchy
코드에 들어가기 전에, 여러 소스가 같은 속성을 정의했을 때 브라우저가 어떤 스타일을 적용할지 결정하는 방식을 이해하는 것이 중요합니다. 우선순위는 다음과 같습니다:
- 인라인
style속성 (가장 높은 우선순위) - CSS 규칙 (
<style>태그 혹은 외부 스타일시트) - SVG 프레젠테이션 속성 (예:
fill="red")
즉:
setStyle()(인라인 스타일)은 모든 CSS 규칙이나 속성을 덮어씁니다.- CSS 규칙은 프레젠테이션 속성을 덮어씁니다.
- 프레젠테이션 속성은 기본값이며 가장 낮은 우선순위를 가집니다.
Snap.svg는 이 계층 구조를 그대로 따르며, 각 레벨을 명시적으로 다룰 수 있는 메서드를 제공합니다.
2. Basic Attribute Styling with attr()
attr() 메서드는 속성의 getter와 setter 역할을 동시에 합니다. 값이 프레젠테이션 속성으로 설정될지, style 속성으로 라우팅될지는 상황에 맞게 자동 판단합니다. 이 방식은 가장 낮은 우선순위를 가지지만 SVG 요소를 스타일링하는 가장 일반적인 방법입니다.
Example: Colored Rectangles with Attributes
// basic-attr.js
var s = Snap("#mySvg");
// Create a group to hold our shapes
var group = s.g().attr({ id: "attrGroup" });
// Rectangle 1: Basic fill and stroke via attr() - object syntax
group
.rect(20, 20, 80, 60)
.attr({
fill: "#3498db", // blue fill
stroke: "#2c3e50", // dark border
strokeWidth: 2
});
// Rectangle 2: Using attr() with key‑value syntax (alternative way)
var rect2 = group.rect(120, 20, 80, 60);
rect2.attr("fill", "#e74c3c"); // Set fill
rect2.attr("opacity", 0.7); // Set opacity
rect2.attr("stroke", "#c0392b");
rect2.attr("strokeWidth", 3);
rect2.attr("strokeDasharray", "5,3"); // dashed: 5px dash, 3px gap
// Rectangle 3: No fill, thick rounded stroke
group
.rect(220, 20, 80, 60)
.attr({
fill: "none",
stroke: "#2ecc71",
strokeWidth: 4,
strokeLinecap: "round", // rounded ends
strokeLinejoin: "round" // rounded corners
});
// Rectangle 4: Gradient‑ready (using a solid color for now)
group
.rect(320, 20, 80, 60)
.attr({
fill: "#f39c12",
stroke: "#e67e22",
strokeWidth: 2,
rx: 10, // rounded corners
ry: 10
});
Output: 네 개의 사각형이 일렬로 배치되며, 각각 다른 fill, stroke, opacity 설정이 속성으로 적용됩니다.
attr() as Getter and Setter
// Setter
element.attr("fill", "red"); // single attribute
element.attr({ fill: "red", opacity: 0.5 }); // multiple attributes
// Getter
var currentFill = element.attr("fill");
var currentOpacity = element.attr("opacity");
Using attr_force() for Pure Presentation Attributes
attr()는 일부 속성을 CSS와의 호환성을 위해 style 속성으로 라우팅할 수 있습니다. 마크업에 프레젠테이션 속성으로 반드시 남겨야 할 경우에는 attr_force()를 사용합니다:
// Smart attr() – may route to style or attribute
element.attr("fill", "blue");
// Force as presentation attribute
element.attr_force("fill", "blue"); // Guarantees a presentation attribute
When to use attr_force()
- 프레젠테이션 속성이 downstream SVG 조작에 필요할 때
- CSS가 값을 쉽게 덮어쓸 수 있게 하고 싶을 때 (속성은 가장 낮은 우선순위)
- SVG 편집기나 도구가 프레젠테이션 속성을 기대할 때
Common Attributes
- Fill:
fill– 색상, 그라디언트, 패턴, 혹은"none" - Stroke:
stroke,strokeWidth,strokeDasharray,strokeLinecap,strokeLinejoin - Opacity:
opacity(0 – 1),fillOpacity,strokeOpacity - Geometry: 요소별
x,y,width,height,rx,ry,r,cx,cy등
3. Inline Styles with setStyle() – Flexible Input
setStyle() 메서드는 요소의 style 속성에 직접 값을 설정하므로 캐스케이드에서 가장 높은 우선순위를 가집니다. 다양한 입력 형식을 지원합니다.
Multiple Ways to Use setStyle()
// inline-style.js
var s = Snap("#mySvg");
var group = s.g().attr({ id: "styleGroup" });
// Create circles for demonstration
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);
// Method 1: Object with multiple properties
circle1.setStyle({
fill: "red",
stroke: "#c0392b",
strokeWidth: 3,
opacity: 0.8
});
// Method 2: Single property with key‑value syntax
circle2.setStyle("fill", "green");
circle2.setStyle("strokeWidth", "2");
circle2.setStyle("stroke", "#27ae60");
// Method 3: CSS string (like inline style attribute)
circle3.setStyle("fill: blue; stroke: navy; stroke-width: 2;");
// Method 4: Mixed – object for one property, then key‑value
circle4.setStyle({ fill: "orange" });
circle4.setStyle("stroke", "darkorange");
// All circles have inline styles that override any CSS or attributes
Understanding the Flexibility
// Object notation (most common)
element.setStyle({
fill: "purple",
strokeWidth: 4,
opacity: 0.5
});
// Property‑value pairs (useful for single properties)
element.setStyle("fill", "purple");
element.setStyle("strokeWidth", 4);
element.setStyle("opacity", 0.5);
// CSS string (useful when copying from CSS)
element.setStyle("fill: purple; stroke-width: 4; opacity: 0.5");
// Note: CSS properties use hyphens (stroke-width), but object properties use camelCase (strokeWidth)
Demonstrating Style Override
setStyle()로 적용한 인라인 스타일은 attr()로 설정한 속성을 덮어씁니다:
// Start with attributes
var rect = s.rect(50, 200, 100, 50).attr({
fill: "#3498db",
stroke: "#2c3e50",
strokeWidth: 2
});
// Apply an inline style that overrides the fill
rect.setStyle("fill", "orange");
// Result: The rectangle appears orange, despite the earlier attribute fill.