QML 中的图像圆角 [英] Image rounded corners in QML

查看:124
本文介绍了QML 中的图像圆角的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

令我惊讶的是,Image 组件没有 radius 属性.我尝试通过将图像放入圆角 Rectangle 来模拟圆角,但它不会裁剪角.

矩形{anchors.right: rectContentBg.leftanchors.top: rectContentBg.top锚点.边距:8半径:8宽度:64身高:64图像 {id: imgAuthor不透明度:1平滑:假anchors.fill:父级来源:qrc:/res/sample_avatar.jpg"}}

如何正确创建带有圆角的图像?

解决方案

由于 QtGraphicalEffects 模块,Qt 5 中存在一个内置的官方解决方案,我很惊讶地发现没有人提供过如此简单的解决方案.

在其他效果中,OpacityMask 是用于此目的的类型.这个想法是用一个具有正确设置的 radiusRectangle 来屏蔽源 Image.这是使用

此解决方案的实现细节与其他

与第一种方法类似,添加了 roundedadapt 属性以控制上述效果的视觉外观.

To my surprise, the Image component has no radius property. I tried emulating the rounded corners by putting the image in a rounded Rectangle, but it does not clip the corners.

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"
    }
}

How can I create an image with rounded corners properly?

解决方案

A built-in official solution exists as of Qt 5 thanks to the QtGraphicalEffects module and I'm quite surprised to find out that no one provided such simple solution.

Among the other effects OpacityMask is the type to be exploited for this purpose. The idea is to mask the source Image with a Rectangle that has a correctly set radius. Here goes the simplest example using 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)
            }
        }
    }
}

This minimum code produces a nice result for square images but it also takes in account non-square images via the adapt variable. By setting the flag to false the produced mask will always be a circle, regardless of the image size. That is possible due to the usage of an external Item which fills the source and allows the real mask (the inner Rectangle) to be sized at please. You can obviously get rid of the external Item, if you simply aim to a mask that fills the source, regardless of the its aspect ratio.

Here is a cute cat image with a square format (left), a non-square format with adapt: true (center) and finally a non-square format and adapt: false (right):

The implementation details of this solution are very similar to those of the shader-based answer in the other nice answer (cfr. the QML source code for OpacityMask that can be found here - SourceProxy simply returns a well-formed ShaderEffectSource to feed the effect).

If you don't want to depend on the QtGraphicalEffects module (well, on the presence of OpacityMask.qml actually), you can reimplement the effect with shaders. Apart from the already provided solution another approach is to use step, smoothstep and fwidth functions. Here is the code:

import 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;
        }"
    }
}

Similarly to the first approach, rounded and adapt properties are added to control the visual appearance of the effect as discussed above.

这篇关于QML 中的图像圆角的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