QML中的图像圆角

问题描述 投票:31回答:7

令我惊讶的是,Image组件没有radius属性。我尝试通过将图像放在圆形的Rectangle中来模拟圆角,但它不会剪切角落。

Rectangle {
    anchors.right: rectContentBg.left
    anchors.top: rectContentBg.top
    anchors.margins: 8

    radius: 8

    width: 64
    height: 64

    Image {
        id: imgAuthor

        opacity: 1
        smooth: false

        anchors.fill: parent

        source: "qrc:/res/sample_avatar.jpg"
    }
}

如何正确创建圆角图像?

qml qt5 qtquick2
7个回答
40
投票

由于QtGraphicalEffects模块,在Qt 5中存在内置的官方解决方案,我很惊讶地发现没有人提供这样简单的解决方案。

在其他影响中,OpacityMask是为此目的而被利用的类型。我的想法是用Image掩盖源Rectangleradius具有正确设置的layering。这是使用Image { id: img property bool rounded: true property bool adapt: true layer.enabled: rounded layer.effect: OpacityMask { maskSource: Item { width: img.width height: img.height Rectangle { anchors.centerIn: parent width: img.adapt ? img.width : Math.min(img.width, img.height) height: img.adapt ? img.height : width radius: Math.min(width, height) } } } } 的最简单的例子:

adapt

这个最小代码为方形图像产生了很好的结果,但它也通过false变量考虑了非方形图像。通过将标志设置为Item,无论图像大小如何,生成的蒙版始终为圆形。这是可能的,因为使用外部Rectangle填充源,并允许真正的掩码(内部Item)在适当的大小。你可以显然摆脱外部adapt: true,如果你只是瞄准填充源的面具,无论其纵横比。

这是一个可爱的猫图像,方形格式(左),非方格式与adapt: false(中心),最后是非方格式和enter image description here(右):

nice answer

这个解决方案的实现细节非常类似于其他OpacityMask中基于着色器的答案(cfr。可以找到here的qML源代码SourceProxy - ShaderEffectSource只返回一个格式良好的QtGraphicalEffects来提供效果)。

如果您不想依赖于OpacityMask.qml模块(实际上存在step),您可以使用着色器重新实现效果。除了已经提供的解决方案,另一种方法是使用smoothstepfwidthimport QtQuick 2.5 Image { id: image property bool rounded: true property bool adapt: true layer.enabled: rounded layer.effect: ShaderEffect { property real adjustX: image.adapt ? Math.max(width / height, 1) : 1 property real adjustY: image.adapt ? Math.max(1 / (width / height), 1) : 1 fragmentShader: " #ifdef GL_ES precision lowp float; #endif // GL_ES varying highp vec2 qt_TexCoord0; uniform highp float qt_Opacity; uniform lowp sampler2D source; uniform lowp float adjustX; uniform lowp float adjustY; void main(void) { lowp float x, y; x = (qt_TexCoord0.x - 0.5) * adjustX; y = (qt_TexCoord0.y - 0.5) * adjustY; float delta = adjustX != 1.0 ? fwidth(y) / 2.0 : fwidth(x) / 2.0; gl_FragColor = texture2D(source, qt_TexCoord0).rgba * step(x * x + y * y, 0.25) * smoothstep((x * x + y * y) , 0.25 + delta, 0.25) * qt_Opacity; }" } } 函数。这是代码:

enter image description here

rounded

与第一种方法类似,添加adaptImage属性以控制效果的视觉外观,如上所述。


7
投票

当你的背景是纯色或者你永远不会移动图像时,快速制作圆角的方法是将你的BorderImage与另一个(或者用http://blog.qt.digia.com/blog/2011/05/03/qml-shadereffectitem-on-qgraphicsview/)重叠,只能画出角落。

如果这不是一个选项,但您使用的是OpenGL,那么另一种方法是通过像素着色器将遮罩应用于图像。有关在Qt 4之上工作的插件,请参阅QDeclarativeImageProvider

最后,还可以编写一个Rectangle { width: 200 height: 200 color: "transparent" //this Rectangle is needed to keep the source image's fillMode Rectangle { id: imageSource anchors.fill: parent Image { anchors.fill: parent source: "your_image_file_path" fillMode: Image.PreserveAspectCrop } visible: false layer.enabled: true } Rectangle { id: maskLayer anchors.fill: parent radius: parent.width / 2 color: "red" border.color: "black" layer.enabled: true layer.samplerName: "maskSource" layer.effect: ShaderEffect { property var colorSource: imageSource fragmentShader: " uniform lowp sampler2D colorSource; uniform lowp sampler2D maskSource; uniform lowp float qt_Opacity; varying highp vec2 qt_TexCoord0; void main() { gl_FragColor = texture2D(colorSource, qt_TexCoord0) * texture2D(maskSource, qt_TexCoord0).a * qt_Opacity; } " } } // only draw border line Rectangle { anchors.fill: parent radius: parent.width / 2 border.color: "black" border.width: 2 color: "transparent" } } 来预处理您的图像,使角落变圆。



5
投票

QML目前仅支持矩形剪切,但您可能需要查看qt-components项目中的DeclarativeMaskedImage:

Image{ id:img } Rectangle { // rounded corners for img anchors.fill: img color: "transparent" border.color: "blue" // color of background border.width: 4 radius: 4 }


5
投票

如果您有单色背景,则可以使用顶部圆角矩形的边框绘制。

Image {
    id: imgAuthor

    width: 64
    height: 64

    source: "qrc:/res/sample_avatar.jpg"

    visible: false // this is needed or the corners of the image will be visible underneath the opacity mask
}

OpacityMask {
    anchors.fill: imgAuthor
    source: imgAuthor
    maskSource: Rectangle {
        width: imgAuthor.width
        height: imgAuthor.height
        radius: 8
        visible: false // this also needs to be invisible or it will cover up the image
    }
}

4
投票

我知道我参加派对有点晚了,但是我通过谷歌搜索来到这里,所以我想我会帮助后代:) QtGraphicalEffects OpacityMask应该更简单地做到这一点(我有层效应方法的问题)

the one from @fury

2
投票

虽然接受的答案和OpacityMask对我来说都同样有效(Qt 5.9.3),但是当应用于光栅图像(没有SVG的那些)时,它们都在角落中留下了一些像差。在所有情况下最适合我的是将Rectangle { id: root; anchors.right: rectContentBg.left anchors.top: rectContentBg.top anchors.margins: 8 radius: 8 width: 64 height: 64 // apply rounded corners mask layer.enabled: true layer.effect: OpacityMask { maskSource: Rectangle { x: root.x; y: root.y width: root.width height: root.height radius: root.radius } } Image { id: imgAuthor opacity: 1 smooth: false anchors.fill: parent source: "qrc:/res/sample_avatar.jpg" } } 应用于周围物品,例如喜欢原帖中的矩形。

qazxswpoi
© www.soinside.com 2019 - 2024. All rights reserved.