Arvis
Arvis

Reputation: 13

Simulate wave in JavaScript with floating element

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

Answers (1)

Mr_KoKa
Mr_KoKa

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

Related Questions