Water distortion effect on image

Hello!

I’m trying to recreate something like this effect on a picture, just the distortion effect without any interaction on hover. A simple distortion animation of a selected picture in loop.

Do you know a simple and easy-custom code way to do something similar?

Thank you :slight_smile:

I’m not too familiar with importing JS, but you can try this:

  1. Add the <canvas id="canvas"></canvas> to the <head> section of the page you want this added to

  2. Create a div, and name its class “canvas”

  3. Add the JS to the <body> section of the same page

Let me know how that works for you. PS - I could be totally wrong about this :lying_face:

Hello @Martina_Salvaterra,

It is a little bit more complicated than that. I have rebuild a codepen removing the fish drag function and adding webflow URls. All you need to do is add a custom code embed component in your webflow layout. Within your custom code component, simply write <canvas id="canvas"></canvas>.

Then copy this modified JavaScript to the custom code part of your webflow project (Note the options module with the little :brain: emoji, those are the settings you want to modify with your own webflow site ID / images).

Here is the modified codepen. Also, you’ll need to download the displacement map image and upload it on your webflow project. Here is the path to the displacement map. (right now uploaded on my webflow project)

https://codepen.io/anthonysalamin/pen/oNjQeXr

document.addEventListener("DOMContentLoaded", () => {
  water();
});

function water() {
  // 🧠 options
  let webflowUrl = "https://uploads-ssl.webflow.com/"; // 🧠 the default webflow upload url
  let dataWfSite = "5b05ed948ee27f736bbe9315"; // 🧠 this is your data-wf-site ID.
  let displacement = "5ec29f511ff8f57ad86daa00_displacementmap2.png"; // 🧠 this is your displacement map
  let image = "5ec29e93078f498c19c51855_rocks.jpg"; // 🧠 this is your image you'd like to animate

  let vw = 630;
  let vh = 410;

  let app = new PIXI.Application(vw, vh, {
    view: document.getElementById("canvas")
  });

  let loader = new PIXI.loaders.Loader(webflowUrl)
    .add(
      "displacementMap",
      `${dataWfSite}/${displacement}?v=1`
    )
    .add(
      "rocks",
      `${dataWfSite}/${image}?v=1`
    )
    .load(init);

  function init(loader, resources) {
    let container = new PIXI.Container();
    let background = new PIXI.Sprite(resources.rocks.texture);
    let displacementSprite = new PIXI.Sprite(resources.displacementMap.texture);
    let displacementFilter = new PIXI.filters.DisplacementFilter(
      displacementSprite
    );

    container.filterArea = new PIXI.Rectangle(0, 0, vw - 20, vh - 20);
    container.filters = [displacementFilter];
    displacementSprite.texture.baseTexture.wrapMode = PIXI.WRAP_MODES.REPEAT;

    container.position.set(-10);
    container.addChild(background);
    container.addChild(displacementSprite);
    app.stage.addChild(container);

    TweenMax.to(displacementSprite, 5, {
      ease: Linear.easeNone,
      repeat: -1,
      x: 512,
      y: 512
    });
  }
}

Here are some explanation what is what, hope that helps:

1 Like

Oh wow! Thanks @anthonysalamin! The explanation was very clear and comprehensive. :blush:

I’m sure your code works perfectly and I’m doing something wrong because still doesn’t work on my project :cry:

I’ve tried and replicated with my :brain: options but it doesn’t show anything :persevere:
not even the static image.
What I’ve done also was a trial with an empty page with only the HTLM and the code (in the body), checked many times the options and they seem ok! I can’t understand.

Maybe I can try with another system. Do you think it could work as well with an external URL for the displacement map and the picture?
Sometimes I use https://imgbb.com/ to save and then copy-paste the image’s address.

Anyway thank you so much :relaxed:

Hi @Martina_Salvaterra,
Ha ! Sorry, I forgot to mention there are actually two JavaScript libraries the author of the original codepen is using, namely TweenMax.js and pixi.js. You need to reference them aswell like so before the end of the body tag custom code section of your page:

libraries

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.4.1/pixi.min.js"></script>

then your custom script:

<script>
document.addEventListener("DOMContentLoaded", () => {
  water();
});

function water() {
  // 🧠 options
  let webflowUrl = "https://uploads-ssl.webflow.com/"; // 🧠 the default webflow upload url
  let dataWfSite = "5b05ed948ee27f736bbe9315"; // 🧠 this is your data-wf-site ID.
  let displacement = "5ec29f511ff8f57ad86daa00_displacementmap2.png"; // 🧠 this is your displacement map
  let image = "5ec29e93078f498c19c51855_rocks.jpg"; // 🧠 this is your image you'd like to animate

  let vw = 630;
  let vh = 410;

  let app = new PIXI.Application(vw, vh, {
    view: document.getElementById("canvas")
  });

  let loader = new PIXI.loaders.Loader(webflowUrl)
    .add(
      "displacementMap",
      `${dataWfSite}/${displacement}?v=1`
    )
    .add(
      "rocks",
      `${dataWfSite}/${image}?v=1`
    )
    .load(init);

  function init(loader, resources) {
    let container = new PIXI.Container();
    let background = new PIXI.Sprite(resources.rocks.texture);
    let displacementSprite = new PIXI.Sprite(resources.displacementMap.texture);
    let displacementFilter = new PIXI.filters.DisplacementFilter(
      displacementSprite
    );

    container.filterArea = new PIXI.Rectangle(0, 0, vw - 20, vh - 20);
    container.filters = [displacementFilter];
    displacementSprite.texture.baseTexture.wrapMode = PIXI.WRAP_MODES.REPEAT;

    container.position.set(-10);
    container.addChild(background);
    container.addChild(displacementSprite);
    app.stage.addChild(container);

    TweenMax.to(displacementSprite, 5, {
      ease: Linear.easeNone,
      repeat: -1,
      x: 512,
      y: 512
    });
  }
}
</script>

Give it a try and let me know if it worked.

And yes, it should work with any public URL. If you’re using webflow, why not use webflow to host your images (displacement and the actual image you wish to animate) ?

1 Like

Because I thought was the problem :see_no_evil:

But indeed, now with the js libraries, it works!! :scream: :heart_eyes: :partying_face:

Thanks, thanks so much! You’re a lifesaver! :blush:

2 Likes

Hi,

I tried following this as well. But unfortunately it doesn’t do what I want.
Instead of creating the effect on the image. It inserts the image on top again.
(I want it on the background image of section “coral reefs” - maybe I need another image as it might not be possible to see it properly on this one. - also thought about putting it on the first one - the hero image. But then I need to separate the image in water and background and only put it on the water part, I guess).


https://preview.webflow.com/preview/reef-viz-dahab?utm_medium=preview_link&utm_source=designer&utm_content=reef-viz-dahab&preview=ef274993e23761287f4fae014af40736&mode=preview

In Photoshop tutorial I learned, we can easily add a realistic water reflection to any photo. I feel that It’s a very easy effect to create and you can add it to any photo you like, although it tends to work best with images that don’t already contain water in them. Great Feature.
sofa cum bed uk