Dawid
Dawid

Reputation: 593

How would you make a wave animated div css/js

One way I can think of is with an animated svg, but there is probably a better way. What would you do if you had to animate these wavy blobs (mobile compatible)

Link to the only pin I've found similar

var wave = document.createElement("div");
wave.className += " wave";
docFrag.appendChild(wave);
wave.style.left = i * waveWidth + "px";
wave.style.webkitAnimationDelay = (i / 100) + "s";

Touch interaction would be nice too. Would there be any problems with canvas stuff ?

The design

Upvotes: 4

Views: 5154

Answers (3)

markE
markE

Reputation: 105015

Here's an implementation of @DA.'s good answer:

enter image description here

var canvas=document.getElementById('canvas');
var ctx=canvas.getContext('2d');
var cw=canvas.width;
var ch=canvas.height;

ctx.textAlign='center';
ctx.textBaseline='middle';
ctx.font='16px verdana';
ctx.lineWidth=5;
ctx.strokeStyle='white';
ctx.fillStyle='white';
var offsetX=0;

var bk=makeWave(canvas.width,canvas.height-120,10,2,'lightskyblue','cornflowerblue');

requestAnimationFrame(animate);

function animate(time){
    ctx.clearRect(0,0,cw,ch);
    ctx.drawImage(bk,offsetX,0);
    ctx.fillStyle='white';
    ctx.font='18px verdana';
    ctx.fillText('Multiple Lists',cw/2,30);
    ctx.strokeRect(cw/2-50,85,100,50);
    ctx.fillStyle='gray';
    ctx.font='12px verdana';
    ctx.fillText('You can create and save multiple ...',cw/2,250);
    offsetX-=1;
    if(offsetX< -bk.width/2){offsetX=0;}
    requestAnimationFrame(animate);
}

function makeWave(width,midWaveY,amplitude,wavesPerWidth,grad0,grad1){
    var PI2=Math.PI*2;
    var totValue=PI2*wavesPerWidth;
    var c=document.createElement('canvas');
    var ctx=c.getContext('2d');
    c.width=width*2;
    c.height=midWaveY+amplitude;
    var grad=ctx.createLinearGradient(0,0,0,midWaveY);
    grad.addColorStop(0.00,grad0);
    grad.addColorStop(1.00,grad1);
    //
    ctx.beginPath();
    ctx.moveTo(0,0);
    for (x=0;x<=200;x++) {
        var n=totValue*x/100;
        ctx.lineTo(width*x/100,Math.sin(n)*amplitude+midWaveY);
    }
    ctx.lineTo(c.width,0);
    ctx.closePath();
    ctx.fillStyle=grad;
    ctx.fill();
    return(c);
}
body{ background-color:white; }
canvas{border:1px solid red; margin:0 auto; }
<canvas id=canvas width=300 height=300></canvas>

Upvotes: 3

DA.
DA.

Reputation: 40671

I'd make the wave a PNG (bottom solid gray, top transparent). Place it in a div twice the width of the card, and place that in a div the width of the card (this second div is the 'mask').

Then via CSS, have the nested give transform on the x axis to animate it sideways.

You shouldn't need any JS for this.

Upvotes: 2

pid
pid

Reputation: 11607

I would do this:

  • on page load create an off-screen canvas (just set display: none)
  • in a for loop compute the wave:
    • clear with transparency
    • paint only the white part because the colored part has a gradient
    • after each paint, get the PNG data out of the canvas and store it in an array
  • after the loop you will have an array of PNG images (frames)
  • cycle through those frames without recomputing the wave over and over again

This requires the wave to have a period that is affine to the number of frames you take (say a 2 second animation at 10 Hz would require 20 frames to be cyclic)

To be honest, you could store that server-side and just download it, without computing it client-side. Those PNG images would be very tiny because there isn't any color involved (just transparent/white/alpha channel). There are optimal settings for this, I guesstimate some 1KB per frame would suffice, that's a tiny 20 KB of images).

Upvotes: 0

Related Questions