JavaFX WebView 不在 Sencha Touch 应用程序中显示蒙版图像

JavaFX WebView doesn't display masked images in Sencha Touch app

我正在开发一个 JavaFX 应用程序,它使用 JavaFX WebView 浏览器来显示 Sencha Touch webapp。长话短说,Sencha Touch 应用程序最初是通过不同的浏览器访问的,但将来需要在设备 运行 JavaFX WebView 上访问它。这让事情变得有点复杂,但它通常是一个非常无缝的过渡。

我遇到的问题来自我们对 -webkit-mask-image CSS 属性 的使用。我们使用这个 属性 来快速为一些按钮和其他图像着色,以适应正在使用的任何着色方案。不幸的是,JavaFX WebView 似乎对如何处理 -webkit-mask-image 很困惑,所有这些图像都被扭曲了。

我做了功课,想出了this blog post,它描述了如何使用svg的foreignObject在其他浏览器中实现类似于-webkit-mask-image的效果。

根据那篇文章,我将以下 html 添加到我的 Sencha Touch 应用程序中,只是为了看看它在 JavaFX WebView 中的呈现方式:

<svg width="400px" height="300px">
  <defs>
    <mask id="mask" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse">
      <image width="400px" height="300px" xlink:href="foo.png"></image>
    </mask>
  </defs>
  <foreignObject width="400px" height="300px" style="mask: url(#mask);">
    <div style="display:inline-block;background-color:blue;width:400px;height:300px">
    </div>
  </foreignObject>
</svg>

遮罩图像 "foo.png" 是带有一些透明胶片的白色图像。我们在使用-webkit-mask-image的时候,mask图片是黑色的,但是我按照博客post的建议把它倒过来了。这实际上在 Firefox 中 非常好,我希望这是个好消息(因为之前我们的图像屏蔽在 Firefox 中不起作用)。 Firefox 显示漂亮的蓝色 div 并被 "foo.png" 掩盖。我漫长的噩梦结束了!

但事实并非如此。在 JavaFX WebView 中,它只显示一个蓝色框。为确保它可以访问 "foo.png",我将其作为常规旧 <img> 标签进行了尝试,并且显示了图像,所以这不是问题。

我确实在 OpenJDK 上找到了 this bug,这听起来与我的问题非常相似,尽管它仍然被列为 "open" 并且并没有让我走得太远。

此外,我发现 this question 其中作者正在尝试做类似的事情。这与我正在尝试做的事情之间的区别在于,在该解决方案中,他想显示图像和 mask/show 该图像的某些部分。我想要做的是有一个彩色的 div,被透明图像遮盖。这是一个例子:

.something-red {
  background-color: red;
  width: 400px;
  height: 365px;
  -webkit-mask-size: 400px;
  -webkit-mask-image: url(http://i.imgur.com/cWSCfGl.png);
}
<div class='something-red'>
</div>

我的临时解决方案是用(由我)预先着色的静态图像替换我们的图像遮罩。这看起来不像我们能够屏蔽图像时那样好,当然这也意味着我必须为我们想要使用的任何配色方案创建具有不同颜色的重复图像。

有没有办法在 JavaFX WebView 浏览器中实现类似 -webkit-mask-image 的功能?非常感谢您花时间阅读我的问题,希望我提供了足够的信息!

我们通常发现 JavaFX webview pretty outdated 并且有些未维护。

我们遇到了很多稳定性问题和崩溃,所以我不建议任何人将它用于生产应用程序,除非您的目标非常简单 HTML。

如果您的目标是 运行 在设备上并且您使用 Sencha 那么为什么需要 FX?

如果您在设备上需要 Java + HTML,请查看我们的 Cordova integration

我找到了一种在 JavaFX 浏览器中模拟 SVG 掩码的方法。我没有尝试强制支持 -webkit-mask-image,而是找到了一个浏览器 polyfill 来启用我在问题中引用的文章中描述的 SVG 屏蔽类型。

Modernizr polyfill collection 包含大量 javascript 库,旨在帮助添加对多个功能的跨浏览器支持。在尝试了其中一些之后,我决定使用 canvg,它将 SVG 定义转换为 canvas 元素,并在其上绘制对象。查看他的示例页面以查看它的实际效果 - 它允许您编辑 SVG 输入,因此您可以查看代码是否适合您。

因此,要实施此解决方案,您必须做四件事。首先,在您需要图像的位置创建一个 canvas 元素。请注意,无论图像大小如何,您都应该为其提供宽度和高度。

<canvas id='foo'></canvas>

接下来,获取对您 canvas 的引用。这将由 canvg 库使用。

var canvas = document.getElementById('foo');

第三,创建你的 svg。 canvg 支持几种不同的格式,但我只是将其作为 XML 字符串提供:

var svg =
        '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="100" viewBox="0 0 100 100">' +
            '<defs>'+
              '<mask id="Mask" maskUnits="userSpaceOnUse">'+
                '<image width="100" height="100" xlink:href="fooBar.png"></image>' +
              '</mask>'+
              '<rect id="rect" x="0" y="0" width="100" height="100" style="stroke-width:0px"/>'+
            '</defs>'+
            '<use xlink:href="#rect" mask="url(#Mask)" fill="red"/>'+
        '</svg>';

请注意,这与我在问题中引用的 SVG 遮罩文章非常相似,但并不完全相同。它定义了一个遮罩,然后是一个矩形,然后简单地遮罩矩形。

你做的最后一件事是像这样调用 canvg:

canvg(canvas, svg);

这应该可以在 JavaFX 浏览器中启用图像遮罩,但由于我专门询问了 Sencha Touch,所以我会提到我是如何将它添加到我的 Sencha Touch 应用程序中的。

在屏幕上呈现您的元素后,使用 Ext 的组件查询获取对它的引用:

var component = Ext.ComponentQuery.query('#itemId');

接下来,如上所述生成 canvas HTML 元素。然后,执行以下操作:

component.setHtml(yourCanvasHtmlElement);

现在,您的组件包含一个空的 canvas 元素。这是 canvg 将使用的元素。如上所述调用 canvg,您的 canvas 元素将更新。