Ottmar Gobrecht
DOAG APEX connect 2015, Düsseldorf
d3js.org github.com/mbostock/d3/wiki/Gallery
Das könnte immer so weiter gehen …
Live im Browser…
<!DOCTYPE html><html><head><title>SVG Beispiel</title></head><body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<svg id="Beispiel_1" style="width:490; height:140;">
<rect x="10" y="10" height="120" width="160" fill="#ff6600"/>
<ellipse cx="270" cy="70" rx="120" ry="40" fill="green"/>
<line x1="40" y1="40" x2="480" y2="120" stroke="blue"/>
</svg>
JavaScript: Bitte in Konsole ausführen
d3.select('svg#Beispiel_1').append('circle')
.attr('cx','420')
.attr('cy','70')
.attr('r','60')
.style('stroke','red')
.style('fill','lightsteelblue')
.style('fill-opacity',0.5);
Anmerkung:
fill
stroke
Schleife über alle Elemente: JavaScript
var p = document.getElementsByTagName('p');
for (var i = 0; i < p.length; i++) {
var pi = p.item(i);
pi.style.setProperty('color','red', null);
}
Schleife über alle Elemente: D3
d3.selectAll('p').style('color','red');
Anmerkung:
Wie man Daten an das DOM bindet
Eine Data Join Live Übertragung direkt aus … … dem Browser:
Ein bereits existierendes Element
<div id="Beispiel_2">
<p style="color:green;">Ein bereits existierendes Element</p>
</div>
Bitte Code in der Browser-Konsole ausführen:
var div = d3.select('div#Beispiel_2');
var p = div.selectAll('p').data([1,2,3])
.style('color', 'red');
p.enter().append('p')
.text( function(d){return 'Neues Element aus Daten ' + d;} )
.style('color', 'green');
p.exit().remove();
Key Function Beispiel:
<svg id="Beispiel_3" width="200" height="30"></svg>
var data = [ {"id":1, "r":14, "x":80, "y":15, "color":"red"},
{"id":2, "r":14, "x":100, "y":15, "color":"green"},
{"id":3, "r":14, "x":120, "y":15, "color":"blue"} ];
var svg = d3.select('svg#Beispiel_3');
var circle = svg.selectAll('circle')
.data(data, function(d){ return d.id; });
circle.exit().remove();
circle.enter().append('circle');
circle
.attr('r', function(d) { return d.r; })
.attr('cx', function(d) { return d.x; })
.attr('cy', function(d) { return d.y; })
.attr('fill', function(d) { return d.color; });
// Einfach mal mit diesen neuen Daten rumprobieren
data = [ {"id":1, "r":7, "x":50, "y":15, "color":"blue"},
{"id":3, "r":14, "x":150, "y":15, "color":"red"} ];
circle = svg.selectAll('circle')
.data(data, function(d){return d.id;}); // Was kommt danach? ;-)
d3.scale.linear()
Eingabewerte skalieren zu Ausgabebereichd3.scale.sqrt()
Radius von SVG Circle Elementend3.scale.category20()
liefert zwanzig verschiedene FarbenLayouts sind Chart Algorithmen
github.com/mbostock/d3/wiki/Layouts
github.com/mbostock/d3/wiki/Pack-Layout
github.com/mbostock/d3/wiki/Bundle-Layout
Anmerkung:
Die Knoten: Mitarbeiter der EMP-Tabelle
var nodes = [
{"name":"King","dept":10},{"name":"Blake","dept":30},
{"name":"Clark","dept":10},{"name":"Jones","dept":20},
{"name":"Scott","dept":20},{"name":"Ford","dept":20},
{"name":"Smith","dept":20},{"name":"Allen","dept":30},
{"name":"Ward","dept":30},{"name":"Martin","dept":30},
{"name":"Turner","dept":30},{"name":"Adams","dept":20},
{"name":"James","dept":30},{"name":"Miller","dept":10}
];
Die Links: Mitarbeiter / Vorgesetzter
var links = [
{"source":1,"target":0},{"source":2,"target":0},
{"source":3,"target":0},{"source":7,"target":1},
{"source":8,"target":1},{"source":9,"target":1},
{"source":10,"target":1},{"source":12,"target":1},
{"source":13,"target":2},{"source":4,"target":3},
{"source":5,"target":3},{"source":6,"target":5},
{"source":11,"target":4}
];
Vorbereitung, Helper und Layout
var width = 600, height = 400;
var svg = d3.select("body").append("svg")
.attr("width",width).attr("height", height);
var color = d3.scale.category10();
var force = d3.layout.force().size([width,height]);
Selections
var link = svg.selectAll("line").data(links)
.enter().append("line").style('stroke','#999');
var node = svg.selectAll("circle").data(nodes)
.enter().append("circle")
.attr("r", 5)
.style("fill", function(d){ return color(d.dept); })
.call(force.drag);
Tick Event
force.on("tick", function(){
link.attr("x1", function(d){ return d.source.x; })
.attr("y1", function(d){ return d.source.y; })
.attr("x2", function(d){ return d.target.x; })
.attr("y2", function(d){ return d.target.y; });
node.attr("cx", function(d){ return d.x; })
.attr("cy", function(d){ return d.y; });
});
Ausführung
force.nodes(nodes).links(links).start();
Das Ergebnis…
Knoten dürfen bewegt werden ;-)
…ein wenig aufgebrezelt
Mit Customize Wizard: Standalone, APEX Plugin
Anmerkung:
Beispiel Closure:
function my_chart() {
var conf = { "width": 600, "height": 400 };
function chart(){/*create chart with conf*/}
chart.render = function(){
chart();
return chart;
};
chart.width = function(value) {
if (!arguments.length) return conf.width;
conf.width = value;
return chart;
};
return chart;
}
//Einfach einzeln in der Konsole ausprobieren ;-)
var test = my_chart(); //Initialisierung
test.width(); //Breite auslesen
test.chart(); //Versuch, die Chart Funktion auszuführen
test.render(); //Chart Funktion über Render-Methode
test.width(300).render().width(); //Was passiert jetzt?