我试图去寻找的外观和感觉是有一个纯色按钮,其上的文本就像“Hello World”,文本是完全透明的,背景通过按钮显示。如何将不透明度蒙版应用于QML项目?
换句话说,将文本作为按钮元素上的透明度蒙版。
我试图去寻找的外观和感觉是有一个纯色按钮,其上的文本就像“Hello World”,文本是完全透明的,背景通过按钮显示。如何将不透明度蒙版应用于QML项目?
换句话说,将文本作为按钮元素上的透明度蒙版。
我认为这是OpacityMask的用途。
下面的示例似乎说明了您正在寻找的效果。背景是坚实的红色Rectangle
。前景是坚实的蓝色Rectangle
。一个Text
对象,其中黑色文本位于蓝色前景的顶部。 OpacityMask
使用Text
作为背景的掩码,导致出现红色文本。
import QtQuick 2.7
import QtGraphicalEffects 1.0
Rectangle {
width: 500
height: 500
Rectangle {
id: background
anchors.fill: parent
Rectangle {
id: left
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
width: parent.width/2
color: "red"
ColorAnimation on color {
from: "red"
to: "green"
duration: 5000
loops: Animation.Infinite
}
}
Rectangle {
id: right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
width: parent.width/2
color: "red"
}
}
Rectangle {
id: foreground
anchors.fill: parent
color: "blue"
}
Text {
id: txt
anchors.centerIn: parent
text: "Test"
font.pointSize: 60
color: "black"
}
OpacityMask {
anchors.fill: txt
source: background
maskSource: txt
}
}
更新:增加了一个更复杂的背景下,以更好地说明了OpacityMask
真的计算过层切割。还添加了一个动画,以显示随时间变化的计算切分。
下面是做到这一点的一种方法:
// TB.qml
MouseArea {
width: txt.contentWidth + 20
height: txt.contentHeight + 10
property alias text: txt.text
property alias color: sh.color
ShaderEffect {
id: sh
anchors.fill: parent
property color color: "red"
property var source : ShaderEffectSource {
sourceRect: Qt.rect(0, 0, sh.width, sh.height)
sourceItem: Item {
width: sh.width
height: sh.height
Text {
id: txt
anchors.centerIn: parent
font.bold: true
font.pointSize: 30
text: "test"
}
}
}
fragmentShader:
"varying highp vec2 qt_TexCoord0;
uniform highp vec4 color;
uniform sampler2D source;
void main() {
gl_FragColor = color * (1.0 - texture2D(source, qt_TexCoord0).w);
}"
}
}
使用它:
TB {
text: "HELLO WORLD!!!"
color: "red"
onClicked: console.log("hi world")
}
结果:
按钮是红色的,文字是灰色的灰色背景,它会准确显示按钮下方的任何内容。
显然,该按钮是基本的,但这个例子不足以让你按照你的需要去实现某些东西。
这里的关键元素是自定义着色器,它是一个非常基本的着色器 - 它将每个片段着色并将掩码应用为alpha。显然,您可以使用ShaderEffectSource
将任何QML项目转换为纹理,并将ShaderEffectSource
替换为另一个sampler 2D
,并以任何您想要的方式混合使用这两种纹理,使用Alpha通道进行剪切,或者在使用灰度时使用任何RGB面具。而且不同于相当有限的OpacityMask
元素,它实际上会切入并显示任何在其下面的东西,因为它应该是。
不错的解决方案:) – Tim
你想要的是一个OpacityMask
可以倒置。 这在未来的Qt释放计划(5.7.1也许?),实际上你已经可以看看它:https://github.com/qt/qtgraphicaleffects/blob/5.7.1/src/effects/OpacityMask.qml
同时,你可以在一个名为MyOpacityMask.qml
文件或其他东西,并使用代码复制这种方式从Qt Quick的一个Button控制2:
Button {
id: button
text: "Yolo"
background.visible: false
contentItem.visible: false
contentItem.anchors.fill: button //can be avoided at the cost of creating another Item and ShaderEffectSource
MyOpacityMask {
anchors.fill: parent
invert: true
source: button.background
maskSource: button.contentItem
}
}
此之前已经在Opposite for OpacityMask
提到您可以实现,使用layer
附加属性如下不使用OpacityMask
。
你也没有任何限制,你可以使用任何QML项目,使用任何QtQuick.Controls
和风格它像往常一样:)
Image {
id: bk
source: "http://l7.alamy.com/zooms/7b6f221aadd44ffab6a87c234065b266/sheikh-lotfollah-mosque-at-naqhsh-e-jahan-square-in-isfahan-iran-interior-g07fw2.jpg"
}
Button {
id: button
anchors.centerIn: bk
width: 210; height: 72
visible: true
opacity: 0.0
layer.enabled: true
layer.smooth: true
onClicked: console.log("Clicked")
}
Rectangle {
id: _mask
anchors.fill: button
color: "transparent"
visible: true
Text {
font { pointSize: 20; bold: true }
anchors.centerIn: parent
text: "Hello World!"
}
layer.enabled: true
layer.samplerName: "maskSource"
layer.effect: ShaderEffect {
property variant source: button
fragmentShader: "
varying highp vec2 qt_TexCoord0;
uniform highp float qt_Opacity;
uniform lowp sampler2D source;
uniform lowp sampler2D maskSource;
void main(void) {
gl_FragColor = texture2D(source, qt_TexCoord0.st) * (1.0-texture2D(maskSource, qt_TexCoord0.st).a) * qt_Opacity;
}
"
}
}
这是一个完全自定义按钮控制?或者你使用Qt Quick Controls还是类似的? – peppe
Qt快速控制1或2? – GrecKo