如何在 React 项目中使用 observablehq D3 graph?

How to use observablehq D3 graph in React project?

在 React 项目中,我想使用像这样的纠结树图 - tangled-tree-visualization-ii

我该如何使用它?由于D3是开源库,上面的示例代码是否也开源使用?

我是 D3 的初学者。迄今为止, 1. 使用 npm install d3 --save 安装 D3 库 2. 创建 D3 基本条形图以检查 d3 是否正常工作

想要使用上面共享的纠结树可视化而不是条形图。但它似乎使用了 observablehq 生成的缩小 runtime.js。

BarChart.js

import React from 'react';
import * as d3 from 'd3';

import { Runtime, Inspector } from "@observablehq/runtime";
import define from "@nitaku/tangled-tree-visualization-ii";

class BarChart extends React.Component {
    componentDidMount() {
        this.drawChart();
    }

    drawChart() {
        const data = this.props.data;
        const svg = d3.select("body").append("svg")
            .attr("width", this.props.width)
            .attr("height", this.props.height);

        const h = this.props.height;

        svg.selectAll("rect")
            .data(data)
            .enter()
            .append("rect")
            .attr("x", (d, i) => i * 70)
            .attr("y", (d, i) => h - 10 * d)
            .attr("width", 65)
            .attr("height", (d, i) => d * 10)
            .attr("fill", "green")

        svg.selectAll("text")
            .data(data)
            .enter()
            .append("text")
            .text((d) => d)
            .attr("x", (d, i) => i * 70)
            .attr("y", (d, i) => h - (10 * d) - 3)

        //selection.attr(“property”, (d, i) => {})
    }

    render() {
        return <div id={"#" + this.props.id}></div>
    }

}

export default BarChart;

App.js

import React from 'react';
import BarChart from './BarChart.js';
import './App.css';

class App extends React.Component {

  state = {
    data: [12, 5, 6, 6, 9, 10],
    width: 700,
    height: 500,
    id: "root"
  }

  render() {
    return (
      <div className="App">
        <BarChart data={this.state.data} width={this.state.width} height={this.state.height} />
      </div>
    );
  }
}

export default App;

这是一个遵循他们的 guideline 但使用反应钩子的例子。

安装组件时,您必须实例化运行时,指定要安装的单元格和 html 节点,在本例中使用 ref 指向 [=15] =] 元素

  useEffect(() => {
    const runtime = new Runtime();
    runtime.module(notebook, name => {
      if (name === "animation") {
        return new Inspector(animationRef.current);
      }
       if (name === "mutable speed") {
        return {fulfilled: (value) => {
          animationSpeed.current = value;
        }};
      }
    });
  },[]);

animationSpeed 是对可观察笔记本中的 mutable speed 单元格的引用。当反应输入范围有更新时,您 useEffect 在笔记本内部更新,使用 animationSpeed 参考

useEffect(() => {
  if(animationSpeed.current){
    animationSpeed.current.value = speed;
    }
  },[speed]);

这是功能示例。

ps。在 Whosebug 代码片段中加载模块有点 o hack

const {
  useState,
  useEffect,
  useRef,
} = React;

const App = () => {
  const [speed, setSpeed] = useState(1);
  const animationRef = useRef();
  const animationSpeed = useRef();
  
  useEffect(() => {
    const runtime = new Runtime();
    runtime.module(notebook, name => {
      if (name === "animation") {
        return new Inspector(animationRef.current);
      }
       if (name === "mutable speed") {
        return {fulfilled: (value) => {
          animationSpeed.current = value;
        }};
      }
    });
  },[]);
  
  useEffect(() => {
  if(animationSpeed.current){
    animationSpeed.current.value = speed;
    }
  },[speed]);

  return (
  <div className="App">
    <small>Speed: {speed}</small>
    <input type="range"
            min="0"
            max="5"
            step="0.1"
            value={speed}
            onChange={(event)=> setSpeed(event.target.valueAsNumber)} />
     <div ref={animationRef}></div>

  </div>
  );
};

// Render
ReactDOM.render( <App / > ,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
<script type="module">
  import {Runtime, Inspector} from "https://cdn.jsdelivr.net/npm/@observablehq/runtime@4/dist/runtime.js"; import notebook from "https://api.observablehq.com/@observablehq/how-to-embed-a-notebook-in-a-react-app.js?v=3";
  // hack to make module packages global, so the babel transpile code can see it
  window.Runtime = Runtime;
  window.Inspector = Inspector;
  window.notebook = notebook;
</script>