mirror of
https://github.com/kay-is/react-from-zero.git
synced 2026-01-11 07:38:15 -05:00
142 lines
4.0 KiB
HTML
142 lines
4.0 KiB
HTML
<!doctype html>
|
|
|
|
<title>16 Advanced Integration - React From Zero</title>
|
|
|
|
<script src="https://unpkg.com/react@16.4.0/umd/react.development.js"></script>
|
|
<script src="https://unpkg.com/react-dom@16.4.0/umd/react-dom.development.js"></script>
|
|
<script src="https://unpkg.com/create-react-class@15.6.3/create-react-class.js"></script>
|
|
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
|
|
|
<script src="https://unpkg.com/d3@4.7.3/build/d3.min.js">
|
|
// Sometimes we need to integrate more complex
|
|
// libraries. Libraries that want to use the
|
|
// DOM directly or require asynchronous interaction.
|
|
// In this example we use D3.js, a free InfoVis library.
|
|
</script>
|
|
|
|
<div id="app"></div>
|
|
|
|
<script type="text/babel">
|
|
// Since D3 needs to interact directly with the DOM we
|
|
// should use a component class, because it can store
|
|
// references to its DOM-elements.
|
|
var Visual = createReactClass({
|
|
// We simply render an empty canvas and tell React to
|
|
// store its reference after the render
|
|
render: function() {
|
|
return <canvas ref={this.handleRef} width={500} height={500} />;
|
|
},
|
|
|
|
handleRef: function(canvas) {
|
|
this.canvas = canvas;
|
|
},
|
|
|
|
// After the first render, we grab the reference
|
|
// to the canvas element in the DOM and pass it
|
|
// to the library
|
|
componentDidMount: function() {
|
|
// Here we also use some additional color configuration
|
|
drawGraph(this.canvas, this.props.color);
|
|
},
|
|
|
|
// We also have some fine-granular control over the re-render
|
|
// With the use of this lifecylce method
|
|
shouldComponentUpdate: function(nextProps, nextState) {
|
|
// Here we could tell our library the new data for props
|
|
// or state, so it can update the DOM elements on its own
|
|
|
|
// At the end we always return false so our render method
|
|
// isn't called and the canvas element isn't replaced
|
|
return false;
|
|
},
|
|
|
|
// This lifecycle method can be used to free resources
|
|
// before the component will be removed from the DOM.
|
|
// Our canvas will be removed for sure, but often there
|
|
// is state for the library, other objects, listeners etc.
|
|
// they could be stored on the component and should be
|
|
// deleted to prevent memory leaks
|
|
componentWillUnmount() {}
|
|
});
|
|
|
|
// Now we can use the library as a component
|
|
// No need for global IDs, every instance has its own canvas
|
|
// reference stored, also its own color property
|
|
var reactElement = (
|
|
<div>
|
|
<Visual color="#f00" />
|
|
<Visual color="#0f0" />
|
|
<Visual color="#00f" />
|
|
</div>
|
|
);
|
|
|
|
ReactDOM.render(reactElement, document.getElementById("app"));
|
|
|
|
// Wrapping the library interaction into a function
|
|
function drawGraph(canvas, strokeColor) {
|
|
// An example from
|
|
// http://bl.ocks.org/mbostock/1b64ec067fcfc51e7471d944f51f1611
|
|
// its released under the GPL-V3
|
|
|
|
var n = 20;
|
|
|
|
var nodes = d3.range(n * n).map(function(i) {
|
|
return { index: i };
|
|
});
|
|
|
|
var links = [];
|
|
|
|
for (var y = 0; y < n; ++y) {
|
|
for (var x = 0; x < n; ++x) {
|
|
if (y > 0)
|
|
links.push({ source: (y - 1) * n + x, target: y * n + x });
|
|
if (x > 0)
|
|
links.push({ source: y * n + (x - 1), target: y * n + x });
|
|
}
|
|
}
|
|
|
|
d3.forceSimulation(nodes)
|
|
.force("charge", d3.forceManyBody().strength(-30))
|
|
.force(
|
|
"link",
|
|
d3
|
|
.forceLink(links)
|
|
.distance(20)
|
|
.iterations(10)
|
|
)
|
|
.on("tick", ticked);
|
|
|
|
var context = canvas.getContext("2d");
|
|
var width = canvas.width;
|
|
var height = canvas.height;
|
|
|
|
function ticked() {
|
|
context.clearRect(0, 0, width, height);
|
|
context.save();
|
|
context.translate(width / 2, height / 2);
|
|
|
|
context.beginPath();
|
|
links.forEach(drawLink);
|
|
context.strokeStyle = "#aaa";
|
|
context.stroke();
|
|
|
|
context.beginPath();
|
|
nodes.forEach(drawNode);
|
|
context.fill();
|
|
context.strokeStyle = strokeColor;
|
|
context.stroke();
|
|
|
|
context.restore();
|
|
}
|
|
|
|
function drawLink(d) {
|
|
context.moveTo(d.source.x, d.source.y);
|
|
context.lineTo(d.target.x, d.target.y);
|
|
}
|
|
|
|
function drawNode(d) {
|
|
context.moveTo(d.x + 3, d.y);
|
|
context.arc(d.x, d.y, 3, 0, 2 * Math.PI);
|
|
}
|
|
}
|
|
</script> |