知识介绍
- 在div容器中并列两个SVG元素 -> 对div容器设置display: "flex"
- 使用d3创建散点图
- 使用d3的scaleLinear函数创建x轴和y轴的比例尺
- 对d3的svg元素增加tooltip提示
- 对svg元素增加zoom功能
- 使用d3在svg中画线
- 对d3中某个元素的attr属性使用函数表达式return值
代码分析
2 使用d3创建散点图
import { createSignal, onMount } from 'solid-js';
import * as d3 from 'd3';
const ScatterPlot = () => {
// 使用SolidJS的createSignal来创建一个响应式的数据信号
const [data, setData] = createSignal([
{ x: 10, y: 20 },
{ x: 40, y: 90 },
{ x: 80, y: 50 },
{ x: 90, y: 10 },
{ x: 60, y: 70 },
]);
// 定义一个SVG元素的引用
let svgRef: SVGSVGElement | undefined;
// 在组件挂载时执行的逻辑
onMount(() => {
// 选择SVG元素并设置其宽度和高度
const svg = d3.select(svgRef)
.attr('width', 1000)
.attr('height', 700);
// 定义边距
const margin = { top: 20, right: 20, bottom: 30, left: 40 };
// 计算绘图区域的宽度和高度
const width = +svg.attr('width') - margin.left - margin.right;
const height = +svg.attr('height') - margin.top - margin.bottom;
// 创建x轴的比例尺
const x = d3.scaleLinear()
.domain([0, d3.max(data(), d => d.x) || 0]) // 设置x轴的范围
.range([0, width]); // 设置x轴的输出范围
// 创建y轴的比例尺
const y = d3.scaleLinear()
.domain([0, d3.max(data(), d => d.y) || 0]) // 设置y轴的范围
.range([height, 0]); // 设置y轴的输出范围
// 在SVG中添加一个g元素,并应用边距的平移变换
const g = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
// 选择所有的圆圈,绑定数据,并创建新的圆圈
g.selectAll('circle')
.data(data()) // 绑定数据
.enter().append('circle') // 创建新的圆圈
.attr('cx', d => x(d.x)) // 设置圆圈的x坐标
.attr('cy', d => y(d.y)) // 设置圆圈的y坐标
.attr('r', 5) // 设置圆圈的半径
.attr('fill', 'steelblue'); // 设置圆圈的颜色
// 添加x轴
g.append('g')
.attr('transform', `translate(0,${height})`) // 将x轴平移到底部
.call(d3.axisBottom(x)); // 调用d3的x轴生成函数
// 添加y轴
g.append('g')
.call(d3.axisLeft(y)); // 调用d3的y轴生成函数
});
// 返回SVG元素
return (
<svg ref={svgRef}></svg>
);
};
// 导出组件
export default ScatterPlot;
3 使用d3的scaleLinear函数创建x轴和y轴的比例尺
请注意:若数据集中在一个区间时,使用该数据中最小值和最大值作为数据域的两侧
const x=d3.scaleLinear()
.domain([(d3.min(xpoints(),d => d.coords[0]))-10 || 0,d3.max(xpoints(),d => d.coords[0])+10 || 0])
.range([0,width]);
const y=d3.scaleLinear()
.domain([d3.min(ypoints(),d => d.coords[1])-50 || 0,d3.max(ypoints(),d => d.coords[1])+50 || 0])
.range([height,0]);
4 对d3的svg元素增加tooltip提示
- 核心是'mouseover'和'mouseout'事件的绑定
// 选择所有的圆圈,绑定数据,并创建新的圆圈
g.selectAll('circle')
.data(data()) // 绑定数据
.enter().append('circle') // 创建新的圆圈
.attr('cx', d => x(d.x)) // 设置圆圈的x坐标
.attr('cy', d => y(d.y)) // 设置圆圈的y坐标
.attr('r', 5) // 设置圆圈的半径
.attr('fill', 'steelblue') // 设置圆圈的颜色
.on('mouseover', (event, d) => {
// 鼠标悬停时显示工具提示
const tooltip = d3.select('body')
.append('div')
.attr('class', 'tooltip')
.style('position', 'absolute')
.style('background-color', 'white')
.style('border', '1px solid black')
.style('padding', '5px')
.style('pointer-events', 'none')
.style('left', `${event.pageX + 10}px`)
.style('top', `${event.pageY + 10}px`)
.text('圆圈');
})
.on('mouseout', () => {
// 鼠标移出时移除工具提示
d3.select('.tooltip').remove();
});
5 对svg元素增加zoom功能
- 引用d3-zoom模块
- 添加事件监听器
- 对指定svg元素绑定事件监听器
import {zoom} from 'd3-zoom';
// 添加缩放事件监听器
const zoomBehavior = zoom()
.scaleExtent([0.5, 5]) // 设置缩放范围
.on('zoom', (event) => {
g.attr('transform', event.transform); // 应用缩放变换
});
yourSvgElement.call(zoomBehavior); // 将缩放行为应用到SVG元素
6 使用d3在svg中画线
// 生成配对数据并在成对的点之间画线
const pairedData = data().map((d, i) => ({
blue: d,
red: redData()[i],
}));
g.selectAll('line.connection')
.data(pairedData)
.enter().append('line')
.attr('class', 'connection')
.attr('x1', d => x(d.blue.x))
.attr('y1', d => y(d.blue.y))
.attr('x2', d => x(d.red.x))
.attr('y2', d => y(d.red.y))
.attr('stroke', 'black')
.attr('stroke-width', 1);
7 对d3中某个元素的attr属性使用函数表达式return值
g.selectAll('line.connection')
.data(connections())
.enter().append('line')
.attr('class','connection')
.attr('x1',d => x(d.X_point[0]))
.attr('y1',d => y(d.X_point[1]))
.attr('x2',d => x(d.Y_transformed_point[0]))
.attr('y2',d => y(d.Y_transformed_point[1]))
.attr('stroke-width',1)
.attr('stroke', d => {
// 根据条件设置不同的颜色
if (d.matched === 1) {
return 'green';
}
else {
return 'orange'; // 其他情况使用红色
}
});
标签:13,const,attr,svg,知识,SolidJS,圆圈,data,d3
From: https://www.cnblogs.com/Frey-Li/p/18413459