<p id="notSupport">喔不,你的瀏覽器不支援 clip path Q<>Q!!所以給你 canvas。</p>

<div class="image-wrapper">
  <img id="original-img" src="https://i.imgur.com/dYqaQU8.jpg" />
  <img id="invert-img" src="https://i.imgur.com/dYqaQU8.jpg" />
</div>

<canvas id="canvas" width="640" height="360"/>
.image-wrapper {
  width: 300px;
  overflow: hidden;
  object-fit: contain;
}

#original-img {
  position: absolute;
  left: 1em;
  height: 100%;
}

#invert-img {
  max-width: 0%;
  filter: invert(1);
  position: absolute;
  left: 1em;
  height: 100%;
}

#notSupport {
  display: none;
  font-size: 1em;
  margin: 10px;
}

#canvas {
  visibility: hidden; 
}
const platform = window.navigator.platform;
if (['iPhone', 'iPad'].indexOf(platform) !== -1) {
  document.querySelector('#notSupport').style.display = 'initial';
  document.querySelector('.image-wrapper').style.display = 'none';
  document.querySelector('#canvas').style.visibility = 'visible';
}

const createTheWorldAnimation = (x, y) => [
  {
    maxWidth: '100%',
    clipPath: `circle(0% at ${x}% ${y}%)`,
  },
  {
    clipPath: `circle(100%)`,
    offset: 0.01
  },
  {
    clipPath: `circle(100%)`,
    offset: 0.99
  },
  {
    maxWidth: '100%',
    clipPath: `circle(0% at ${x}% ${y}%)`,
  }
];

const vibrationAnimation = {
  transform: [
    'translate(0, 5px)',
    'translate(5px, 5px)',
    'translate(5px, 0)',
    'translate(0, 0)',
    'translate(5px, 0)',
    'translate(5px, 5px)',
    'translate(0, 0)',
    'translate(0, 5px)',
  ]
}

const imageElement = document.querySelector('#original-img');
const invertElement = document.querySelector('#invert-img');

imageElement.addEventListener('click', e => {  
  const { width, height } = imageElement.getBoundingClientRect();
  const xPertentage = ((e.layerX / width) * 100).toPrecision(4);
  const yPertenage = ((e.layerY / height) * 100).toPrecision(4);
  
    invertElement.animate(createTheWorldAnimation(xPertentage, yPertenage), {
      duration: 3000,
      easing: 'ease-in-out',
      delay: 1000,
    });
    
    invertElement.animate(vibrationAnimation, {
      duration: 500,
      iterations: 1,
      delay: 1000,
    });
    
    imageElement.animate(vibrationAnimation, {
      duration: 500,
      iterations: 1,
      delay: 1000,
    });
});

// canvas

const img = new Image();
img.crossOrigin = "Anonymous";
img.src = "https://i.imgur.com/dYqaQU8.jpg";

function coordination(index, width, height) {
  if (index > width * height * 4) {
    console.error('GET COORDINATION ERROR: index exceed');
  }

  return {
    x: index % (width * 4),
    y: Math.floor(index / width),
  }
}

function invertCircle(image, offsetX, offsetY, r) {
  const tempImage = new ImageData(image.data.slice(), image.width, image.height);
  for (let i = 0; i < tempImage.data.length; i += 4) {
    const {x, y} = coordination(i, 640, 360);

    if (Math.pow(y - (offsetY * 4), 2) <= Math.pow(r, 2) - Math.pow(x - (offsetX * 4), 2)) {

      tempImage.data[i] = 255 - tempImage.data[i];
      tempImage.data[i + 1] = 255 - tempImage.data[i + 1];
      tempImage.data[i + 2] = 255 - tempImage.data[i + 2];
    }          
  }

  return tempImage;
}

const canvas = document.querySelector("#canvas").getContext("2d");
const canvasElement = document.querySelector("#canvas");

img.addEventListener("load", (e) => {
  canvas.drawImage(img, 0, 0, 640, 360);
  
  const imageData = canvas.getImageData(0, 0, 640, 360);
  let count = 1;
  let invertFlag = true;

  function inverter(x, y) {
    canvas.putImageData(invertCircle(imageData, x, y, 100 * count), 0, 0);
    invertFlag = count < 30 && invertFlag;

    count = invertFlag ? count + 1 : count - 1;
    if (count > -1) {
      console.log('count', count);
      requestAnimationFrame(() => {inverter(x, y)});
    } else {
      invertFlag = true;
    }
  }

  document.querySelector("#canvas").addEventListener("click", e => {
    document.querySelector("#canvas").animate(vibrationAnimation, 500);
    requestAnimationFrame(() => {inverter(e.layerX, e.layerY)});
  });
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/web-animations/2.3.2/web-animations.min.js