Reputation: 13
New to HTML canvas. I got a good pointer for the wave generation using Shovan Dhara
codes. However i want to achieve a floating rectangle at the top of this wave. Any pointer would be useful. Thanks.
P.S: find code below:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Oscillators</title>
<style type='text/css'>
body {
margin:0;
padding:0;
overflow:hidden;
background:#e6e5e5;
}
</style>
<script type='text/javascript'>
// shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
//<![CDATA[
window.onload=function(){
/**
* Wave oscillators by Ken Fyrstenberg Nilsen
* http://abdiassoftware.com/
*
* CC-Attribute 3.0 License
*/
var ctx = canvas.getContext('2d'),
w, h;
canvas.width = w = window.innerWidth * 1.1;
canvas.height = h = window.innerHeight * 1;
var osc1 = new osc(),
osc2 = new osc(),
osc3 = new osc(),
horizon = h * 0.5;
count = 40,
step = Math.ceil(w / count),
//points = new Array(count);
buffer = new ArrayBuffer(count * 4),
points = new Float32Array(buffer);
osc1.max = 15;//h * 0.7;
osc2.max = 5;
osc2.speed = 0.03;
osc2.max = 5;
osc2.speed = 0.015;
function fill() {
for(var i = 0; i < count; i++) {
points[i] = mixer(osc1, osc2, osc3);
}
}
fill();
ctx.lineWidth = 20;
ctx.strokeStyle = '#0000';
ctx.fillStyle = '#1d96d3';
function loop() {
var i;
/// move points to the left
for(i = 0; i < count - 1; i++) {
points[i] = points[i + 1];
}
/// get a new point
points[count - 1] = mixer(osc1, osc2, osc3);
ctx.clearRect(0, 0, w, h);
//ctx.fillRect(0, 0, w, h);
/// render wave
ctx.beginPath();
ctx.moveTo(-5, points[0]);
for(i = 1; i < count; i++) {
ctx.lineTo(i * step, points[i]);
}
ctx.lineTo(w, h);
ctx.lineTo(-5, h);
ctx.lineTo(-5, points[1]);
ctx.stroke();
ctx.fill();
ctx.strokeRect(100,h/2,150,100);
}
/// oscillator object
function osc() {
this.variation = 0.4;
this.max = 150;
this.speed = 0.02;
var me = this,
a = 0,
max = getMax();
this.getAmp = function() {
a += this.speed;
if (a >= 2.0) {
a = 0;
max = getMax();
}
return max * Math.sin(a * Math.PI);
}
function getMax() {
return Math.random() * me.max * me.variation +
me.max * (1 - me.variation);
}
return this;
}
function mixer() {
var d = arguments.length,
i = d,
sum = 0;
if (d < 1) return 0;
while(i--) sum += arguments[i].getAmp();
return sum / d + horizon;
}
(function animloop(){
requestAnimFrame(animloop);
loop();
})();
}//]]>
</script>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
Upvotes: 1
Views: 392
Reputation: 618
I took width of the screen and divided it by points number then I calculated which point to use for the box Y coordinate for given X coordinate based on its dimensions. points are just Y coordinates, so the height of a wave in the point. Those are my calculations:
var rectX = 500;
var rectWidth = 200;
var rectHeight = 100;
var centerX = rectX + rectWidth / 2;
var pointToUse = Math.floor(centerX / (w / points.length));
And I draw the box like this:
ctx.strokeRect(rectX, points[pointToUse] - rectHeight, rectWidth, rectHeight);
You can make it more submerged by adding some to points[pointToUse] - rectHeight
You may also add safety checks for points.length != 0 and (w / points.length) != 0
Here is working snippet:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Oscillators</title>
<style type='text/css'>
body {
margin:0;
padding:0;
overflow:hidden;
background:#e6e5e5;
}
</style>
<script type='text/javascript'>
// shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
//<![CDATA[
window.onload=function(){
/**
* Wave oscillators by Ken Fyrstenberg Nilsen
* http://abdiassoftware.com/
*
* CC-Attribute 3.0 License
*/
var ctx = canvas.getContext('2d'),
w, h;
canvas.width = w = window.innerWidth * 1.1;
canvas.height = h = window.innerHeight * 1;
var osc1 = new osc(),
osc2 = new osc(),
osc3 = new osc(),
horizon = h * 0.5;
count = 40,
step = Math.ceil(w / count),
//points = new Array(count);
buffer = new ArrayBuffer(count * 4),
points = new Float32Array(buffer);
osc1.max = 15;//h * 0.7;
osc2.max = 5;
osc2.speed = 0.03;
osc2.max = 5;
osc2.speed = 0.015;
function fill() {
for(var i = 0; i < count; i++) {
points[i] = mixer(osc1, osc2, osc3);
}
}
fill();
ctx.lineWidth = 20;
ctx.strokeStyle = '#0000';
ctx.fillStyle = '#1d96d3';
var rectX = 200;
var rectWidth = 100;
var rectHeight = 50;
var centerX = rectX + rectWidth / 2;
var pointToUse = Math.floor(centerX / (w / points.length));
function loop() {
var i;
/// move points to the left
for(i = 0; i < count - 1; i++) {
points[i] = points[i + 1];
}
/// get a new point
points[count - 1] = mixer(osc1, osc2, osc3);
ctx.clearRect(0, 0, w, h);
//ctx.fillRect(0, 0, w, h);
/// render wave
ctx.beginPath();
ctx.moveTo(-5, points[0]);
for(i = 1; i < count; i++) {
ctx.lineTo(i * step, points[i]);
}
ctx.lineTo(w, h);
ctx.lineTo(-5, h);
ctx.lineTo(-5, points[1]);
ctx.stroke();
ctx.fill();
ctx.strokeRect(rectX, points[pointToUse] - rectHeight, rectWidth, rectHeight);
}
/// oscillator object
function osc() {
this.variation = 0.4;
this.max = 150;
this.speed = 0.02;
var me = this,
a = 0,
max = getMax();
this.getAmp = function() {
a += this.speed;
if (a >= 2.0) {
a = 0;
max = getMax();
}
return max * Math.sin(a * Math.PI);
}
function getMax() {
return Math.random() * me.max * me.variation +
me.max * (1 - me.variation);
}
return this;
}
function mixer() {
var d = arguments.length,
i = d,
sum = 0;
if (d < 1) return 0;
while(i--) sum += arguments[i].getAmp();
return sum / d + horizon;
}
(function animloop(){
requestAnimFrame(animloop);
loop();
})();
}//]]>
</script>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
Upvotes: 1