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>
参数解释:
x
、y
:矩形左上角的坐标width
、height
:矩形的宽度和高度fill
:填充颜色
圆形 (Circle)
绘制一个圆形:
html
<svg width="500" height="300">
<circle cx="250" cy="150" r="80" fill="red" />
</svg>
参数解释:
cx
、cy
:圆心坐标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>
参数解释:
x1
、y1
:起点坐标x2
、y2
:终点坐标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等专业数据可视化库,创建更复杂的可视化作品。
练习建议
- 尝试创建一个简单的饼图
- 实现一个折线图展示随时间变化的数据
- 为柱状图添加更多交互功能,如点击切换颜色或显示详细信息
- 尝试结合实际数据(如CSV文件)实现可视化
- 探索SVG滤镜和渐变效果以增强视觉效果