知识介绍
- 在视图缩放时,对SVG中的元素也进行缩放,使得text、circle等在放大后不会过于占据视野
- 对mainSVG中的蓝点增加双击强调的效果
- 对双击强调后的蓝点在lenSVG视图中,增加其他元素的半透明效果
代码分析
1 在视图缩放时,对SVG中的元素也进行缩放,使得text、circle等在放大后不会过于占据视野
- 对于需要控制的元素复制到变量
// 绘制Y坐标点的圆圈
const drawingCircle = g.selectAll('circle.drawingData')
.data(ypoints()) // 绑定数据
.enter().append('circle') // 创建圆元素
.attr('class', 'drawingData') // 设置类名
.attr('cx', d => x(d.coords[0])) // 设置圆心X坐标
.attr('cy', d => y(d.coords[1])) // 设置圆心Y坐标
.attr('r', 2) // 设置圆的半径
.attr('fill', 'red') // 设置圆的填充颜色
.on('mouseover', (event, d) => { // 鼠标悬停事件
const tooltip = d3.select('body') // 选择body元素创建tooltip
.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`) // 设置tooltip左位置
.style('top', `${event.pageY + 10}px`) // 设置tooltip顶部位置
.text(d.text); // 显示文本内容
})
.on('mouseout', () => {
d3.select('.tooltip').remove(); // 鼠标移出时移除tooltip
});
// 绘制X坐标点的文本标签
const textElements = g.selectAll('text')
.data(xpoints()) // 绑定数据
.enter().append('text') // 创建文本元素
.attr('x', d => x(d.coords[0]) - 5) // 设置文本X位置
.attr('y', d => y(d.coords[1]) + 5) // 设置文本Y位置
.text(d => d.name) // 设置文本内容
.attr('font-family', 'sans-serif') // 设置字体
.attr('font-size', '10px') // 设置字体大小
.attr('fill', 'black') // 设置文本颜色
.attr('opacity', 0); // 初始设置为不可见
- 在zoom行为中修改对应元素的属性
// 添加缩放行为
const zoomBehavior = zoom()
.scaleExtent([0.5, 5]) // 设置缩放范围
.on('zoom', (event) => {
g.attr('transform', event.transform); // 应用缩放变换到g元素
updateLenSVG(event.transform); // 更新Len SVG的视图
const fontSize= 12 / event.transform.k; // 根据缩放比例调整字体大小
textElements.attr('font-size', `${fontSize}px`);
// 根据缩放比例设置 opacity
if (event.transform.k > 1.5) { // 假设1.5是可见的阈值
textElements.attr('opacity', 1); // 可见
} else {
textElements.attr('opacity', 0); // 不可见
}
drawingCircle.attr('r', 2 / (event.transform.k*0.6)); // 根据缩放比例调整圆的半径
});
2 对mainSVG中的蓝点增加双击强调的效果
// 选择所有的圆圈,绑定数据,并创建新的圆圈
g.selectAll('circle.blue')
.data(data()) // 绑定数据
.enter().append('circle') // 创建新的圆圈
.attr('class', 'blue') // 添加类名
.attr('cx', d => x(d.x)) // 设置圆圈的x坐标
.attr('cy', d => y(d.y)) // 设置圆圈的y坐标
.attr('r', 5) // 设置圆圈的半径
.attr('fill', 'steelblue') // 设置圆圈的颜色
.on('dblclick', function(event, d) {
// 阻止双击事件的默认行为
event.preventDefault();
// 双击时添加土黄色圆环
const circle = d3.select(this);
const cx = circle.attr('cx');
const cy = circle.attr('cy');
g.append('circle') // 在同一个g元素中添加新的圆圈
.attr('class', 'highlight') // 可以给这个圆圈添加一个类名以便于后续操作
.attr('cx', cx) // 设置与被点击圆圈相同的x坐标
.attr('cy', cy) // 设置与被点击圆圈相同的y坐标
.attr('r', 10) // 设置土黄色圆圈的半径(稍大于原始圆圈)
.attr('fill', 'none') // 填充颜色设为无
.attr('stroke', 'sandybrown') // 设置边框颜色为土黄色
.attr('stroke-width', 2); // 设置边框宽度
});
3 对双击强调后的蓝点在lenSVG视图中,增加其他元素的半透明效果
请注意:当selectedPoints的数据为浮点数时,可能会比较异常,转换成字符串再比较即可
- 创建selectedPoints信号量,保存被选中的蓝点
const [selectedPoints, setSelectedPoints] = createSignal([]);
- 在蓝点的双击事件中,将被选中的蓝点保存到selectedPoints信号量中
.on('dblclick', function(event, d) {
// 阻止双击事件的默认行为
event.preventDefault();
// 获取当前选中的蓝点数组
const currentSelected = selectedPoints();
// 检查该点是否已经被选中
if (currentSelected.includes(d)) {
// 如果已选中,则移除
setSelectedPoints(currentSelected.filter(point => point !== d));
} else {
// 如果未选中,则添加到选中状态中
setSelectedPoints([...currentSelected, d]);
}
// 双击时添加土黄色圆环
const circle = d3.select(this);
const cx = circle.attr('cx');
const cy = circle.attr('cy');
g.append('circle') // 在同一个g元素中添加新的圆圈
.attr('class', 'highlight') // 可以给这个圆圈添加一个类名以便于后续操作
.attr('cx', cx) // 设置与被点击圆圈相同的x坐标
.attr('cy', cy) // 设置与被点击圆圈相同的y坐标
.attr('r', 10) // 设置土黄色圆圈的半径(稍大于原始圆圈)
.attr('fill', 'none') // 填充颜色设为无
.attr('stroke', 'sandybrown') // 设置边框颜色为土黄色
.attr('stroke-width', 2); // 设置边框宽度
});
- 在updateLenSVG中,根据selectedPoints信号量中的数据,对其他元素进行半透明处理
// 生成配对数据并在成对的点之间画线
const pairedData = data().map((d, i) => ({
blue: d,
red: redData()[i],
}));
g.selectAll('line.connection').remove(); // 移除旧的线条
// 更新lenSVG中的内容
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', (d) => selectedPoints().includes(d.blue) ? 'black' : 'rgba(0, 0, 0, 0.2)') // 设置为黑色或半透明
.attr('stroke-width', 1);
标签:15,attr,知识,SolidJS,设置,圆圈,const,circle,event
From: https://www.cnblogs.com/Frey-Li/p/18416059