An experiment with RxJS, D3.js, and Three.js. Inspired by The introduction to Reactive Programming you've been missing by André Staltz.
Last active
November 15, 2015 19:30
-
-
Save plmrry/e9d1c7d1e095797170be to your computer and use it in GitHub Desktop.
Everything is a Stream
This file contains 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> | |
<html> | |
<head> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r72/three.min.js"></script> | |
<title>Everything is a Stream</title> | |
</head> | |
<body> | |
<script type="text/coffeescript" src="script.coffee"></script> | |
<script src="http://coffeescript.org/extras/coffee-script.js"></script> | |
</body> | |
</html> |
This file contains 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
stream = Rx.Observable | |
apply = (o, func) -> func o | |
animation = stream.create (observer) -> | |
d3.timer -> observer.onNext() | |
.timestamp() | |
resize = stream.fromEvent window, 'resize' | |
.startWith {} | |
.map -> | |
width: window.innerWidth | |
height: window.innerHeight | |
updateCameraSize = resize.map (s) -> | |
(c) -> | |
c.aspect = s.width / s.height | |
c.updateProjectionMatrix() | |
return c | |
camera = stream.just new THREE.PerspectiveCamera() | |
.concat stream.just (c) -> | |
c.position.z = 5 | |
return c | |
.concat updateCameraSize | |
.scan apply | |
renderer = stream.just new THREE.WebGLRenderer() | |
.concat stream.just (r) -> r.setClearColor 'white'; r | |
.concat resize.map (s) -> (r) -> r.setSize s.width, s.height; r | |
.scan apply | |
renderer.first() | |
.subscribe (renderer) -> | |
document.body.appendChild renderer.domElement | |
geometry = stream.just new THREE.SphereGeometry 1, 1, 1 | |
material = stream.just new THREE.MeshBasicMaterial | |
color: 'grey', wireframe: true | |
newCube = stream.combineLatest geometry, material | |
.map (arr) -> | |
[geom, mat] = arr | |
mesh = new THREE.Mesh(geom, mat) | |
mesh.name = 'cube' | |
return mesh | |
.shareReplay() # Re-send values to second subscriber | |
cubeUpdate = animation.map (time) -> | |
(cube) -> | |
cube.rotation.x += 0.01 | |
cube.rotation.y += 0.01 | |
return cube | |
addNewCube = newCube.map (c) -> | |
(s) -> | |
s.add c | |
return s | |
scene = stream.just new THREE.Scene() | |
.concat addNewCube | |
.scan apply | |
cube = newCube | |
.concat cubeUpdate | |
.scan apply | |
stream.combineLatest renderer, scene, camera, cube | |
.subscribe (arr) -> | |
[renderer, scene, camera, cube] = arr | |
renderer.render scene, camera |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment