CSS переход на маску SVG? - PullRequest
1 голос
/ 15 марта 2019

У меня есть изображение внутри встроенного SVG, которое переключается между двумя масками при наведении курсора.

Однако переход CSS не работает с transition-property: mask;

Можно ли использовать другой метод, который работает с переходом CSS?

Я также попробовал стилизацию <mask>, но кажется, что элементы определения не могут быть стилизованы (?).

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
</head>
<body>
<div style="width: 604px; height: 302px; margin: 20px auto;"> <!-- IE needs width AND height specified to scale the SVG inside correctly. -->
<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">

	<style type="text/css">
		/* <![CDATA[ */
		.mask_hover a:link,
		.mask_hover a:visited {
			mask: url(#mask_right);
		}
		.mask_hover a:hover,
		.mask_hover a:active {
			transition-property: mask;
			transition-duration: 0.4s;
			transition-timing-function: ease-in-out;
			mask: url(#mask_left);
		}
		/* ]]> */
	</style>

	<defs>
		<mask id="mask_left">
			<circle id="circle_l" cx="416" cy="216" r="202" fill="#fff"/>
		</mask>
		
		<mask id="mask_right">
			<circle id="circle_r" cx="809" cy="337" r="202" fill="#fff"/>
		</mask>
		
	</defs>
	
	<g class="mask_hover">
		<a xlink:href="#">
			<image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
		</a>
	</g>
</svg>
</div>
</body>
</html>

Кредит изображения: Pixabay

1 Ответ

3 голосов
/ 15 марта 2019

Это не свойство mask, которое нельзя анимировать, а url() .

Чтобы создать переход, вам нужно иметь состояние 1, которое переходит в состояние 2 с возможностью создания интерполяции между обоими состояниями.
Когда вы используете url(#1) и хотите перейти к url(#2), нет никакой возможности создать какую-либо интерполяцию между этими двумя состояниями, потому что url(#1.5) не будет промежуточным состоянием.

Что может быть анимировано, так это содержимое вашей маски.

В SVG2 вы можете напрямую установить свойства, которые действительно изменились (например, cx и cy) из CSS, но это все еще поддерживается только браузерами Blink & Safari:

<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">
  <style type="text/css">
  /* <![CDATA[ */
    .mask_hover a:link,
    .mask_hover a:visited {
      mask: url(#mask);
    }
    #mask > circle {
      transition-property: cx, cy;
      transition-duration: 0.4s;
      transition-timing-function: ease-in-out;    
    }
    .mask_hover a:hover + defs #mask > circle,
    .mask_hover a:active + defs #mask > circle {
      cx: 416;
      cy: 216;
    }
  /* ]]> */
  </style>
  <g class="mask_hover">
    <a xlink:href="#">
      <image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
    </a>
    <!-- we need to move it here so we can target it with our CSS rules -->
    <defs>
      <mask id="mask">
        <circle id="circle_l" cx="809" cy="337" r="202"   fill="#fff"/>
      </mask>		
    </defs>
  </g>
</svg>

Для других браузеров, которые не поддерживают эту часть SVG2, вы должны иметь возможность делать это с помощью свойства transform, но каким-то образом Firefox не принимает это ...

<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">
  <style type="text/css">
  /* <![CDATA[ */
    .mask_hover a:link,
    .mask_hover a:visited {
    mask: url(#mask);
    }
    #mask > circle {
    transition-property: transform;
    transition-duration: 0.4s;
    transition-timing-function: ease-in-out;    
    }
    .mask_hover a:hover + defs #mask > circle,
    .mask_hover a:active + defs #mask > circle {
    transform: translate(-393px, -121px);
    }
  /* ]]> */
  </style>
  <g class="mask_hover">
    <a xlink:href="#">
     <image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
    </a>
  <!-- we need to move it here so we can target it with our CSS rules -->
  <defs>
    <mask id="mask">
     <circle id="circle_l" cx="809" cy="337" r="202" fill="#fff"/>
    </mask>		
  </defs>
  </g>
</svg>

Так что вы можете попробовать SMIL, но там вы не сможете использовать правило :active, и Safari содержит ошибку при реализации состояния наведения ...

<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">
  <style type="text/css">
  /* <![CDATA[ */
    .mask_hover a:link,
    .mask_hover a:visited {
      mask: url(#mask);
    }
  /* ]]> */
  </style>
  <defs>
    <mask id="mask">
      <circle id="circle_r" cx="809" cy="337" r="202" fill="#fff">
        <animateTransform attributeName="transform"
          attributeType="XML"
          type="translate"
          to="-393 -121"
          dur="0.4s"
          fill="freeze"
          begin="anchor.mouseover"/>
        <animateTransform attributeName="transform"
          attributeType="XML"
          type="translate"
          to="0 0"
          dur="0.4s"
          fill="freeze"
          begin="anchor.mouseout"/>
      </circle>
   </mask>
  </defs>
  <g class="mask_hover">
    <a xlink:href="#" id="anchor">
      <image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
    </a>
  </g>
</svg>

Таким образом, последний способ может заключаться в реализации всего этого, используя только clip-path из CSS:

<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">
  <style type="text/css">
  /* <![CDATA[ */
    .mask_hover a image {
      transition: clip-path .4s;
    }
    .mask_hover a {
      pointer-events: all;
    }
    .mask_hover a:link image,
     .mask_hover a:visited image{
      clip-path: circle(202px at 809px 337px);
    }
    .mask_hover a:hover image,
     .mask_hover a:active image{
      clip-path: circle(202px at 416px 216px);
    }
  /* ]]> */
  </style>
  <g class="mask_hover">
    <a xlink:href="#">
      <image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
      <!-- so we can hover everywhre -->
      <rect fill="none" width="1208" height="604"/>
    </a>
  </g>
</svg>
...