SolidJS-每日小知识(9/15)

知识介绍

  1. 在视图缩放时,对SVG中的元素也进行缩放,使得text、circle等在放大后不会过于占据视野
  2. 对mainSVG中的蓝点增加双击强调的效果
  3. 对双击强调后的蓝点在lenSVG视图中,增加其他元素的半透明效果

代码分析

1 在视图缩放时,对SVG中的元素也进行缩放,使得text、circle等在放大后不会过于占据视野

  1. 对于需要控制的元素复制到变量
        // 绘制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); // 初始设置为不可见  
  1. 在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的数据为浮点数时,可能会比较异常,转换成字符串再比较即可

  1. 创建selectedPoints信号量,保存被选中的蓝点
    const [selectedPoints, setSelectedPoints] = createSignal([]);
  2. 在蓝点的双击事件中,将被选中的蓝点保存到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); // 设置边框宽度
});

  1. 在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);
posted @   梧桐灯下江楚滢  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示