QML 的 OpacityMask
用于通过遮罩元素的 透明度(Alpha 通道) 裁剪源元素的可见区域,适用于创建不规则形状的 UI 元素(如圆形头像、波浪形进度条)或复杂视觉效果。以下是详细使用技巧和常见场景示例:
1. 基本用法
import QtQuick 2.15
import QtQuick.Effects 1.15 // 引入效果模块Item {width: 300height: 300// 源元素(被裁剪的内容)Image {id: sourceImagesource: "image.jpg"visible: false // 隐藏源,仅用于遮罩输入}// 遮罩元素(定义可见区域)Rectangle {id: maskwidth: 200height: 200radius: 100 // 圆形遮罩visible: false // 隐藏遮罩元素}// 应用透明度遮罩OpacityMask {anchors.fill: parentsource: sourceImage // 源内容maskSource: mask // 遮罩形状}
}
关键属性:
source
:被遮罩的源元素(需隐藏,visible: false
)。maskSource
:定义裁剪形状的遮罩元素(透明度决定源元素的可见性)。invert
:设为true
时反转遮罩(显示原本透明的区域)。cached
:设为true
缓存遮罩结果,提升性能。
2. 常见应用场景
(1) 圆形头像
Image {id: avatarsource: "user.png"visible: false
}OpacityMask {width: 100height: 100source: avatarmaskSource: Rectangle { // 圆形遮罩width: 100height: 100radius: 50visible: false}
}
(2) 渐变遮罩(文字淡出)
Text {id: longTexttext: "This is a long text that needs to fade out at the bottom..."width: 200wrapMode: Text.Wrapvisible: false
}// 渐变遮罩(从上到下透明度从1到0)
Rectangle {id: gradientMaskwidth: 200height: 100visible: falsegradient: Gradient {GradientStop { position: 0.0; color: "white" }GradientStop { position: 1.0; color: "transparent" }}
}OpacityMask {source: longTextmaskSource: gradientMask
}
(3) 动态遮罩(可拖动区域)
Item {width: 400height: 400Image {id: backgroundsource: "map.jpg"visible: false}// 可拖动的圆形遮罩Rectangle {id: dynamicMaskwidth: 100height: 100radius: 50visible: falsex: mouseArea.mouseX - width/2y: mouseArea.mouseY - height/2}OpacityMask {source: backgroundmaskSource: dynamicMask}MouseArea {id: mouseAreaanchors.fill: parenthoverEnabled: true}
}
3. 进阶技巧
(1) 结合其他特效(模糊+遮罩)
OpacityMask {source: ShaderEffect { // 先模糊再遮罩property variant src: Image { source: "image.jpg" }layer.enabled: truelayer.effect: FastBlur { radius: 16 }}maskSource: Rectangle { // 星形遮罩width: 200; height: 200visible: falseCanvas { // 绘制星形路径anchors.fill: parentonPaint: {var ctx = getContext("2d");ctx.beginPath();// ... 绘制星形路径ctx.fillStyle = "white";ctx.fill();}}}
}
(2) 反转遮罩(显示外部区域)
OpacityMask {source: Image { source: "image.jpg"; visible: false }maskSource: Rectangle { // 中心透明的圆形width: 200; height: 200radius: 100color: "white"Rectangle { // 中心挖空anchors.centerIn: parentwidth: 50; height: 50radius: 25color: "transparent"}visible: false}invert: true // 反转遮罩,显示挖空的外部
}
(3) 动画遮罩(动态形状变化)
Rectangle {id: animatingMaskwidth: 200; height: 200visible: falseradius: width/2 * (0.5 + waveAnim.value) // 动态圆角NumberAnimation {id: waveAnimtarget: animatingMaskproperty: "radius"from: 0.1to: 0.9duration: 2000loops: Animation.Infiniterunning: true}
}OpacityMask {source: Image { source: "texture.jpg"; visible: false }maskSource: animatingMask
}
4. 性能优化
- 启用缓存:对静态遮罩设置
cached: true
。 - 简化遮罩元素:避免使用复杂
Canvas
或动态生成的遮罩。 - 降采样处理:缩小遮罩和源的纹理尺寸:
layer.textureSize: Qt.size(width/2, height/2)
5. 常见问题
(1) 遮罩不显示
- 检查
source
和maskSource
是否已正确隐藏(visible: false
)。 - 确认遮罩元素的 Alpha 通道非全透明(至少部分区域为可见)。
(2) 边缘锯齿
- 启用
layer.smooth: true
抗锯齿。 - 使用高分辨率遮罩或增加遮罩元素的
layer.textureSize
。
(3) 动态遮罩卡顿
- 减少遮罩元素的复杂度(如避免实时绘制
Canvas
)。 - 限制遮罩属性更新的频率(如节流动画帧率)。
总结
- 核心作用:通过遮罩的透明度通道控制源元素的可见区域。
- 关键属性:
source
(源内容)、maskSource
(遮罩形状)、invert
(反转遮罩)。 - 适用场景:不规则形状裁剪、动态区域显示、渐变过渡效果。
- 优化要点:简化遮罩结构、启用缓存、合理降采样。