Acrylic 材质实现(下)

由于最新的SPlayerX基于Electron + Vue.js框架构建,在图标材质这一方面的实现完全可以使用HTML5和CSS3的一些特性进行处理。

 

SVG and SVG filter

SVG是一种使用XML定义的可伸缩矢量图形的格式,HTML5允许直接使用`<svg>...</svg>`标签在文档中插入SVG图像,现在很多图形软件都支持导出svg格式的文件。
因此最简单的想法是直接将Sketch中设计好的效果导出,插入在HTML文档中。

 直接使用sketch导出的svg图像

直接使用sketch导出的svg图像

测试中,生成的svg图形并不会对其后的背景图像做模糊处理。为进一步确认,在Sketch中单独做一个只添加了background-blur效果的图形并导出成svg,观察代码可以发现,其中并未有任何背景模糊处理的内容。

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs></defs>
    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <rect id="Rectangle" x="0" y="0" width="1011" height="993"></rect>
    </g>
</svg>

其实SVG本身提供了很多用于图像的滤镜即SVG filter,这些滤镜可以在`<filter>...</filter>`标签中定义,其中就有高斯模糊滤镜feGaussianBlur。但这一滤镜只能应用在给定的图像上,也就是说,若将其使用在图标上,被模糊的是图标本身而非图标后的背景;若将其使用在背景上,为了达到目标效果,则需要对使用了模糊效果的背景做一个图标轮廓的裁切,并在这之后再加一层完全相同的背景图。显然这种方式不适合用在背景为视频的播放器图标上。

 

backdrop-filter

在BOSS的建议下了解到了backdrop-filter这一CSS属性,它可以将图形特效应用到某一元素之后的区域,譬如对元素后的背景使用模糊滤镜,这就与Sketch中的background-blur非常类似了。同时,为了使效果能够显示,使用了backdrop-filter的元素或其背景必须具有一定的透明度。

backdrop-filter提供的图形特效滤镜有很多,譬如常见的亮度、对比度、饱和度等,甚至还支持引用在svg中定义的滤镜,以此支持更加丰富和灵活的特效。

这个属性的确是我们所需要的,为了确保它能够被正确地运用在视频图标上,还需要考虑两个问题:一、如何将该效果应用在不规则图形上?二、若使用该属性的元素处于播放状态的视频之前,滤镜效果是否能实时渲染?

 

clip-path

先来解决第一个问题。

 对svg元素使用backdrop-filter效果

对svg元素使用backdrop-filter效果

如图所示,若将`backdrop-filter:blur(20px);`用在<svg>元素的样式表中,backdrop-filter会对SVG图形整个画布背后的图像做模糊处理。但我们需要的是只对图标形状背后的画面使用滤镜,就必须裁掉这个元素上图标形状以外的部分。

这个时候就需要引入一个新的CSS属性:clip-path。它的作用正如其名,将路径定义的区域从元素中剪切出来,只显示区域内的内容,而区域外的内容被隐藏。最方便的一点是,这个被裁出的区域可以使用定义在svg中的路径,这样我们就可以从一个使用了背景模糊效果的div上将图标轮廓裁出。

 从使用了backdeop-filter模糊效果的div元素中裁出图标的路径形状

从使用了backdeop-filter模糊效果的div元素中裁出图标的路径形状

<style>
    .effect {
        ...
        background: rgba(255,255,255,.6);
        overflow: hidden;
        clip-path: url(#myClip);
        backdrop-filter: blur(30px);
    }
</style>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <clipPath id="myClip">
            <path d="..."></path>
        </clipPath>
    </defs>
</svg>

最后直接将背景图片换成video标签并插入视频,图标依旧能很好的对播放中的画面做模糊处理,这样第二个问题也就迎刃而解了。

到此为止,在浏览器网页中的Acrylic材质已经实现了大半,接下来还要测试这一方案在Electron框架中的应用效果。

 

Enable Experimental Web Platform Features

Electron框架使用了Chromium内核,在效果应用到实际项目之前,以上内容均在Chrome浏览器中进行测试。测试过程中曾一度遇到backdrop-filter属性失效的问题,单单升级Chrome仍无法解决。

再次仔细阅读MDN网站上列出的浏览器兼容性表格,在Chrome一栏下发现,尽管Chrome从版本47就开始支持backdrop-filter,但它仍然是一种实验特性,需要在Chrome的设置页面中打开“Enable Experimental Web Platform Features”选项才能看到最终效果。

 

在Electron中遇到的问题

尝试新特性的过程中总是会面临许多难题。在开启了实验特性的最新版Chrome中能够实现的效果,搬到内核版本还未升级到最新的Electron框架中,便无法正确显示。

尽管backdrop-filter能够对背景视频画面作出处理,但始终存在两个严重的问题:一、backdrop-filter会将应用之后的系统桌面背景也处理进去,在某些状态下能够穿透播放器应用看到桌面上的内容;二、clip-path对经过backdrop-filter处理后的内容无效。

目前猜测问题出现的原因正是Electron的内核版本问题,但是升级内核的成本非常大,在交付日期将近的Pre-alpha Version中已经来不及完成。团队也在不断尝试其他的替代方案,希望能够早日把Acrylic材质带到SPlayerX的用户面前。

如果正在阅读这篇文章的你,也对新设计的应用、新特性的实现有着自己独特的见解,SPlayerX射手影音团队诚挚地欢迎你的加入。

设计lilacvapor