Is there a good method for dynamically drawing clouds with HTML5 canvas and javascript without using images?
Asked Answered
A

3

6

I am trying to create a background for my website that uses canvases to draw stuff, get the data URL of it and set it as the background-image property of an element. The method works, but I can't find a good way to draw a cloud on the canvas. Other simpler things like the sun and stars are easy to do without images, and I would prefer to keep the entire script image-less. Drawing a multitude of circles around a point can slightly do it, but I would prefer a more realistic way to do it. Thanks in advance.

Absolutism answered 7/2, 2011 at 23:26 Comment(1)
Definitely need an example of what type of cloud you would consider a good cloud, otherwise it'll be nothing but a huge game of guess and check. Some links to some vector clouds that you like would do wonders.Corked
A
3

Ok, I have been thinking about the problem of draw clouds, and this is where I am at.

HTMLCanvasElement.prototype.makeCloud=function (xLast, yLast, rLast, lLast){
    rLast = (rLast || 50)
    lLast = lLast || Math.random()*25+75;
    var x = (xLast || 250) + Math.random()*(2*rLast)-rLast/1,
        y = (yLast || 250) + Math.random()*(1*rLast)-rLast/1.5,
        r = (rLast) + Math.random()*10-7.5,
        l = (lLast);

    if(x-r < 0)
        x = r+1;
    else if (x+r > this.width)
        x = this.width-r-1;
    if(y-r < 0)
        y = r+1;
    else if (y+r > this.height)
        y = this.height-r-1;
    if(r <= 0)
        return this;
    if(l<0)
        l=0;
    else if(l>100)
        l=100;

    var ctx=this.getContext('2d');
    ctx.fillStyle='hsl(0, 0%, '+l+'%)';
    ctx.beginPath();
    ctx.arc(x, y, r, 0, Math.PI*2, true);
    ctx.closePath();
    ctx.fill();
    if(Math.random < 0.01)
        return this;
    this.makeCloud(x, y, r, l)
    return this;
} 

It generates some pretty crazy stuff... can anyone think of any improvements? i know editing the canvas prototype isn't the best thing to do, but my application uses a bit of chaining and this makes it flow better.

Absolutism answered 8/2, 2011 at 21:5 Comment(2)
Made a JSFiddle in case anyone else comes along this question and wants to see what these clouds look like: jsfiddle.net/qs8wfBrachiate
here was a quick stab (jsfiddle.net/icodeforlove/qs8wf/22). Im sure this could be expanded to use paths instead and better restrictions.Unbalance
S
4

I have just created Cloudgen.js, an open source library that generates clouds for the canvas. The approach I took uses overlapping circles, each with a radial gradient and transparency. Cloudgen.js provides a way to draw a single cloud with the "drawCloud" method or many clouds at once with "drawCloudGroup". As clouds are roughly circular, using "drawCloudGroup" also allows you to create single clouds with more interesting or predefined shapes.

You can find Cloudgen.js at https://github.com/Ninjakannon/Cloudgen.js

Sunstroke answered 31/5, 2012 at 15:53 Comment(0)
A
3

Ok, I have been thinking about the problem of draw clouds, and this is where I am at.

HTMLCanvasElement.prototype.makeCloud=function (xLast, yLast, rLast, lLast){
    rLast = (rLast || 50)
    lLast = lLast || Math.random()*25+75;
    var x = (xLast || 250) + Math.random()*(2*rLast)-rLast/1,
        y = (yLast || 250) + Math.random()*(1*rLast)-rLast/1.5,
        r = (rLast) + Math.random()*10-7.5,
        l = (lLast);

    if(x-r < 0)
        x = r+1;
    else if (x+r > this.width)
        x = this.width-r-1;
    if(y-r < 0)
        y = r+1;
    else if (y+r > this.height)
        y = this.height-r-1;
    if(r <= 0)
        return this;
    if(l<0)
        l=0;
    else if(l>100)
        l=100;

    var ctx=this.getContext('2d');
    ctx.fillStyle='hsl(0, 0%, '+l+'%)';
    ctx.beginPath();
    ctx.arc(x, y, r, 0, Math.PI*2, true);
    ctx.closePath();
    ctx.fill();
    if(Math.random < 0.01)
        return this;
    this.makeCloud(x, y, r, l)
    return this;
} 

It generates some pretty crazy stuff... can anyone think of any improvements? i know editing the canvas prototype isn't the best thing to do, but my application uses a bit of chaining and this makes it flow better.

Absolutism answered 8/2, 2011 at 21:5 Comment(2)
Made a JSFiddle in case anyone else comes along this question and wants to see what these clouds look like: jsfiddle.net/qs8wfBrachiate
here was a quick stab (jsfiddle.net/icodeforlove/qs8wf/22). Im sure this could be expanded to use paths instead and better restrictions.Unbalance
P
0
function clouds(x,y,scale) { if(scale < 5) { return; }

fill(random(0,255),random(0,255),random(0,255),100);
ellipse(x,y,scale,scale);

clouds(x + scale/2, y + random(-scale/2,scale/2), scale * 0.75);
clouds(x - scale/2, y + random(-scale/2,scale/2), scale * 0.75);
}
Papotto answered 23/3, 2023 at 17:29 Comment(1)
Please edit your post to include a explanation, maybe also a image of the result. This doesn't seem like it would be any more realistic than OP's version.Epidermis

© 2022 - 2024 — McMap. All rights reserved.