Как сделать CSS transition для маски SVG?

160
02 декабря 2019, 10:00

У меня есть изображение внутри встроенного SVG, которое переключается при наведении курсора между двумя масками.
Однако CSS-transition не работает в этом случае со свойством transition-property: mask;

Можно ли использовать другой метод, который работает с transition 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>

Answer 1

На самом деле это не свойство маски, которое нельзя анимировать, а url() <func>.

Чтобы создать transition, вам нужно иметь состояние 1, которое переходит в состояние 2 с возможностью создания интерполяции между обоими состояниями.

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

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

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

<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>

READ ALSO
Плавный переход изображения в CSS [закрыт]

Плавный переход изображения в CSS [закрыт]

Есть картинка снизу, где при помощи фотошопа происходит постепенный переход изображения к прозрачности

155
json в структуру

json в структуру

Отправляю json через js сокет, читаю сообщение на сервере go:

150
Как на TypeScript указать тип для фукнции?

Как на TypeScript указать тип для фукнции?

Мне нужно написать на typeScript типы для функции, которая принимает объект config, в свойствах которого записаны функции, а возвращает объект с теме...

142
Проблема с массивом | Discord Bot | NODE.js | JavaScript | discord.js

Проблема с массивом | Discord Bot | NODE.js | JavaScript | discord.js

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

144