跨浏览器渐变遮罩

Cross browser gradient mask

我有一个背景垂直滚动的 CSS3 动画。我想让背景的顶部逐渐淡出。我在 Chrome 中使用:

实现了这一点
-webkit-mask-box-image: -webkit-linear-gradient(transparent, black);

是否有跨浏览器的方式来实现这一点?也许使用 SVG 蒙版?或者甚至 JavaScript 设置此动画的解决方案?

请参阅下面的示例代码:

div {
  background-image: linear-gradient(rgba(24, 49, 67, .95), rgba(24, 49, 67, .88)), url(https://static.pexels.com/photos/96380/pexels-photo-96380.jpeg);
  background-size: cover;
  position: absolute;
  width: 500px;
  height: 500px;
}
div:before {
  background: url(https://dl.dropboxusercontent.com/u/3454522/shapes1.svg);
  content: '';
  display: block;
  position: absolute;
  right: 0;
  left: 0;
  bottom: 0;
  background-size: 100%;
  height: 500px;
  animation: bgscroll 100s infinite linear;
  -webkit-mask-box-image: linear-gradient(transparent, black);
}
@keyframes bgscroll {
  100% {
    background-position: 0px -3000px;
  }
}
<div>
</div>

跨浏览器掩码:

是的,我们可以使用 SVG 蒙版实现跨浏览器蒙版。为此,我们需要将背景图像(您的形状 SVG)和蒙版放在同一个 SVG 元素上,如下面的代码片段所示。这部分答案适用于 Chrome、Firefox、Opera(所有最新版本)、IE11 和 Edge。它也应该在 IE9 和 IE10 中工作,因为它们支持基本的 SVG、遮罩和裁剪。

div {
  background-image: linear-gradient(rgba(24, 49, 67, .95), rgba(24, 49, 67, .88)), url(https://static.pexels.com/photos/96380/pexels-photo-96380.jpeg);
  background-size: cover;
  position: absolute;
  width: 500px;
  height: 500px;
}
svg {
  position: absolute;
  right: 0;
  left: 0;
  bottom: 0;
  height: 500px;
  width: 500px;
}
<div>
  <svg viewBox='0 0 500 500' id='svg1'>
    <defs>
      <pattern id='bg-img' patternUnits='userSpaceOnUse' width='500' height='500' patternTransform='translate(0 3000)'>
        <image xlink:href='https://dl.dropboxusercontent.com/u/3454522/shapes1.svg' x='0' y='0' width='500' height='500' />
      </pattern>
      <linearGradient id='grad' gradientTransform='rotate(90 250 250)'>
        <stop offset='0%' stop-color='black' />
        <stop offset='100%' stop-color='white' />
      </linearGradient>
      <mask id='msk'>
        <polygon points='0,0 0,500 500,500 500,0' fill='url(#grad)' />
      </mask>
    </defs>
    <polygon points='0,0 0,500 500,500 500,0' fill='url(#bg-img)' mask='url(#msk)' />
  </svg>
</div>


跨浏览器遮罩动画:

理论上,使用SVG的patternTransform属性也可以实现动画效果。我们可以将 translate 转换添加到 pattern 元素并使其模仿 background-position 动画。

var y = 3000;
var svg1 = document.getElementById('bg-img');
setInterval(function() {
  y = (y <= 0) ? 3000 : y - 10;
  svg1.setAttribute('patternTransform', 'translate(0 ' + y + ')');
}, 100);
div {
  background-image: linear-gradient(rgba(24, 49, 67, .95), rgba(24, 49, 67, .88)), url(https://static.pexels.com/photos/96380/pexels-photo-96380.jpeg);
  background-size: cover;
  position: absolute;
  width: 500px;
  height: 500px;
}
svg {
  position: absolute;
  right: 0;
  left: 0;
  bottom: 0;
  height: 500px;
  width: 500px;
}
<div>
  <svg viewBox='0 0 500 500' id='svg1'>
    <defs>
      <pattern id='bg-img' patternUnits='userSpaceOnUse' width='500' height='500' patternTransform='translate(0 3000)'>
        <image xlink:href='https://dl.dropboxusercontent.com/u/3454522/shapes1.svg' x='0' y='0' width='500' height='500' />
      </pattern>
      <linearGradient id='grad' gradientTransform='rotate(90 250 250)'>
        <stop offset='0%' stop-color='black' />
        <stop offset='100%' stop-color='white' />
      </linearGradient>
      <mask id='msk'>
        <polygon points='0,0 0,500 500,500 500,0' fill='url(#grad)' />
      </mask>
    </defs>
    <polygon points='0,0 0,500 500,500 500,0' fill='url(#bg-img)' mask='url(#msk)' />
  </svg>
</div>

不幸的是,这似乎只在 Chrome、Firefox 和 Opera 中有效。与往常一样,IE 的行为有所不同并且不会更改模式位置,即使 patterTransform 已正确应用。


在 IE 中也有效 如果我们为模式的 y 属性设置动画 使用 snap.svg 库.

var s = Snap("#svg1");

var polygon = s.polygon([0, 0, 0, 500, 500, 500, 500, 0]);
var mask = s.polygon([0, 0, 0, 500, 500, 500, 500, 0]);
var grad = s.gradient('L(0,0,500,500)#000-#fff').attr({
  gradientTransform: 'rotate(45,250,250)'
});
var pattern = s.image('https://dl.dropboxusercontent.com/u/3454522/shapes1.svg', 0, 0, 500, 500)
  .pattern(0, 0, 500, 500);
mask.attr({
  fill: grad
});
polygon.attr({
  fill: pattern,
  mask: mask
});

function animIn() {
  this.animate({
    y: '0'
  }, 10000, mina.linear, animOut);
}

function animOut() {
  this.animate({
    y: '3000'
  }, 0, mina.linear, animIn);
};
pattern.animate({
  y: '3000'
}, 0, mina.linear, animIn);
div {
  background-image: linear-gradient(rgba(24, 49, 67, .95), rgba(24, 49, 67, .88)), url(https://static.pexels.com/photos/96380/pexels-photo-96380.jpeg);
  background-size: cover;
  position: absolute;
  width: 500px;
  height: 500px;
}

svg {
  position: absolute;
  right: 0;
  left: 0;
  bottom: 0;
  height: 500px;
  width: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.4.1/snap.svg-min.js"></script>
<div>
  <svg viewBox='0 0 500 500' id='svg1'>
  </svg>
</div>

(非常感谢 web-tiki 帮助我找出使用 snap.svg 的选项。)