<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>分段填充折线图</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
.tooltip {
position: absolute;
background-color: rgba(255, 255, 255, 0.9);
border: 1px solid #ccc;
padding: 5px;
font-size: 12px;
pointer-events: none;
opacity: 0;
}
.line {
fill: none;
stroke: black;
stroke-width: 2;
}
</style>
</head>
<body>
<div id="chart"></div>
<div class="tooltip" id="tooltip"></div>
<script>
// 示例数据
const data = [
{ time: "2025-01-01", value: 10, description: "说明1" },
{ time: "2025-01-02", value: 15, description: "说明2" },
{ time: "2025-01-03", value: 20, description: "说明3" },
{ time: "2025-01-04", value: 25, description: "说明4" },
{ time: "2025-01-05", value: 30, description: "说明5" },
{ time: "2025-01-06", value: 35, description: "说明6" },
{ time: "2025-01-07", value: 40, description: "说明7" },
{ time: "2025-01-08", value: 45, description: "说明8" },
{ time: "2025-01-09", value: 50, description: "说明9" },
{ time: "2025-01-10", value: 55, description: "说明10" },
{ time: "2025-01-11", value: 60, description: "说明11" },
{ time: "2025-01-12", value: 65, description: "说明12" },
{ time: "2025-01-13", value: 70, description: "说明13" },
{ time: "2025-01-14", value: 75, description: "说明14" },
{ time: "2025-01-15", value: 80, description: "说明15" },
{ time: "2025-01-16", value: 85, description: "说明16" },
{ time: "2025-01-17", value: 90, description: "说明17" },
{ time: "2025-01-18", value: 95, description: "说明18" },
{ time: "2025-01-19", value: 100, description: "说明19" },
{ time: "2025-01-20", value: 105, description: "说明20" }
];
// 设置图表尺寸
const margin = { top: 20, right: 30, bottom: 30, left: 40 };
const width = 800 - margin.left - margin.right;
const height = 400 - margin.top - margin.bottom;
// 创建 SVG 容器
const svg = d3.select("#chart")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
// 解析时间格式
const parseTime = d3.timeParse("%Y-%m-%d");
// 格式化数据
data.forEach(d => {
d.time = parseTime(d.time);
d.value = +d.value;
});
// 设置比例尺
const x = d3.scaleTime()
.domain(d3.extent(data, d => d.time))
.range([0, width]);
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([height, 0]);
// 添加 X 轴
svg.append("g")
.attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(x));
// 添加 Y 轴
svg.append("g")
.call(d3.axisLeft(y));
// 创建折线生成器
const line = d3.line()
.x(d => x(d.time))
.y(d => y(d.value));
// 绘制折线
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
// 分段填充颜色
const first10 = data.slice(0, 10);
const last10 = data.slice(-10);
const middle = data.slice(10, -10);
// 填充前十个时间段的绿色区域
svg.append("path")
.datum(first10)
.attr("fill", "green")
.attr("opacity", 0.3)
.attr("d", d3.area()
.x(d => x(d.time))
.y0(height)
.y1(d => y(d.value))
);
// 填充中间时间段的蓝色区域
svg.append("path")
.datum(middle)
.attr("fill", "blue")
.attr("opacity", 0.3)
.attr("d", d3.area()
.x(d => x(d.time))
.y0(height)
.y1(d => y(d.value))
);
// 填充后十个时间段的红色区域
svg.append("path")
.datum(last10)
.attr("fill", "red")
.attr("opacity", 0.3)
.attr("d", d3.area()
.x(d => x(d.time))
.y0(height)
.y1(d => y(d.value))
);
// 添加悬停交互
const tooltip = d3.select("#tooltip");
svg.selectAll(".dot")
.data(data)
.enter()
.append("circle")
.attr("class", "dot")
.attr("cx", d => x(d.time))
.attr("cy", d => y(d.value))
.attr("r", 5)
.attr("fill", "steelblue")
.on("mouseover", (event, d) => {
tooltip.style("opacity", 1)
.html(`时间: ${d3.timeFormat("%Y-%m-%d")(d.time)}<br>数值: ${d.value}<br>说明: ${d.description}`)
.style("left", `${event.pageX + 5}px`)
.style("top", `${event.pageY - 20}px`);
})
.on("mouseout", () => {
tooltip.style("opacity", 0);
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>交互式图表</title>
<!-- 引入 Plotly.js -->
<script src="https://cdn.plot.ly/plotly-2.24.1.min.js"></script>
</head>
<body>
<div id="chart"></div>
<script>
// 读取CSV文件(假设文件名为 data.csv)
fetch('data.csv')
.then(response => response.text())
.then(csvText => {
// 解析CSV数据
const rows = csvText.split('\n');
const x = [], y = [];
rows.forEach((row, index) => {
if (index === 0) return; // 跳过标题行
const [xVal, yVal] = row.split(',');
x.push(parseFloat(xVal));
y.push(parseFloat(yVal));
});
// 绘制图表
Plotly.newPlot('chart', [{
x: x,
y: y,
type: 'scatter',
mode: 'lines+markers',
marker: { color: 'blue' },
line: { shape: 'spline' }
}], {
title: '交互式数据图表',
xaxis: { title: 'X轴' },
yaxis: { title: 'Y轴' },
hovermode: 'closest'
});
});
</script>
</body>
</html>
import pandas as pd
import plotly.express as px
# 1. 读取CSV文件
df = pd.read_csv("data.csv")
# 2. 创建交互式图表
fig = px.line(
df, x='x', y='y',
title='Python生成的交互式图表',
markers=True, # 显示数据点
line_shape='spline' # 平滑曲线
)
# 3. 自定义悬停效果和样式
fig.update_traces(
hoverinfo='x+y', # 悬停显示x和y值
line=dict(width=2, color='royalblue'),
marker=dict(size=8, color='firebrick')
)
# 4. 保存为HTML文件
fig.write_html("interactive_chart.html")