Let people change variables in a system as it updates. Here, you can change the size and speed of the balls.
forked from HarryStevens's block: Bouncing Balls
license: gpl-3.0 |
Let people change variables in a system as it updates. Here, you can change the size and speed of the balls.
forked from HarryStevens's block: Bouncing Balls
<!DOCTYPE html> | |
<html> | |
<head> | |
<style> | |
body { | |
margin: 0; | |
font-family: "Helvetica Neue", sans-serif; | |
} | |
#sliders { | |
position: absolute; | |
background: rgba(255, 255, 255, .8); | |
padding: 5px; | |
} | |
.slider-wrapper { | |
display: inline-block; | |
text-align: center; | |
font-size: .8em; | |
font-weight: bold; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="canvas"> | |
<div id="sliders"> | |
<div class="slider-wrapper"> | |
<div>Speed</div> | |
<input data-variable="distance" type="range" id="speed"> | |
</div> | |
<div class="slider-wrapper"> | |
<div>Size</div> | |
<input data-variable="radius" type="range" id="size"> | |
</div> | |
</div> | |
</div> | |
<script src="https://d3js.org/d3.v5.min.js"></script> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> | |
<script src="https://unpkg.com/jeezy@1.11.2/lib/jeezy.min.js"></script> | |
<script> | |
var width = window.innerWidth, height = window.innerHeight; | |
var variables = { | |
radius: 15, | |
distance: 10 | |
} | |
var extents = { | |
radius: [3, 50], | |
distance: [0, 40] | |
} | |
var min = 2, max = 100; | |
$("#sliders input").each(function(slider_index, slider){ | |
var this_var = $(this).attr("data-variable"); | |
var extent = extents[this_var]; | |
$(this).attr("value", variables[this_var]).attr("min", extent[0]).attr("max", extent[1]); | |
}).on("change input", function(){ | |
variables[$(this).attr("data-variable")] = $(this).val(); | |
}); | |
var data = []; | |
var point_count = 20; | |
var svg = d3.select("#canvas").append("svg").attr("width", width).attr("height", height); | |
for (var i = 0; i < point_count; i++){ | |
data.push({ | |
id: jz.str.randomString(), | |
x: jz.num.randBetween(0, width), | |
y: jz.num.randBetween(0, height), | |
slope: jz.num.randBetween(1, 20) / 10, | |
x_dir: [-1, 1][jz.num.randBetween(0, 1)], | |
y_dir: [-1, 1][jz.num.randBetween(0, 1)] | |
}); | |
} | |
var drag = d3.drag() | |
.on("start", d =>{}) | |
.on("drag", d =>{svg.select(".dragger").attr("cx", d3.event.x).attr("cy", d3.event.y)}) | |
.on("end", d => {}); | |
svg.append("circle").attr("class", "dragger") | |
.attr("fill", "black") | |
.attr("r", 20).attr("cx", 300).attr("cy", 300) | |
.call(drag); | |
redraw(data); | |
go(); | |
async function go(){ | |
while(true) | |
{ | |
await animateToRandom(data, Math.max(Math.random()*6, 3)*1000); | |
} | |
} | |
function redraw(data){ | |
var circle = svg.selectAll(".bouncingcircle") | |
.data(data, function(d){ return d.id; }) | |
circle | |
.attr("r", variables.radius) | |
.attr("cx", function(d){ return d.x; }) | |
.attr("cy", function(d){ return d.y; }); | |
circle.enter().append("circle") | |
.attr("fill", "steelblue") | |
.attr("stroke", "white") | |
.attr("class", "bouncingcircle") | |
.attr("r", variables.radius) | |
.attr("cx", function(d){ return d.x; }) | |
.attr("cy", function(d){ return d.y; }); | |
} | |
function animateToRandom(data, time){ | |
for (let x of data){ | |
x.x = Math.random()*width; | |
x.y = Math.random()*height; | |
} | |
var circle = svg.selectAll(".bouncingcircle") | |
return circle.transition().duration(time) | |
.attr("r", variables.radius) | |
.attr("cx", function(d){ return d.x; }) | |
.attr("cy", function(d){ return d.y; }) | |
.end(); | |
} | |
function update(data){ | |
data.forEach(function(d){ | |
return calcPointB(d, variables.distance, d.slope); | |
}); | |
return data; | |
} | |
// given a point, p, and a distance, d, and a slope, m, return x and y | |
// formula from http://www.geeksforgeeks.org/find-points-at-a-given-distance-on-a-line-of-given-slope/ | |
function calcPointB(p, d, m){ | |
p.x_dir = getDir(p.x, p.x_dir, width); | |
p.y_dir = getDir(p.y, p.y_dir, height); | |
function getDir(coord, dir, dimension){ | |
return Math.floor(coord) <= variables.radius ? 1 : | |
Math.ceil(coord) >= dimension - variables.radius ? -1 : | |
dir; | |
} | |
p.x = p.x + (d * Math.sqrt(1 / (1 + Math.pow(m, 2))) * p.x_dir); | |
p.y = p.y + (m * d * Math.sqrt(1 / (1 + Math.pow(m, 2))) * p.y_dir); | |
return p; | |
} | |
</script> | |
</body> | |
</html> |
�PNG | |