跳到主要内容

JavaScript SVG基础

SVG是什么?

SVG (Scalable Vector Graphics) 是一种基于XML的矢量图形格式,用于在网页上绘制二维图形。与位图格式(如JPEG、PNG)不同,SVG图形在放大时不会失真,因为它们是通过数学公式定义的形状和路径。

优势

SVG图形可以通过CSS样式化,通过JavaScript进行交互操作,是现代Web数据可视化的重要基础。

SVG的基本结构

SVG元素需要放在<svg>标签内,并可以设置宽度和高度:

html
<svg width="500" height="300">
<!-- SVG内容将放在这里 -->
</svg>

基本SVG图形

矩形 (Rectangle)

创建一个简单的矩形:

html
<svg width="500" height="300">
<rect x="50" y="50" width="200" height="100" fill="blue" />
</svg>

参数解释:

  • xy:矩形左上角的坐标
  • widthheight:矩形的宽度和高度
  • fill:填充颜色

圆形 (Circle)

绘制一个圆形:

html
<svg width="500" height="300">
<circle cx="250" cy="150" r="80" fill="red" />
</svg>

参数解释:

  • cxcy:圆心坐标
  • r:半径
  • fill:填充颜色

椭圆 (Ellipse)

椭圆与圆类似,但有两个半径:

html
<svg width="500" height="300">
<ellipse cx="250" cy="150" rx="100" ry="50" fill="green" />
</svg>

参数解释:

  • rx:x轴半径
  • ry:y轴半径

线段 (Line)

绘制一条线:

html
<svg width="500" height="300">
<line x1="50" y1="50" x2="450" y2="250" stroke="black" stroke-width="2" />
</svg>

参数解释:

  • x1y1:起点坐标
  • x2y2:终点坐标
  • stroke:线条颜色
  • stroke-width:线条宽度

多边形 (Polygon)

绘制多边形:

html
<svg width="500" height="300">
<polygon points="200,10 250,190 160,210" fill="yellow" />
</svg>

参数解释:

  • points:所有顶点坐标,格式为"x1,y1 x2,y2 x3,y3..."

折线 (Polyline)

与多边形类似,但不闭合:

html
<svg width="500" height="300">
<polyline points="20,20 40,25 60,40 80,120 120,140 200,180"
fill="none" stroke="orange" stroke-width="3" />
</svg>

路径 (Path)

路径是最灵活的SVG图形,可以创建复杂的形状:

html
<svg width="500" height="300">
<path d="M150 0 L75 200 L225 200 Z" fill="purple" />
</svg>

参数解释:

  • d:定义路径的命令和坐标
    • M:移动到某点
    • L:画线到某点
    • Z:闭合路径

使用JavaScript操作SVG

动态创建SVG元素

使用JavaScript可以动态创建SVG元素:

javascript
// 创建SVG元素
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("width", "500");
svg.setAttribute("height", "300");

// 创建圆形
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
circle.setAttribute("cx", "250");
circle.setAttribute("cy", "150");
circle.setAttribute("r", "80");
circle.setAttribute("fill", "blue");

// 将圆形添加到SVG中
svg.appendChild(circle);

// 将SVG添加到文档中
document.body.appendChild(svg);
备注

注意创建SVG元素需要使用document.createElementNS而不是document.createElement,并指定正确的命名空间。

修改SVG元素

可以通过JavaScript动态修改SVG元素的属性:

javascript
// 假设我们已经有了一个circle元素的引用
function animateCircle() {
let radius = 10;
const maxRadius = 100;

const intervalId = setInterval(() => {
circle.setAttribute("r", radius);
radius += 1;

if (radius > maxRadius) {
clearInterval(intervalId);
}
}, 20);
}

// 调用动画函数
animateCircle();

为SVG元素添加事件

SVG元素可以添加事件监听器,实现交互功能:

javascript
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
circle.setAttribute("cx", "250");
circle.setAttribute("cy", "150");
circle.setAttribute("r", "50");
circle.setAttribute("fill", "red");

// 添加鼠标悬停事件
circle.addEventListener("mouseover", () => {
circle.setAttribute("fill", "orange");
});

circle.addEventListener("mouseout", () => {
circle.setAttribute("fill", "red");
});

// 添加点击事件
circle.addEventListener("click", () => {
const currentRadius = parseInt(circle.getAttribute("r"));
circle.setAttribute("r", currentRadius + 10);
});

svg.appendChild(circle);

实际案例:简单的数据可视化柱状图

下面是一个使用SVG创建简单柱状图的例子:

javascript
// 数据
const data = [120, 150, 180, 90, 200, 130];
const svgWidth = 500;
const svgHeight = 300;
const barWidth = (svgWidth - 100) / data.length;

