我想要的外观和感觉是拥有一个纯色按钮,文字就像" Hello World"文本完全透明,背景通过按钮显示。
换句话说,将文本作为按钮元素上的透明蒙版。
答案 0 :(得分:5)
这是一种方法:
<a href="javascript:;" onclick="ReplaceImage();">Load More</a>
使用它:
// 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);
}"
}
}
结果:
按钮为红色,灰色背景中的文字为灰色,并且会准确显示按钮下方的任何内容。
显然,这个按钮很简陋,但是这个例子足以让你根据自己的需要去实现一些东西。
这里的关键元素是自定义着色器,它是一个非常基本的着色器 - 它将每个片段着色并将蒙版应用为alpha。显然,您可以使用 TB {
text: "HELLO WORLD!!!"
color: "red"
onClicked: console.log("hi world")
}
将任何QML项目转换为纹理,并将ShaderEffectSource
替换为另一个ShaderEffectSource
并以您想要的任何方式混合两个纹理,使用Alpha通道剪切,如果您使用的是灰度蒙版,则为任何RGB。与相当有限的sampler 2D
元素不同,这实际上会切断并显示其下方的任何内容。
答案 1 :(得分:3)
你想要的是可以倒置的OpacityMask
。
这是计划在未来的Qt版本中发布的(可能是5.7.1?),事实上你已经可以看一下它:https://github.com/qt/qtgraphicaleffects/blob/5.7.1/src/effects/OpacityMask.qml
与此同时,您可以将代码复制到名为MyOpacityMask.qml
或其他名称的文件中,并以Qt Quick Controls 2中的Button使用它:
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
}
}
中提及过
答案 2 :(得分:1)
我认为这是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
实际上是计算切入层。还添加了一个动画,通过随时间变化显示计算出的剪切。
答案 3 :(得分:1)
您可以使用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;
}
"
}
}