CSS中是否有类似“背景转换”的内容?或通过某种方式来转换同一图像/视频/ iframe /等的不同区域。独立吗?

时间:2019-02-24 02:04:31

标签: css css-houdini

在CSS中,我们有transformfilter,还有backdrop-filter。但据我所知,我们没有backdrop-transform或类似的东西。

解释一下我的意思:backdrop-filter允许您过滤某些特定元素后面的,例如,您可以调整背景图像特定区域的色相通过在该区域上放置一个div,然后对其应用backdrop-filter: hue-rotate(90deg),如下所示:

backdrop-filter

因此backdrop-transformtransform属性的类似物。您可以transform部分背景图片,如下所示:

backdrop-transform

您还可以对单个嵌入式youtube视频(或任何其他iframe)执行类似的操作,例如:

backdrop-transform iframe

请注意,如果您尝试使用两个独立的iframe进行模拟,则需要以某种方式使其保持同步(关于滚动,视频播放等),如果iframe是跨域的。更不用说为要转换的每个细分嵌入新的iframe /视频的成本了。

也许我对Houdini的惊人承诺太醉了,但是我认为类似这样的事情真的很强大而且非常有用(至少对我而言!)。例如,您可以嵌入视频元素,但将其分解为四分之一,甚至使用CSS 将这些四分之一弄乱!使用4个不同的蒙版视频进行处理比较麻烦,并且尝试使它们完美地逐帧同步可能会很麻烦(特别是考虑到HTML5视频API的时间分辨率较低),并在服务器上剪切视频,似乎只是不必要的繁琐。

对于我的特定用例,我什至没有对视频的控制(它在跨域iframe中),因此CSS是实现我想做的唯一方法。 backdrop-filter将我带到了一半,但我还需要能够独立地对片段进行一些转换。


可能的解决方案#1:element()

CSS element(...)可以在url(..)函数可以使用的任何地方使用。它使您可以将页面上任何元素的完整快照(包括跨域内容)用作图像(令人兴奋)。 Here's a good into以及一些感兴趣的演示。唯一的问题是,Firefox目前仅支持它,但是它处于标准轨道上,因此将来很有可能会被其他浏览器支持。如果我们得到了element()函数的跨浏览器版本,则可以使用假设的backdrop-transform属性来实现所有可能的事情。我们将在该区域上放置一个div,然后获取它的实时快照,并根据需要对其进行转换。根据幕后如何实施element(),性能可能会成为问题。 Here is the chromium issue代表element()

1 个答案:

答案 0 :(得分:1)

您可以自己组合不同的功能来创建它。基本上,您使用两个元素,在其中一个元素中,删除要用另一个元素重新创建的零件,然后可以轻松地应用任何类型的变换。

这是一个具有 fake 透明性的基本概念:

