问题
根据 QML Item 类型 clip 属性的文档:
https://doc.qt.io/qt-5/qml-qtquick-item.html#clip-prop
https://doc.qt.io/qt-5/qtquick-visualcanvas-scenegraph-renderer.html#clipping
可以看到,他描述的是根据 Item 的矩形边框剪切,没有对圆角或其他异形进行处理。
实测默认效果:
Rectangle{
anchors.centerIn: parent
radius: 20
clip: true
width: 200
height: 200
color: "green"
Rectangle{
width: 100
height: 100
color: "red"
}
}
运行上面的代码可以看到外层的 radius 并不会对 clip 效果产生影响,因为里面的色块还是完整的方形。
效果图:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtGraphicalEffects 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("龚建波 1992")
Rectangle{
anchors.centerIn: parent
width: 200
height: 200
color: "green"
layer.enabled: true
layer.effect: OpacityMask{
maskSource: Rectangle{
width: 200
height: 200
radius: 20
}
}
Rectangle{
width: 100
height: 100
color: "red"
}
}
}
或者这样写:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtGraphicalEffects 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("龚建波 1992")
Rectangle{
id: rect
visible: false
width: 200
height: 200
color: "green"
Rectangle{
width: 100
height: 100
color: "red"
}
}
OpacityMask{
anchors.centerIn: parent
width: 200
height: 200
source: rect
maskSource: Rectangle{
width: 200
height: 200
radius: 20
}
}
}
2.使用 ShaderEffect 写着色器
OpacityMask 也是用 ShaderEffect 实现的,自己写着色器要注意的是对不同着色器版本进行兼容处理,我这里只写了个简单的没处理版本问题:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtGraphicalEffects 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("龚建波 1992")
color: "gray"
Rectangle{
id: rect
visible: false
radius: 20
width: 200
height: 200
color: "green"
Rectangle{
width: 100
height: 100
color: "red"
}
}
ShaderEffect{
anchors.centerIn: parent
width: 200
height: 200
property var source: ShaderEffectSource{
sourceItem: rect
}
property var mask: ShaderEffectSource{
sourceItem: Rectangle{
width: 200
height: 200
radius: 20
}
}
vertexShader: "
uniform highp mat4 qt_Matrix;
attribute highp vec4 qt_Vertex;
attribute highp vec2 qt_MultiTexCoord0;
varying highp vec2 coord;
void main() {
coord = qt_MultiTexCoord0;
gl_Position = qt_Matrix * qt_Vertex;
}"
fragmentShader: "
varying highp vec2 coord;
uniform lowp float qt_Opacity;
uniform sampler2D source;
uniform sampler2D mask;
void main() {
gl_FragColor = texture2D(source, coord) * texture2D(mask, coord) * qt_Opacity;
}"
}
}
3.其他
文档提到的 QSGNode 太麻烦,忽略。
拓展机智你可能已经发现了,遮罩不仅能实现四个圆角的 clip,也能实现自己想要的圆角效果(QML 默认四个圆角是统一设置的):
import QtQuick 2.12
import QtQuick.Window 2.12
import QtGraphicalEffects 1.0
Window {
width: 640
height: 480
visible: true
title: qsTr("龚建波 1992")
Rectangle{
anchors.centerIn: parent
width: 200
height: 200
color: "green"
layer.enabled: true
layer.effect: OpacityMask{
maskSource: Rectangle{
width: 200
height: 200
radius: 50
//左侧
Rectangle{
width: 60
height: 200
}
//右上角
Rectangle{
width: 60
height: 60
radius: 20
anchors.right: parent.right
}
}
}
}
}