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

知识介绍

  1. 在div容器中并列两个SVG元素 -> 对div容器设置display: "flex"
  2. 使用d3创建散点图
  3. 使用d3的scaleLinear函数创建x轴和y轴的比例尺
  4. 对d3的svg元素增加tooltip提示
  5. 对svg元素增加zoom功能
  6. 使用d3在svg中画线
  7. 对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功能

  1. 引用d3-zoom模块
  2. 添加事件监听器
  3. 对指定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'; // 其他情况使用红色
          }
        });
posted @ 2024-09-14 10:30  梧桐灯下江楚滢  阅读(39)  评论(0)    收藏  举报