.box {
  width:300px;
  height:200px;
  margin:50px;
  background:
    /*I hide a part of the image using a white gradient*/
    linear-gradient(#fff,#fff) 50px 50px/100px 100px,
    /*the main image*/
    url(https://picsum.photos/300/200?image=1069);
  background-repeat:no-repeat;
  position:relative;
}
.box:before {
  content:"";
  position:absolute;
  top:0;
  left:0;
  right:0;
  bottom:0;
  box-sizing:border-box;
  /*I get the same background*/
  background:inherit;
  /*I make the gradient with 0 size*/
  background-size:0 0,auto;
  /*I clip the background to only the content*/
  background-clip:content-box;
  padding:50px 150px 50px 50px;
  /*Apply what you want here*/
  transform:perspective(100px) rotateY(-20deg) skewX(10deg);
}
<div class="box">

</div>

主要技巧是使两者具有相同的背景,并依靠裁剪和渐变来模拟所需的效果。

除了剪裁,您还可以调整背景大小/位置:

.box {
  width:300px;
  height:200px;
  margin:50px;
  background:
    /*I hide a part of the image using a white gradient*/
    linear-gradient(#fff,#fff) 50px 50px/100px 100px,
    /*the main image*/
    url(https://picsum.photos/300/200?image=1069);
  background-repeat:no-repeat;
  position:relative;
}
.box:before {
  content:"";
  position:absolute;
  top:50px;
  left:50px;
  width:100px;
  height:100px;
  background:inherit;
  background-size:0 0,300px 200px;
  background-position:-50px -50px;
  /*Apply what you want here*/
  transform:perspective(100px) rotateY(-20deg) skewX(15deg);
  transform-origin:right;
}
<div class="box">

</div>


另一个想法是使用clip-path来获得完美的透明度,但是要找到不同的值可能会有些棘手:

.container {
  display:inline-block;
  position:relative;
  margin:50px;
}

.box {
  width:300px;
  height:200px;
  background:
    url(https://picsum.photos/300/200?image=1069);
  background-repeat:no-repeat;
clip-path: polygon(0% 0%, 0% 100%, 
  50px 100%, 50px 50px, 150px 50px, 150px 150px, 50px 150px, 50px 100%, 100% 100%, 100% 0%);
}
.container:before {
  content:"";
  position:absolute;
  top:50px;
  left:50px;
  width:100px;
  height:100px;
  box-sizing:border-box;
  background:
    url(https://picsum.photos/300/200?image=1069) -50px -50px/300px 200px no-repeat;

  /*Apply what you want here*/
  transform:perspective(100px) rotateY(-20deg) scale(0.8);
}

body {
  background:linear-gradient(to right,pink,red);
}
<div class="container">
<div class="box">

</div>
</div>

为了使其易于处理,您可以考虑使用CSS变量轻松调整要定位的区域:

.container {
  display:inline-block;
  position:relative;
  z-index:0;
  margin:5px;
  /*we set background here for inheritance*/
  background-image:var(--img);
  background-size:0 0; /*don't show here*/
  width:200px;
  height:200px;
}

.container:before,
.container:after{
  content:"";
  position:absolute;
  background-image:inherit;
}
.container:before {
  top:0;
  left:0;
  right:0;
  bottom:0;
  clip-path: polygon(0% 0%, 0% 100%, 
  var(--l) 100%, var(--l) var(--t), calc(var(--l) + var(--w)) var(--t), calc(var(--l) + var(--w)) calc(var(--t) + var(--h)), var(--l) calc(var(--t) + var(--h)), var(--l) 100%, 100% 100%, 100% 0%);
}
.container:after {
  top:var(--t);
  left:var(--l);
  width:var(--w);
  height:var(--h);
  background-position:calc(-1*var(--l)) calc(-1*var(--t));
  transform:var(--transform,none);
}

body {
  background:linear-gradient(to right,pink,red);
}
<div class="container"
  style="--img:url(https://picsum.photos/200/200?image=1069);
         --t:50px;--l:50px;
         --w:100px;--h:100px;
         --transform:perspective(100px) rotateY(-20deg) scale(0.8)">
</div>

<div class="container"
  style="--img:url(https://picsum.photos/200/200?image=1052);
         --t:10px;--l:50px;
         --w:100px;--h:150px;
         --transform:perspective(100px) rotate(-20deg) scale(0.8)">
</div>
<div class="container"
  style="--img:url(https://picsum.photos/200/200?image=1055);
         --t:5px;--l:5px;
         --w:80px;--h:80px;
         --transform:perspective(100px) skew(25deg) scale(0.8)">
</div>
<div class="container"
  style="--img:url(https://picsum.photos/200/200?image=1049);
         --t:100px;--l:100px;
         --w:100px;--h:100px;
         --transform:translate(50px,50px)">
</div>

如您所见,代码被简化为一个容器,您可以在其中轻松设置图像,区域的顶部/左侧位置及其宽度/高度,然后进行转换。