To explore and experiment in order to better create something functional.
Goal Oriented Learning
Photoshop of the Web
Create a Scene
var canvas = null;
var context = null;
window.onload = function() {
canvas = document.getElementById("canvas");
context = canvas.getContext('2d');
}
window.onresize = resize;
Resize (simple)
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
Resize (retina)
function resize() {
var devicePixelRatio = window.devicePixelRatio || 1;
var backingStoreRatio = canvas.webkitBackingStorePixelRatio || canvas.mozBackingStorePixelRatio || canvas.msBackingStorePixelRatio || canvas.oBackingStorePixelRatio || canvas.backingStorePixelRatio || 1;
var ratio = devicePixelRatio / backingStoreRatio;
var w = window.innerWidth;
var h = window.innerHeight;
canvas.width = w*ratio;
canvas.height = h*ratio;
canvas.style.width = w + 'px';
canvas.style.height = h + 'px';
}
Selections in Canvas
circles.forEach(function(d) {
var diff = {
"x":(mouse.x - d.x),
"y":(mouse.y - d.y)
}
var dist = Math.sqrt(diff.x*diff.x + diff.y*diff.y);
if (dist < d.r) {
d.clicked = true; // circle was clicked
break;
}
});
setTimeout
function animate() {
draw(); // draw and move things
setTimeout(animate, 1000/60); // 60fps
}
window.onload = function() {
canvas = document.getElementById("canvas");
context = canvas.getContext('2d');
animate();
}
requestAnimationFrame
function animate() {
requestAnimationFrame(animate); // ~60fps
draw(); // draw and move things (afterward)
}
window.onload = function() {
canvas = document.getElementById("canvas");
context = canvas.getContext('2d');
animate();
}
Add Movement
var shape = {"x":0,"y":0,"w":200,"h":200};
var dim = {}; // set in resize
function draw() {
context.fillStyle = '#00aaff'; // light blue
context.fillRect(shape.x, shape.y, shape.w, shape.h);
}
function animate() {
requestAnimationFrame(animate); // ~60fps
shape.x += 1; // movement
shape.y += 1;
draw(); // draw and move things (afterward)
}
Refresh the Scene
function resize() {
dim.w = window.innerWidth;
dim.h = window.innerHeight;
}
function draw() {
context.fillStyle = '#fff'; // actually it's black
context.fillRect(0,0,dim.w,dim.h); // refresh!
context.fillStyle = '#00aaff';
context.fillRect(shape.x, shape.y, shape.w, shape.h);
}
globalAlpha!
function draw() {
context.globalAlpha = 0.1;
context.fillStyle = '#fff';
context.fillRect(0,0,dim.w,dim.h); // refresh (?)
context.globalAlpha = 1;
context.fillStyle = '#00aaff';
context.fillRect(shape.x, shape.y, shape.w, shape.h);
}
Scalable Vector Graphics
Illustrator of the Web
Create a d3 Rectangle
var svg = d3.select("body").append("svg")
.attr('class','main') // important for selecting later
.attr("width", w)
.attr("height", h);
svg.append("rect")
.attr("width", 20)
.attr("height", 20)
.style("fill", "#f00");
typical d3.js
( unpack this and win )
svg.selectAll("rect")
.data(d3.range(x * y))
.enter().append("rect")
.attr("transform", translate)
.attr("width", z)
.attr("height", z)
.style("fill", function(d) { return d3.hsl(d % x / x * 360, 1, Math.floor(d / x) / y); })
.on("mouseover", mouseover); // note: easy selections
function translate(d) {
return "translate(" + (d % x) * z + "," + Math.floor(d / x) * z + ")";
}
Resize
var dim = {};
function resize() {
dim.w = window.innerWidth;
dim.h = window.innerHeight;
d3.select('.main')
.attr("width", dim.w)
.attr("height", dim.h); // no append
update(); // redraw everything to new dimensions
}
window.onresize = resize;
d3-timer
function animate() {
// requestAnimationFrame(animate); not needed
draw();
}
window.onload = function() {
canvas = document.getElementById("canvas");
context = canvas.getContext('2d');
t1 = d3.timer(animate); // https://github.com/d3/d3-timer
}
d3-zoom
svg.append("rect")
.attr("fill", "none")
.attr("pointer-events", "all")
.attr("width", width)
.attr("height", height)
.call(d3.zoom().on("zoom", zoom));
function zoom() {
g.attr("transform", d3.event.transform);
}
d3-force
simulation = d3.forceSimulation(nodes)
.force("x", d3.forceX().strength(0.02))
.force("y", d3.forceY().strength(0.02))
.force("collide", d3.forceCollide().radius(
function(d) { return d.r + 0.5; }).iterations(2).strength(1)
)
.alphaTarget(0.3); // how hard it tries
check out this crazy entropy example
GPU accelerated 3D graphics
Documentation
pay attention to updates - r91 as of April 18, 2018Examples
Creating a Scene
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth/window.innerHeight,
0.1,
1000
);
Initialize the Renderer
window.onload = function() {
var renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio ); // retina displays
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
Make a Cube!
function addcube() {
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
}
Resize
function resize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
window.onresize = resize;
Animation
var animate = function () {
requestAnimationFrame( animate );
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
};
Orbit Controls
function render() {
renderer.render( scene, camera );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
render();
}
var controls = new THREE.OrbitControls( camera, renderer.domElement );
Lights
var light1 = new THREE.PointLight( 0xffffff );
light1.position.set( -700, 1000, 300 );
light1.intensity = 0.5;
var light2 = new THREE.PointLight( 0xffffff );
light2.position.set( 700, 1000, -300 );
light2.intensity = 0.8;
var light3 = new THREE.AmbientLight( 0x222222 );
scene.add( light1 );
scene.add( light2 );
scene.add( light3 );
Selections
Raycasting Example
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( scene.children );
for ( var i = 0; i < intersects.length; i++ ) {
intersects[ i ].object.material.color.set( 0xff0000 );
}
var unitx = new THREE.Vector3(1,0,0);
var unity = new THREE.Vector3(0,0,-1);
var unitz = new THREE.Vector3(0,1,0);
unitz.crossVectors(unitx,unity); // finds the cross product
unitz.applyMatrix4(matrix); // rotates the vector
// rotate about x-axis by radians
var matrix = new THREE.Matrix4().identity();
matrix.makeRotationAxis(unitz,radians);
group.applyMatrix(matrix);
// handy helper
group.lookAt(unitz);
var cubeA = new THREE.Mesh( geometry, material );
var cubeB = new THREE.Mesh( geometry, material );
cubeA.position.set( 100, 100, 0 );
cubeB.position.set( -100, -100, 0 );
//These cubes can now be rotated / scaled etc as a group
var group = new THREE.Group();
group.add( cubeA );
group.add( cubeB );
scene.add( group );
function UXVtoGL(comp) {
var Vect = new THREE.Vector3(comp[0], comp[2], -comp[1]);
return Vect; // returns graphical
}
function GLtoUX(Vect) {
var comp = [Vect.x,-Vect.z,Vect.y];
return comp; // returns cartesian
}
// user to graphical
UXVtoGL([1,2,3])
--> p {x: 1, y: 3, z: -2}
// graphical to user
GLtoUX(new THREE.Vector3(1,3,-2))
--> (3) [1, 2, 3]
var xunit = UXVtoGL([1,0,0]); // readable
Audio in Your Browser
Note: We are at the stage where nearly all browsers support MP3 — for more details visit this page on media format browser compatibility.
// you can access the audio from the audio tag
var audio = document.getElementById('audio_element');
// or you can create an audio element in javascript
var audio = new Audio('audio_file.mp3');
// then to play or stop...
audio.stop();
audio.play();
// note there is no pause
WebAudio Concept
Audio Context and Source
var AuContext = new (window.AudioContext
|| window.webkitAudioContext)(); // define audio context
// Webkit/blink browsers need prefix, Safari won't work without window.
// get an audio source from the DOM
var source = audioCtx.createMediaElementSource(audio);
// or from a stream
var source = audioCtx.createMediaStreamSource(stream);
Connect a Gain Node
var gainNode = AuContext.createGain();
gainNode.gain.value = 1;
source.connect(gainNode);
gainNode.connect(AuContext.destination);
Connect an Analyser
var analyser = audioCtx.createAnalyser();
source.connect(gainNode);
gainNode.connect(analyser);
analyser.connect(AuContext.destination);
Max MSP / Jitter
(not webAudio but you get the idea)webAudio: other resources
Panners and Listeners
var listener = AuContext.listener;
AuContext.listener.setPosition(camPos.x,camPos.y,camPos.z);
AuContext.listener.setOrientation(dirVect.x, dirVect.y, dirVect.z, upVect.x, upVect.y, upVect.z);
var panner = AuContext.createPanner();
panner.distanceModel = "linear";
panner.setPosition(0,200,0);
// connecting
source.connect(panner);
panner.connect(gainNode);
gainNode.connect(analyser);
analyser.connect(AuContext.destination);
three.js - attach a listener to a camera
// create an AudioListener and add it to the camera
var listener = new THREE.AudioListener();
camera.add( listener );
Thank You!