我正在开发一个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
时,掩码图像是黑色的,但我根据博客文章的建议将其颠倒了。这实际上在Firefox中工作得非常好,我希望这是个好消息(因为以前我们的图像屏蔽在Firefox中不起作用)。 Firefox显示了一个漂亮的蓝色div,被“foo.png”掩盖了。我的长噩梦结束了!
除非不是。在JavaFX WebView中,它只显示一个蓝色框。为了确保它可以访问“foo.png”,我尝试将其作为常规的旧<img>
标记,并显示图像,这不是问题。
我确实在OpenJDK上找到了this bug,这听起来和我的问题非常相似,虽然它仍然被列为“开放”并且没有引导我走得太远。
另外,我发现this question作者试图做类似的事情。我和我想要做的事情之间的区别在于,在该解决方案中,他想要在图像中显示并掩盖/显示该图像的某些部分。我要做的是有一个彩色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
等功能?非常感谢您花时间阅读我的问题,希望我已经提供了足够的信息!
答案 0 :(得分:1)
我找到了一种在JavaFX浏览器中模拟SVG屏蔽的方法。我没有尝试强制支持-webkit-mask-image
,而是找到了一个浏览器polyfill来启用我在问题中引用的文章中描述的SVG屏蔽类型。
Modernizr polyfill collection包含大量的javascript库,旨在帮助添加对多个功能的跨浏览器支持。在尝试了其中的一些之后,我选择了canvg,它将SVG定义转换为canvas元素,并在其上绘制对象。看看他的示例页面,看看它是否正常运行 - 它允许您编辑SVG输入,这样您就可以看到代码是否适合您。
因此,要实现此解决方案,您必须做四件事。首先,在需要图像的地方创建一个canvas元素。请注意,无论图像大小如何,都应该为它提供宽度和高度。
<canvas id='foo'></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');
接下来,如上所述生成画布HTML元素。然后,执行以下操作:
component.setHtml(yourCanvasHtmlElement);
现在,您的组件包含一个空的canvas元素。这是canvg将使用的元素。如上所述调用canvg,canvas元素将更新。
答案 1 :(得分:0)
我们通常发现JavaFX webview是pretty outdated并且有点不受维护。
我们遇到了很多稳定性问题并且崩溃了所以我不建议任何人将它用于生产应用程序,除非您的目标是非常简单的HTML。
如果您的目标是在设备上运行并且您使用Sencha,那么您为什么需要FX?
如果您需要在设备上使用Java + HTML,请查看我们的Cordova integration。