// 创建SVG元素
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("width", svgWidth);
svg.setAttribute("height", svgHeight);

// 计算最大值用于缩放
const maxValue = Math.max(...data);
const scale = (svgHeight - 50) / maxValue;

// 绘制每个柱子
data.forEach((value, index) => {
const barHeight = value * scale;
const bar = document.createElementNS("http://www.w3.org/2000/svg", "rect");

bar.setAttribute("x", 50 + index * barWidth);
bar.setAttribute("y", svgHeight - barHeight - 10);
bar.setAttribute("width", barWidth - 10);
bar.setAttribute("height", barHeight);
bar.setAttribute("fill", "steelblue");

// 添加悬停效果
bar.addEventListener("mouseover", () => {
bar.setAttribute("fill", "orange");

// 显示数值
const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
text.setAttribute("x", 50 + index * barWidth + (barWidth - 10) / 2);
text.setAttribute("y", svgHeight - barHeight - 15);
text.setAttribute("text-anchor", "middle");
text.setAttribute("id", "tooltip-" + index);
text.textContent = value;

svg.appendChild(text);
});

bar.addEventListener("mouseout", () => {
bar.setAttribute("fill", "steelblue");

// 移除数值显示
const text = document.getElementById("tooltip-" + index);
if (text) {
svg.removeChild(text);
}
});

svg.appendChild(bar);
});

// 添加X轴
const xAxis = document.createElementNS("http://www.w3.org/2000/svg", "line");
xAxis.setAttribute("x1", "50");
xAxis.setAttribute("y1", svgHeight - 10);
xAxis.setAttribute("x2", svgWidth - 50);
xAxis.setAttribute("y2", svgHeight - 10);
xAxis.setAttribute("stroke", "black");
xAxis.setAttribute("stroke-width", "2");

svg.appendChild(xAxis);

// 添加Y轴
const yAxis = document.createElementNS("http://www.w3.org/2000/svg", "line");
yAxis.setAttribute("x1", "50");
yAxis.setAttribute("y1", "10");
yAxis.setAttribute("x2", "50");
yAxis.setAttribute("y2", svgHeight - 10);
yAxis.setAttribute("stroke", "black");
yAxis.setAttribute("stroke-width", "2");

svg.appendChild(yAxis);

// 添加到DOM
document.body.appendChild(svg);

结合CSS美化SVG

SVG元素可以使用CSS样式:

html
<style>
.bar {
fill: steelblue;
transition: fill 0.3s ease;
}

.bar:hover {
fill: orange;
}

.axis {
stroke: #333;
stroke-width: 2;
}
</style>

<svg width="500" height="300">
<rect class="bar" x="50" y="50" width="50" height="200" />
<rect class="bar" x="110" y="100" width="50" height="150" />
<rect class="bar" x="170" y="150" width="50" height="100" />
<line class="axis" x1="50" y1="250" x2="300" y2="250" />
<line class="axis" x1="50" y1="50" x2="50" y2="250" />
</svg>

SVG的动画效果

SVG提供了内置的<animate>元素用于制作简单动画:

html
<svg width="500" height="300">
<circle cx="250" cy="150" r="50" fill="blue">
<animate
attributeName="r"
values="50;80;50"
dur="2s"
repeatCount="indefinite" />
<animate
attributeName="fill"
values="blue;purple;blue"
dur="2s"
repeatCount="indefinite" />
</circle>
</svg>

也可以使用JavaScript实现更复杂的动画:

javascript
function animateCircle(circle) {
let radius = 20;
let increasing = true;

setInterval(() => {
if (radius >= 100) increasing = false;
if (radius <= 20) increasing = true;

radius = increasing ? radius + 1 : radius - 1;
circle.setAttribute("r", radius);
}, 30);
}

const circle = document.querySelector("circle");
animateCircle(circle);

总结

SVG是一种强大的矢量图形格式,结合JavaScript可以创建丰富的交互式数据可视化。本文介绍了:

  • SVG的基本概念和优势
  • 常见SVG图形元素:矩形、圆形、椭圆、线段、多边形、路径等
  • 使用JavaScript创建和操作SVG元素
  • 为SVG元素添加事件处理
  • 实际案例:创建简单的交互式柱状图
  • SVG的样式和动画效果

掌握SVG和JavaScript的结合使用,是进入现代Web数据可视化领域的重要基础。在此基础上,您可以进一步学习D3.js等专业数据可视化库,创建更复杂的可视化作品。

练习建议

  1. 尝试创建一个简单的饼图
  2. 实现一个折线图展示随时间变化的数据
  3. 为柱状图添加更多交互功能,如点击切换颜色或显示详细信息
  4. 尝试结合实际数据(如CSV文件)实现可视化
  5. 探索SVG滤镜和渐变效果以增强视觉效果

附加资源