d3.js
Utilizzando D3 con altri framework
Ricerca…
Componente D3.js con ReactJS
Questo esempio è basato su un post sul blog di Nicolas Hery . Utilizza le classi ES6 e i metodi del ciclo di vita di ReactJS per mantenere aggiornato il componente D3
d3_react.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello, d3React!</title>
<style>
.d3Component {
width: 720px;
height: 120px;
}
</style>
</head>
<script src="https://fb.me/react-15.2.1.min.js"></script>
<script src="https://fb.me/react-dom-15.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<body>
<div id="app" />
<script type="text/babel" src="d3_react.js"></script>
</body>
</html>
d3_react.js
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
d3React: new d3React()
};
this.getd3ReactState = this.getd3ReactState.bind(this);
}
getd3ReactState() {
// Using props and state, calculate the d3React state
return ({
data: {
x: 0,
y: 0,
width: 42,
height: 17,
fill: 'red'
}
});
}
componentDidMount() {
var props = {
width: this._d3Div.clientWidth,
height: this._d3Div.clientHeight
};
var state = this.getd3ReactState();
this.state.d3React.create(this._d3Div, props, state);
}
componentDidUpdate(prevProps, prevState) {
var state = this.getd3ReactState();
this.state.d3React.update(this._d3Div, state);
}
componentWillUnmount() {
this.state.d3React.destroy(this._d3Div);
}
render() {
return (
<div>
<h1>{this.props.message}</h1>
<div className="d3Component" ref={(component) => { this._d3Div = component; } } />
</div>
);
}
}
class d3React {
constructor() {
this.create = this.create.bind(this);
this.update = this.update.bind(this);
this.destroy = this.destroy.bind(this);
this._drawComponent = this._drawComponent.bind(this);
}
create(element, props, state) {
console.log('d3React create');
var svg = d3.select(element).append('svg')
.attr('width', props.width)
.attr('height', props.height);
this.update(element, state);
}
update(element, state) {
console.log('d3React update');
this._drawComponent(element, state.data);
}
destroy(element) {
console.log('d3React destroy');
}
_drawComponent(element, data) {
// perform all drawing on the element here
var svg = d3.select(element).select('svg');
svg.append('rect')
.attr('x', data.x)
.attr('y', data.y)
.attr('width', data.width)
.attr('height', data.height)
.attr('fill', data.fill);
}
}
ReactDOM.render(<App message="Hello, D3.js and React!"/>, document.getElementById('app'));
Inserire i contenuti di d3_react.html
e d3_react.js
nella stessa directory e navigare un browser Web nel file d3React.html. Se tutto va bene, vedrai un'intestazione che indica Hello, D3.js and React!
reso dal componente React e un rettangolo rosso sotto dal componente D3 personalizzato.
React utilizza i riferimenti per "raggiungere" l'istanza del componente. I metodi del ciclo di vita della classe d3React
richiedono a questo riferimento di aggiungere, modificare e rimuovere elementi DOM. La classe d3React
può essere estesa per creare più componenti personalizzati e inserita dovunque un div.d3Component
viene creato da React.
D3js con angolare
Utilizzando D3js con Angular puoi aprire nuovi fronti di possibilità come l'aggiornamento live dei grafici non appena i dati vengono aggiornati. Possiamo incapsulare la funzionalità completa del grafico all'interno di una direttiva Angular, che lo rende facilmente riutilizzabile.
index.html >>
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script data-require="[email protected]" data-semver="1.4.1" src="https://code.angularjs.org/1.4.1/angular.js"></script>
<script src="app.js"></script>
<script src="bar-chart.js"></script>
</head>
<body>
<div ng-controller="MyCtrl">
<!-- reusable d3js bar-chart directive, data is sent using isolated scope -->
<bar-chart data="data"></bar-chart>
</div>
</body>
</html>
Possiamo passare i dati al grafico utilizzando il controller e osservare eventuali modifiche nei dati per abilitare l'aggiornamento in tempo reale del grafico nella direttiva:
app.js >>
angular.module('myApp', [])
.controller('MyCtrl', function($scope) {
$scope.data = [50, 40, 30];
$scope.$watch('data', function(newVal, oldVal) {
$scope.data = newVal;
}, true);
});
Infine, la definizione della direttiva. Il codice che scriviamo per creare e manipolare il grafico si troverà nella funzione di collegamento della direttiva.
Nota che abbiamo inserito un ambito. $ Guarda anche nella direttiva, per aggiornarlo non appena il controller passa i nuovi dati. Stiamo riassegnando nuovi dati alla nostra variabile di dati se c'è qualche cambiamento di dati e poi chiamando la funzione repaintChart (), che esegue il re-rendering del grafico.
bar-chart.js >>
angular.module('myApp').directive('barChart', function($window) {
return {
restrict: 'E',
replace: true,
scope: {
data: '='
},
template: '<div id="bar-chart"></div>',
link: function(scope, element, attrs, fn) {
var data = scope.data;
var d3 = $window.d3;
var rawSvg = element;
var colors = d3.scale.category10();
var canvas = d3.select(rawSvg[0])
.append('svg')
.attr("width", 300)
.attr("height", 150);
// watching for any changes in the data
// if new data is detected, the chart repaint code is run
scope.$watch('data', function(newVal, oldVal) {
data = newVal;
repaintChart();
}, true);
var xscale = d3.scale.linear()
.domain([0, 100])
.range([0, 240]);
var yscale = d3.scale.linear()
.domain([0, data.length])
.range([0, 120]);
var bar = canvas.append('g')
.attr("id", "bar-group")
.attr("transform", "translate(10,20)")
.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr("class", "bar")
.attr("height", 15)
.attr("x", 0)
.attr("y", function(d, i) {
return yscale(i);
})
.style("fill", function(d, i) {
return colors(i);
})
.attr("width", function(d) {
return xscale(d);
});
// changing the bar widths according to the changes in data
function repaintChart() {
canvas.selectAll('rect')
.data(data)
.transition()
.duration(800)
.attr("width", function(d) {
return xscale(d);
})
}
}
}
});
Grafico D3.js con Angular v1
HTML:
<div ng-app="myApp" ng-controller="Controller">
<some-chart data="data"></some-chart>
</div>
Javascript:
angular.module('myApp', [])
.directive('someChart', function() {
return {
restrict: 'E',
scope: {data: '=data'},
link: function (scope, element, attrs) {
var chartElement = d3.select(element[0]);
// here you have scope.data and chartElement
// so you may do what you want
}
};
});
function Controller($scope) {
$scope.data = [1,2,3,4,5]; // useful data
}