Created
December 7, 2013 00:42
-
-
Save david4096/7835736 to your computer and use it in GitHub Desktop.
Example used for n-body toy. Shows attractive nodes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| body{ | |
| padding: 0; | |
| margin: 0; | |
| background: white; | |
| font-family: sans-serif; | |
| } | |
| rect { | |
| fill: none; | |
| pointer-events: all; | |
| } | |
| .node { | |
| } | |
| .inputs {transition: opacity .2s; text-align: left; position:absolute; font-family: sans-serif; | |
| opacity: .5; color:#ccc; font-size: 10pt; color: #cdcdcf; position:absolute; display:block; size: 8em; top: 30px;} | |
| em { size:14em; opacity: .8;} | |
| .slideLog { | |
| position:absolute; | |
| left: 300px; | |
| } | |
| .inputs:hover {opacity: .8;} | |
| .cursor { | |
| fill: none; | |
| stroke: #333; | |
| pointer-events: none; | |
| } | |
| .slider { | |
| height: 10px; | |
| left: 3em; | |
| width: 200px; | |
| position: absolute; | |
| right: 2px; | |
| opacity: .82; | |
| } | |
| input[type='range'] { | |
| -webkit-appearance: none; | |
| padding-left:2px; padding-right:2px; | |
| -webkit-border-radius: 5px; | |
| opacity: .5; | |
| background: #3ac; | |
| } | |
| input[type='range']::-webkit-slider-thumb { | |
| -webkit-appearance: none; | |
| background-color: #fff; | |
| opacity: 1; | |
| width: 10px; | |
| height: 10px; | |
| } | |
| </style> | |
| <body> | |
| <script src="http://d3js.org/d3.v3.min.js"></script> | |
| <script> | |
| var currentWidth; | |
| currentWidth = function() { | |
| return [window.innerWidth, window.innerHeight]; | |
| } | |
| var width = window.innerWidth, | |
| height = window.innerHeight; | |
| var fill = d3.scale.category20(); | |
| var force = d3.layout.force(); | |
| var trailLength = 1; | |
| window.onresize = function() { force.size(currentWidth());} | |
| function resize () { | |
| force.size(currentWidth()); | |
| } | |
| force | |
| .size(currentWidth()) | |
| .nodes([{}, {}, {}]) // initialize with a single node | |
| .linkDistance(30) | |
| .charge(40) | |
| .gravity(.05) | |
| .on("tick", tick) | |
| //oscillators.push(newOsc()); | |
| var svg = d3.select("body").append("svg") | |
| .attr("width", width) | |
| .attr("height", height) | |
| svg.append("rect") | |
| .attr("width", width) | |
| .attr("height", height); | |
| var nodes = force.nodes(), | |
| links = force.links(), | |
| node = svg.selectAll(".node"), | |
| link = svg.selectAll(".link"); | |
| var cursor = svg.append("circle") | |
| .attr("r", 30) | |
| .attr("transform", "translate(-100,-100)") | |
| .attr("class", "cursor"); | |
| restart(); | |
| function mousemove() { | |
| cursor.attr("transform", "translate(" + d3.mouse(this) + ")"); | |
| } | |
| // TODO separate charges | |
| var charges = []; | |
| function mousedown(auto) { | |
| if (force.nodes().length < 40000) { | |
| var point = d3.mouse(this), | |
| node = {x: point[0], y: point[1]}, | |
| n = nodes.push(node); | |
| charges.push(30); | |
| // oscillators.push(newOsc()); | |
| // add links to any nearby nodes | |
| nodes.forEach(function(target) { | |
| var x = target.x - node.x, | |
| y = target.y - node.y; | |
| if (Math.sqrt(x * x + y * y) < 30) { | |
| links.push({source: node, target: target}); | |
| } | |
| }); | |
| restart(); } | |
| } | |
| function distanceFromZero(d) { | |
| return Math.sqrt ( (d.x - width / 2) * (d.x - width / 2) + (d.y - height / 2) * (d.y - height / 2) ); | |
| } | |
| var totalEnergy = 0; | |
| var lastTime = (new Date).getMilliseconds(); | |
| var maxE = 0; | |
| var energies = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; | |
| function drawEnergy() { | |
| if (totalEnergy > maxE) { | |
| maxE = totalEnergy; | |
| document.getElementById('maxE').style.color = d3.hsl(-200 + 2*Math.log(totalEnergy) % 360, .5, .8).toString(); | |
| document.getElementById('maxE').innerHTML = Math.round(totalEnergy); | |
| } | |
| energies.push(totalEnergy); | |
| var avg; | |
| avg = energies.reduce(function(prev, cur) { | |
| return (cur + prev); | |
| }, 0) / energies.length; | |
| console.log(avg); | |
| energies.shift(); | |
| if (!isNaN(avg)) { | |
| document.getElementById('energy').style.color = d3.hsl(-200 + 2*Math.log(avg) % 360, .5, .8).toString(); | |
| document.getElementById('energy').innerHTML = Math.round(avg); | |
| } | |
| } | |
| var lastTime = 0; | |
| function drawFps(){ | |
| var now = (new Date).getTime(); | |
| document.getElementById('fps').innerHTML = Math.round(1000 / (now - lastTime)); | |
| lastTime = (new Date).getTime(); | |
| } | |
| var sometimes = 0; | |
| function tick() { | |
| //force.charge(charges); | |
| //drawFps(); | |
| //drawEnergy(); | |
| force.resume(); | |
| force.size(currentWidth()); | |
| link.attr("x1", function(d) { return d.source.x; }).attr("stroke", | |
| function(d) { | |
| var length = Math.sqrt(Math.pow(d.source.x - d.target.x, 2) + Math.pow(d.source.y - d.target.y, 2)); | |
| return d3.hsl(length, .5, .3).toString(); | |
| }) | |
| .attr("y1", function(d) { return d.source.y; }) | |
| .attr("x2", function(d) { return d.target.x; }) | |
| .attr("y2", function(d, i) { | |
| return d.target.y; | |
| }); | |
| //.attr("stroke", function(d) { | |
| // console.log(d); | |
| // return d3.hsl(distanceFromZero(d.source) % 360, .5, .5).toString();}); | |
| // requested to make color stick depending on where its placed | |
| totalEnergy = 0; | |
| node.attr("cx", function(d, i) { //console.log(oscillators[0]); | |
| //updateFreq(oscillators[i], numberToNote(distanceFromZero(d) / 10)) ; | |
| return d.x; }) | |
| .attr("cy", function(d) { return d.y; }) | |
| .attr("fill", function(d) { //console.log(d3.hsl(d.x % 360, .5, .5).toString()); | |
| var energy = Math.pow(d.x - d.x_last, 2) + Math.pow(d.y - d.y_last, 2) ; | |
| svg.insert("line", ":first-child") | |
| .attr("stroke", d3.hsl(-200 + 68*Math.log(energy) % 360, .5, .1*Math.log(energy)).toString()) | |
| .attr("x1", function(v) {if (d.x_last == undefined) {return d.x;} else {return d.x_last;}}) | |
| .attr("y1", function(v) {if (d.y_last == undefined) {return d.y;} else {return d.y_last;}}) | |
| .attr("x2", d.x) | |
| .attr("y2", d.y).attr("stroke-width", 1).transition().duration(trailLength) | |
| //.transition().duration(10000).attr("transform", "scale(1.1) translate( " + width / 2 + " " + height / 2 + ")") | |
| .remove(); | |
| //.transition().duration(10000).attr("transform", "scale(1.1) translate( -" + width / 2 + " " + height / 2 + ")") | |
| d.x_last = d.x; | |
| d.y_last = d.y; | |
| // svg.append("circle") | |
| // .attr("r", 2) | |
| // .attr("fill", d3.hsl(distanceFromZero(d) % 360, .5, .5).toString()) | |
| // .attr("cx", d.x) | |
| // .attr("cy", d.y) | |
| // .transition().delay(10000) | |
| // .remove() | |
| totalEnergy = totalEnergy + energy; | |
| return "blue";}) | |
| } | |
| function removeTrails(){ | |
| d3.selectAll("line").remove(); | |
| } | |
| function restart() { | |
| link = link.data(links); | |
| link.enter().insert("line", ".node") | |
| .attr("class", "link"); | |
| node = node.data(nodes); | |
| node.enter().insert("circle", ".cursor") | |
| .attr("class", "node") | |
| .attr("r", 3) | |
| .call(force.drag); | |
| force.start(); | |
| } | |
| function sliderLog(obj, id) { | |
| document.getElementById(id).innerHTML = obj.value; | |
| } | |
| </script> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment