How to implement animation of smooth morphing of image borders?

enter a description of the image here

There is a picture, when hovering, its borders should start to randomly float, bend, until the cursor is removed.

As far as I understood, this should be related to svg morphing, but I didn't find an example. Only pure svg animation, no picture. Maybe someone has a specific example?

Author: Alexandr_TT, 2020-07-04

3 answers

Solution using SVG mask

To implement a smooth change in the image borders, a mask animation is applied.
Inside the mask is a path, the shape of which will change with the animation of the attribute d

The technique for obtaining path formulas for the initial and final state of the image border line is given in the topic Smooth morphing of one path to another path

Using these techniques you can get any custom form of animation borders

1. Example of border change animation

Read the comments in the code, I hope this will help you understand how animation and masks work

<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
     width="250" height="250"   viewBox="0 0 250 250" preserveAspectRatio="xMinYMin meet" >  
 <defs>
  <mask id="msk1">
      <!-- Ко всему изображению применён чёрный цвет маски, поэтому всё пространство вне элипса становится невидимым -->
     <rect width="100%" height="100%" fill="black" />   
        <!-- Участок изображения ограниченный кривой при fill="white" становится видимым -->
    <path  fill="white" d ="M 0.65716244,24.31501 C 0.65716244,12.769206 14.091902,-0.12750335 25.629335,0.31207405 95.055812,2.95723 165.66239,2.95723 224.74955,-0.15260996 236.62119,-0.777431 250.69703,12.426939 250.69703,24.31501 c 0,73.172941 0,139.28327 0,200.43454 0,12.31193 -13.63555,26.2865 -25.94748,26.2865 -63.86693,0 -130.775322,0 -199.120215,0 -12.085756,0 -24.97217256,-14.20074 -24.97217256,-26.2865 0,-61.39127 0,-133.050269 0,-200.43454 z" > 
       <!-- анимация изменения формы границы -->
    <animate
      attributeName="d"
      begin="0s"
      dur="8s"
      repeatCount="indefinite"
      values="
      M 0.65716244,24.31501 C 0.65716244,12.769206 14.091902,-0.12750335 25.629335,0.31207405 95.055812,2.95723 165.66239,2.95723 224.74955,-0.15260996 236.62119,-0.777431 250.69703,12.426939 250.69703,24.31501 c 0,73.172941 0,139.28327 0,200.43454 0,12.31193 -13.63555,26.2865 -25.94748,26.2865 -63.86693,0 -130.775322,0 -199.120215,0 -12.085756,0 -24.97217256,-14.20074 -24.97217256,-26.2865 0,-61.39127 0,-133.050269 0,-200.43454 z;
      
     M 18.400548,36.143934 C 9.9101837,13.70807 43.926223,-0.54996925 51.25867,13.455323 c 76.33542,145.803977 86.46964,86.869767 141.28992,2.163965 18.44086,-28.493975 46.29247,8.882468 40.40505,19.210321 -38.20947,67.028001 -97.855,59.568605 -3.94297,138.004111 21.54722,17.99629 -0.61149,66.59059 -19.37585,46.00136 C 198.19796,206.28598 136.75871,43.292058 55.858806,212.92063 41.687846,242.63389 13.162026,189.96512 27.600822,178.74818 116.80291,109.45052 37.717611,87.189447 18.400548,36.143934 Z;
      
      M 0.65716244,24.31501 C 0.65716244,12.769206 14.091902,-0.12750335 25.629335,0.31207405 95.055812,2.95723 165.66239,2.95723 224.74955,-0.15260996 236.62119,-0.777431 250.69703,12.426939 250.69703,24.31501 c 0,73.172941 0,139.28327 0,200.43454 0,12.31193 -13.63555,26.2865 -25.94748,26.2865 -63.86693,0 -130.775322,0 -199.120215,0 -12.085756,0 -24.97217256,-14.20074 -24.97217256,-26.2865 0,-61.39127 0,-133.050269 0,-200.43454 z;" 
      />
    </path>
   </mask>
    </defs>  
       <!-- К изображению девушки применена маска -->
<image id="img1" xlink:href="https://i.stack.imgur.com/73YNh.jpg"  width="100%" height="100%"
       pointer-events="fill" mask="url(#msk1)" />
</svg>

2. Example of animating a shape change using JS when clicking on an image

<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
     width="250" height="250"   viewBox="0 0 250 250" preserveAspectRatio="xMinYMin meet" >  
 <defs>
  <mask id="msk1">
      <!-- Ко всему изображению применён чёрный цвет маски, поэтому всё пространство вне пр\моугольника становится невидимым -->
     <rect width="100%" height="100%" fill="black" />   
       <!-- Участок изображения ограниченный кривой при fill="white" становится видимым -->
    <path  fill="white" d ="M 0.65716244,24.31501 C 0.65716244,12.769206 14.091902,-0.12750335 25.629335,0.31207405 95.055812,2.95723 165.66239,2.95723 224.74955,-0.15260996 236.62119,-0.777431 250.69703,12.426939 250.69703,24.31501 c 0,73.172941 0,139.28327 0,200.43454 0,12.31193 -13.63555,26.2865 -25.94748,26.2865 -63.86693,0 -130.775322,0 -199.120215,0 -12.085756,0 -24.97217256,-14.20074 -24.97217256,-26.2865 0,-61.39127 0,-133.050269 0,-200.43454 z" > 
      
      <!-- Анимация изменения формы границы после клика по изображению -->
    <animate id="open"
      attributeName="d"
      begin="idefinite"
      dur="1s"
      repeatCount="1"
      fill="freeze"
    restart="whenNotActive"
      values="
      M 0.65716244,24.31501 C 0.65716244,12.769206 14.091902,-0.12750335 25.629335,0.31207405 95.055812,2.95723 165.66239,2.95723 224.74955,-0.15260996 236.62119,-0.777431 250.69703,12.426939 250.69703,24.31501 c 0,73.172941 0,139.28327 0,200.43454 0,12.31193 -13.63555,26.2865 -25.94748,26.2865 -63.86693,0 -130.775322,0 -199.120215,0 -12.085756,0 -24.97217256,-14.20074 -24.97217256,-26.2865 0,-61.39127 0,-133.050269 0,-200.43454 z;
      
     M 18.400548,36.143934 C 9.9101837,13.70807 43.926223,-0.54996925 51.25867,13.455323 c 76.33542,145.803977 86.46964,86.869767 141.28992,2.163965 18.44086,-28.493975 46.29247,8.882468 40.40505,19.210321 -38.20947,67.028001 -97.855,59.568605 -3.94297,138.004111 21.54722,17.99629 -0.61149,66.59059 -19.37585,46.00136 C 198.19796,206.28598 136.75871,43.292058 55.858806,212.92063 41.687846,242.63389 13.162026,189.96512 27.600822,178.74818 116.80291,109.45052 37.717611,87.189447 18.400548,36.143934 Z" 
      />  
      <!-- Анимация возврата к первоначальной форме границы после повторного клика по изображению -->
      <animate id="close"
      attributeName="d"
      begin="idefinite"
      dur="1s"
      repeatCount="1"
      fill="freeze"
    restart="whenNotActive"
      values="
            M 18.400548,36.143934 C 9.9101837,13.70807 43.926223,-0.54996925 51.25867,13.455323 c 76.33542,145.803977 86.46964,86.869767 141.28992,2.163965 18.44086,-28.493975 46.29247,8.882468 40.40505,19.210321 -38.20947,67.028001 -97.855,59.568605 -3.94297,138.004111 21.54722,17.99629 -0.61149,66.59059 -19.37585,46.00136 C 198.19796,206.28598 136.75871,43.292058 55.858806,212.92063 41.687846,242.63389 13.162026,189.96512 27.600822,178.74818 116.80291,109.45052 37.717611,87.189447 18.400548,36.143934 Z;
      
           M 0.65716244,24.31501 C 0.65716244,12.769206 14.091902,-0.12750335 25.629335,0.31207405 95.055812,2.95723 165.66239,2.95723 224.74955,-0.15260996 236.62119,-0.777431 250.69703,12.426939 250.69703,24.31501 c 0,73.172941 0,139.28327 0,200.43454 0,12.31193 -13.63555,26.2865 -25.94748,26.2865 -63.86693,0 -130.775322,0 -199.120215,0 -12.085756,0 -24.97217256,-14.20074 -24.97217256,-26.2865 0,-61.39127 0,-133.050269 0,-200.43454 z" 
      /> 
    </path>
  
 </mask>
    </defs>  
    
       
    
            <!-- К изображению девушки применена маска -->
<image id="img1" xlink:href="https://i.stack.imgur.com/73YNh.jpg"  width="100%" height="100%"
       pointer-events="fill" mask="url(#msk1)" />
</svg>  
<script>
var lion_svg1 = document.getElementById("svg1"),
  close = document.getElementById('close'),
  open = document.getElementById("open");

let flag = true;

lion_svg1.addEventListener('click', function() {
  if (flag == true) {
    open.beginElement();
    flag = false;
  } else {
    close.beginElement();
    flag = true;
  }
}); 
</script>

3. Example of animation of border changes after hovering or leaving the cursor

Adding a wide border with coloring in red makes it semi-transparent
stroke-width="10" stroke="red"

<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
     width="250" height="250"   viewBox="0 0 250 250" preserveAspectRatio="xMinYMin meet" >  
 <defs>
  <mask id="msk1">
      <!-- Ко всему изображению применён чёрный цвет маски, поэтому всё пространство вне пр\моугольника становится невидимым -->
     <rect width="100%" height="100%" fill="black" />   
       <!-- Участок изображения ограниченный кривой при fill="white" становится видимым --> 
         <!-- Добавление широкой границы с окраской в красный цвет делает её полупрозрачной   stroke-width="10" stroke="red" -->
    <path  fill="white" stroke-width="10" stroke="red" d ="M 0.65716244,24.31501 C 0.65716244,12.769206 14.091902,-0.12750335 25.629335,0.31207405 95.055812,2.95723 165.66239,2.95723 224.74955,-0.15260996 236.62119,-0.777431 250.69703,12.426939 250.69703,24.31501 c 0,73.172941 0,139.28327 0,200.43454 0,12.31193 -13.63555,26.2865 -25.94748,26.2865 -63.86693,0 -130.775322,0 -199.120215,0 -12.085756,0 -24.97217256,-14.20074 -24.97217256,-26.2865 0,-61.39127 0,-133.050269 0,-200.43454 z" > 
    
      <!-- анимация изменения формы кривой при наведении курсора -->
    <animate id="open"
      attributeName="d"
      begin="svg1.mouseover"
      dur="0.25s"
      repeatCount="1"
      fill="freeze"
    restart="WhenNotActive"
      values="
      M 0.65716244,24.31501 C 0.65716244,12.769206 14.091902,-0.12750335 25.629335,0.31207405 95.055812,2.95723 165.66239,2.95723 224.74955,-0.15260996 236.62119,-0.777431 250.69703,12.426939 250.69703,24.31501 c 0,73.172941 0,139.28327 0,200.43454 0,12.31193 -13.63555,26.2865 -25.94748,26.2865 -63.86693,0 -130.775322,0 -199.120215,0 -12.085756,0 -24.97217256,-14.20074 -24.97217256,-26.2865 0,-61.39127 0,-133.050269 0,-200.43454 z;
      
     M 18.400548,36.143934 C 9.9101837,13.70807 43.926223,-0.54996925 51.25867,13.455323 c 76.33542,145.803977 86.46964,86.869767 141.28992,2.163965 18.44086,-28.493975 46.29247,8.882468 40.40505,19.210321 -38.20947,67.028001 -97.855,59.568605 -3.94297,138.004111 21.54722,17.99629 -0.61149,66.59059 -19.37585,46.00136 C 198.19796,206.28598 136.75871,43.292058 55.858806,212.92063 41.687846,242.63389 13.162026,189.96512 27.600822,178.74818 116.80291,109.45052 37.717611,87.189447 18.400548,36.143934 Z" 
      /> 
     
   <!-- анимация изменения формы кривой при покидании курсора -->
     <animate id="close"
      attributeName="d"
      begin="svg1.mouseleave"
      dur="0.25s"
      repeatCount="1"
      fill="freeze"
    restart="WhenNotActive"
      values="
            M 18.400548,36.143934 C 9.9101837,13.70807 43.926223,-0.54996925 51.25867,13.455323 c 76.33542,145.803977 86.46964,86.869767 141.28992,2.163965 18.44086,-28.493975 46.29247,8.882468 40.40505,19.210321 -38.20947,67.028001 -97.855,59.568605 -3.94297,138.004111 21.54722,17.99629 -0.61149,66.59059 -19.37585,46.00136 C 198.19796,206.28598 136.75871,43.292058 55.858806,212.92063 41.687846,242.63389 13.162026,189.96512 27.600822,178.74818 116.80291,109.45052 37.717611,87.189447 18.400548,36.143934 Z;
      
           M 0.65716244,24.31501 C 0.65716244,12.769206 14.091902,-0.12750335 25.629335,0.31207405 95.055812,2.95723 165.66239,2.95723 224.74955,-0.15260996 236.62119,-0.777431 250.69703,12.426939 250.69703,24.31501 c 0,73.172941 0,139.28327 0,200.43454 0,12.31193 -13.63555,26.2865 -25.94748,26.2865 -63.86693,0 -130.775322,0 -199.120215,0 -12.085756,0 -24.97217256,-14.20074 -24.97217256,-26.2865 0,-61.39127 0,-133.050269 0,-200.43454 z" 
      /> 
    </path>
   </mask>
    </defs>  
           <!-- К изображению девушки применена маска -->
<image id="img1" xlink:href="https://i.stack.imgur.com/73YNh.jpg"  width="100%" height="100%"
       pointer-events="fill" mask="url(#msk1)" />
</svg>

4. Morphing a rectangle into an oval when hovering the cursor

<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
     width="250" height="250"   viewBox="0 0 250 250" preserveAspectRatio="xMinYMin meet" >  
 <defs>
  <mask id="msk1">
      <!-- Ко всему изображению применён чёрный цвет маски, поэтому всё пространство вне пр\моугольника становится невидимым -->
     <rect width="100%" height="100%" fill="black" />   
       <!-- Участок изображения ограниченный кривой при fill="white" становится видимым --> 
         <!-- Добавление широкой границы с окраской в красный цвет делает её полупрозрачной   stroke-width="10" stroke="red" -->
    <path  fill="white" stroke-width="10" stroke="red" d ="m 249.74954,120.11816 c -0.032,33.80035 0.94749,70.87812 0.71924,101.39854 -0.0941,12.58837 -12.25359,28.03187 -24.83532,28.45154 -32.01304,1.06781 -66.74462,1.86496 -100.05841,-0.0897 -33.048172,-1.93908 -64.250431,1.15753 -99.314815,0.21055 C 18.620731,249.88275 2.7940939,236.54064 2.2155966,225.78362 0.65716244,196.8049 1.3036891,156.87429 1.4005632,122.41823 1.4912502,90.1628 0.65716244,60.443397 2.707633,25.660386 3.3483296,14.791976 15.595091,3.365135 26.481903,3.2644139 59.685029,2.95723 92.106049,2.5598942 124.91789,2.1867235 c 32.54245,-0.370107 66.11789,0.1133441 97.62686,-1.1517993 9.43211,-0.37871659 28.01925,11.9761648 28.05329,24.6882068 0.099,36.962802 -0.81868,62.928765 -0.8485,94.395029 z" > 
    
      <!-- анимация изменения формы кривой при наведении курсора -->
    <animate id="open"
      attributeName="d"
      begin="svg1.mouseover"
      dur="0.5s"
      repeatCount="1"
      fill="freeze"
      restart="whenNotActive"
      values="
      m 249.74954,120.11816 c -0.032,33.80035 0.94749,70.87812 0.71924,101.39854 -0.0941,12.58837 -12.25359,28.03187 -24.83532,28.45154 -32.01304,1.06781 -66.74462,1.86496 -100.05841,-0.0897 -33.048172,-1.93908 -64.250431,1.15753 -99.314815,0.21055 C 18.620731,249.88275 2.7940939,236.54064 2.2155966,225.78362 0.65716244,196.8049 1.3036891,156.87429 1.4005632,122.41823 1.4912502,90.1628 0.65716244,60.443397 2.707633,25.660386 3.3483296,14.791976 15.595091,3.365135 26.481903,3.2644139 59.685029,2.95723 92.106049,2.5598942 124.91789,2.1867235 c 32.54245,-0.370107 66.11789,0.1133441 97.62686,-1.1517993 9.43211,-0.37871659 28.01925,11.9761648 28.05329,24.6882068 0.099,36.962802 -0.81868,62.928765 -0.8485,94.395029 z;
      
     m 221.49156,121.76107 c -0.69227,23.05451 -6.7151,46.60634 -17.68131,66.89751 -6.97552,12.90704 -17.15264,24.69924 -29.43545,32.7231 -14.53539,9.49538 -32.09533,16.21404 -49.45691,16.33934 -16.56191,0.11952 -33.444079,-5.98391 -47.398985,-14.9042 -13.467298,-8.60861 -24.66387,-21.4135 -32.259169,-35.4772 C 34.532257,167.47628 29.118446,144.3228 28.344223,121.76107 27.76932,105.00775 30.919476,87.720522 37.537242,72.318919 45.292705,54.26954 56.430489,36.398301 72.154692,24.622193 87.101007,13.428659 106.24474,5.7671169 124.91789,5.8011169 c 18.87659,0.03437 38.10425,7.9785591 53.2684,19.2202361 14.61764,10.836531 25.23724,27.129484 32.65343,43.745917 7.34348,16.453518 11.19263,34.98401 10.65184,52.9938 z" 
      /> 
     
   <!-- анимация изменения формы кривой при покидании курсора -->
     <animate id="close"
      attributeName="d"
      begin="svg1.mouseleave"
      dur="0.5s"
      repeatCount="1"
      fill="freeze"
      restart="whenNotActive"
      values="
            m 221.49156,121.76107 c -0.69227,23.05451 -6.7151,46.60634 -17.68131,66.89751 -6.97552,12.90704 -17.15264,24.69924 -29.43545,32.7231 -14.53539,9.49538 -32.09533,16.21404 -49.45691,16.33934 -16.56191,0.11952 -33.444079,-5.98391 -47.398985,-14.9042 -13.467298,-8.60861 -24.66387,-21.4135 -32.259169,-35.4772 C 34.532257,167.47628 29.118446,144.3228 28.344223,121.76107 27.76932,105.00775 30.919476,87.720522 37.537242,72.318919 45.292705,54.26954 56.430489,36.398301 72.154692,24.622193 87.101007,13.428659 106.24474,5.7671169 124.91789,5.8011169 c 18.87659,0.03437 38.10425,7.9785591 53.2684,19.2202361 14.61764,10.836531 25.23724,27.129484 32.65343,43.745917 7.34348,16.453518 11.19263,34.98401 10.65184,52.9938 z;
      
           m 249.74954,120.11816 c -0.032,33.80035 0.94749,70.87812 0.71924,101.39854 -0.0941,12.58837 -12.25359,28.03187 -24.83532,28.45154 -32.01304,1.06781 -66.74462,1.86496 -100.05841,-0.0897 -33.048172,-1.93908 -64.250431,1.15753 -99.314815,0.21055 C 18.620731,249.88275 2.7940939,236.54064 2.2155966,225.78362 0.65716244,196.8049 1.3036891,156.87429 1.4005632,122.41823 1.4912502,90.1628 0.65716244,60.443397 2.707633,25.660386 3.3483296,14.791976 15.595091,3.365135 26.481903,3.2644139 59.685029,2.95723 92.106049,2.5598942 124.91789,2.1867235 c 32.54245,-0.370107 66.11789,0.1133441 97.62686,-1.1517993 9.43211,-0.37871659 28.01925,11.9761648 28.05329,24.6882068 0.099,36.962802 -0.81868,62.928765 -0.8485,94.395029 z" 
      /> 
    </path>
  
 </mask>
    </defs>  
            <!-- К изображению девушки применена маска -->
<image id="img1" xlink:href="https://i.stack.imgur.com/73YNh.jpg"  width="100%" height="100%"
       pointer-events="fill" mask="url(#msk1)" />
</svg>  
 6
Author: Alexandr_TT, 2020-07-06 08:38:28

In general, smil

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  max-width: 300px;
  margin: 0px auto;
}
<div class="container">
  <svg viewBox="0 0 150 150" id="svg" xmlns="http://www.w3.org/2000/svg">
    <defs>
      <clipPath id="mask">
        <path d="m123.3 221.82a47.625 48.57 0 0 1-47.625 48.57 47.625 48.57 0 0 1-47.625-48.57 47.625 48.57 0 0 1 47.625-48.57 47.625 48.57 0 0 1 47.625 48.57z" fill="none" stroke="#000">
        <animate attributeName="d" 
                 dur="12s"
                 begin="svg.mousemove" 
                 end="svg.mouseout"
                 values="m 123.29583,221.82054 c 0,26.82444 -22.2105,55.34697 -47.625,48.56994 -23.20821,-6.1887 -44.672416,-27.65067 -47.625,-48.56994 -3.748893,-26.56118 21.322438,-48.56994 47.625,-48.56994 26.30256,0 47.625,21.7455 47.625,48.56994 z;
m 123.29583,221.82054 c 0,26.82444 -21.32244,48.56994 -47.625,48.56994 -26.302562,0 -55.96245,-23.07411 -47.625,-48.56994 5.885147,-17.99672 25.450452,-42.37792 47.625,-48.56994 25.33341,-7.0741 47.625,21.7455 47.625,48.56994 z;
m 123.29583,221.82054 c 6.27285,26.08068 -21.32244,48.56994 -47.625,48.56994 -26.302562,0 -47.625001,-21.7455 -47.625,-48.56994 -10e-7,-26.82444 22.703382,-56.98051 47.625,-48.56994 23.884403,8.06053 44.04413,33.68173 47.625,48.56994 z;
m 123.29583,221.82054 c 5.53265,28.52679 -13.8157,50.87971 -47.625,48.56994 -26.241395,-1.79275 -47.625001,-21.7455 -47.625,-48.56994 -10e-7,-26.82444 21.322438,-48.56994 47.625,-48.56994 26.30256,0 42.51769,22.2362 47.625,48.56994 z;
m123.3 221.82a47.625 48.57 0 0 1-47.625 48.57 47.625 48.57 0 0 1-47.625-48.57 47.625 48.57 0 0 1 47.625-48.57 47.625 48.57 0 0 1 47.625 48.57z"
                 repeatCount="indefinite"/>
      </path>
   </clipPath>
    </defs>
    
     <g transform="translate(0,-147)">
     <image href="https://sun9-72.userapi.com/c824600/v824600327/19d5b5/4kUSTPvShoQ.jpg?ava=1" 
           x="0" y="150" 
           width="150" height="150"
           clip-path="url(#mask)"
          preserveAspectRatio="none"/>
     </g>
    
    

  </svg>
</div>
 8
Author: MaximLensky, 2020-07-06 01:42:12

A simple CSS version using a "pseudo-mask" made from an image with a transparent "blob".
The "Pseudo-mask" goes over the image, initially with the property scale(2), when hovering over the parent, scale(1) is applied.

.image {
  display: inline-block;
  overflow: hidden;
  position: relative;
}

.image .pseudo-mask {
  display: block;
  width: 100%;
  height: 100%;
  background: url('https://i.imgur.com/nj9o1MA.png') no-repeat center center / 100% 100%;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(2);
  transition: all .3s linear;
  z-index: 1;
}

.image > img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border: 0;
  border-radius: 20px;
}

.image:hover .pseudo-mask {
  transform: translate(-50%, -50%) scale(1);
}
<div class="image">
  <div class="pseudo-mask"></div>
  <img src="https://i.imgur.com/5NBOFbo.png">
</div>

With animation of rotation after hover.

You will have to increase the size of the image, so that the "klaxa" itself remains the same size, and its background becomes larger. I increased in .5 times, from the previous one size.
After that, you will have to change the initial scale(2), to 2.5, and the final one to 1.5.

After adding the rotation animation, taking into account the previous entries in transform.

It turns out something like this:

.image {
  display: inline-block;
  overflow: hidden;
  position: relative;
}

.image .pseudo-mask {
  display: block;
  width: 100%;
  height: 100%;
  background: url('https://i.imgur.com/cmz0d0O.png') no-repeat center center / 95% 95%;
  /* Пришлось немного уменьщить размер, чтобы не вылезало за края */
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(2.5);
  transition: all .3s linear;
  z-index: 1;
}

.image > img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border: 0;
  border-radius: 20px;
}

.image:hover .pseudo-mask {
  transform: translate(-50%, -50%) scale(1.5);
  animation: pseudo-mask-rotate 30s .3s linear infinite;
  /* .3s это задержка, чтобы анимация "появления" при наведение отработала нормально, а после началось вращение */
}

@keyframes pseudo-mask-rotate {
  100% {
    transform: translate(-50%, -50%) scale(1.5) rotate(1turn);
  }
}
<div class="image">
  <div class="pseudo-mask"></div>
  <img src="https://i.imgur.com/5NBOFbo.png">
</div>

But there is a minus when :hover is reset, the animation is also reset abruptly..

All I could think of was to change scale() to width and height:

.image {
  display: inline-block;
  overflow: hidden;
  position: relative;
}

.image .pseudo-mask {
  display: block;
  width: calc(100% * 2.5);
  height: calc(100% * 2.5);
  background: url('https://i.imgur.com/cmz0d0O.png') no-repeat center center / 95% 95%;
  /* Пришлось немного уменьщить размер, чтобы не вылезало за края */
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  transition: all .3s linear;
  z-index: 1;
}

.image > img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border: 0;
  border-radius: 20px;
}

.image:hover .pseudo-mask {
  width: calc(100% * 1.5);
  height: calc(100% * 1.5);
  animation: pseudo-mask-rotate 30s .3s linear infinite;
  /* .3s это задержка, чтобы анимация "появления" при наведение отработала нормально, а после началось вращение */
}

@keyframes pseudo-mask-rotate {
  100% {
    transform: translate(-50%, -50%) rotate(1turn);
  }
}
<div class="image">
  <div class="pseudo-mask"></div>
  <img src="https://i.imgur.com/5NBOFbo.png">
</div>
 6
Author: CbIPoK2513, 2020-07-06 15:06:29