Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add flaglike waving to 2d Context

I want to make a function that displays a 2d context in a different way than usual. Sort of like the transform works. Instead of curving/changing the size of the context I want to make it wave-like. The idea is that this has to come from the context, not from the data image. No bit manipulation.

A similar request is done here: How to distort an image to create flag waving in the wind effect using html5 canvas but with bit manipulation.

The point is to increase performance by reducing bit manipulation.

Edit: I need to make the same function that is described in the link (the one in above), with a little difference. The link is answered so you can understand what I mean. In the example, this is executed by bit manipulation. I want to make the same thing, but from the context's side. Like its done with the context.transform(..) function.

example of the Context.transform function: http://www.html5canvastutorials.com/advanced/html5-canvas-custom-transform/ (you can change the tranfsorm function's parameters to get the effect)

Hope that clears it up.

like image 828
Moon4u Avatar asked Nov 20 '25 22:11

Moon4u


2 Answers

You can use context.drawImage to draw 1 pixel wide vertical slices with a "wavy" y-offset.

This method gives good performance because you're drawing the entire height of the image at once instead of pixel-by-pixel. Also, the drawing process is much faster than pixel manipulation because the required pixels are blitted from the image to the canvas. And this method uses GPU acceleration when a GPU is available.

enter image description here

Example code and a Demo: http://jsfiddle.net/m1erickson/bcjmxr80/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>
<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    var img=new Image();
    img.onload=start;
    img.src=document.getElementById("source").src;
    function start(){

        var iw=img.width;
        var ih=img.height;
        canvas.width=iw+100;
        canvas.height=ih+100;

        for(var x=0;x<310;x++){
            var y=5*Math.sin(x/10)+200-162;
            ctx.drawImage(img, x,0,1,ih,  x,y,1,ih);
        }

    }

}); // end $(function(){});
</script>
</head>
<body>
    <h4>Original Image</h4>
    <img id=source src="https://dl.dropboxusercontent.com/u/139992952/multple/usaFlag.png"><br>
    <h4>Wavy using vertical slices in canvas</h4>
    <canvas id="canvas"></canvas>
</body>
</html>
like image 185
markE Avatar answered Nov 23 '25 12:11

markE


You could optimize with shaders so that the workload is transfered to GPU, but that's 3d/webgl context.

As for 2d, you'll just have to do it on per-pixel level, there's no other way.

And if by this

The idea is that this has to come from the context

you mean: to have objects that are transformed by some oscillating force, then you should look for physics engine: box2djs comes to mind.

p2.js has a nice demo with springs.

like image 42
nullpotent Avatar answered Nov 23 '25 10:11

nullpotent



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!