In react project, I would like to use a tangled tree graph like - tangled-tree-visualization-ii
How can I use it? Since D3 is open source library, is above example code is also open source to use?
I m beginner in D3. So far,
1. Installed the D3 library with npm install d3 --save
2. Created D3 basic bar chart to check d3 is working
Instead of bar chart wanted to use tangled-tree-visualization shared above. But it seems it uses generated minified runtime.js by observablehq.
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;
Here is an example following their guideline but using react hooks.
When the component is mounted, you have to instance the runtime, specify the cells you want to mount and the html nodes, in this case using ref
to point to a div
element
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
is a reference to a mutable speed
cell from the observable notebook. When there is an updated on the react input range you useEffect
to update inside the notebook, using animationSpeed
reference
useEffect(() => {
if(animationSpeed.current){
animationSpeed.current.value = speed;
}
},[speed]);
Here is the functional example.
ps. there is a bit o hack to load the modules inside stackoverflow code snippets
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>