QML中的图像圆角
令我惊讶的是,QML中的图像圆角,qml,qt5,qtquick2,Qml,Qt5,Qtquick2,令我惊讶的是,Image组件没有radius属性。我试图通过将图像放在圆角的矩形中来模拟圆角,但它不会剪裁圆角 Rectangle { anchors.right: rectContentBg.left anchors.top: rectContentBg.top anchors.margins: 8 radius: 8 width: 64 height: 64 Image { id: imgAuthor
Image
组件没有radius
属性。我试图通过将图像放在圆角的矩形中来模拟圆角,但它不会剪裁圆角
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目前仅支持矩形剪裁,但您可能希望查看qt components项目中的DeclarativeSkedimage:
当您的背景为纯色或从不移动图像时,制作圆角的一种快速方法是将您的图像
与另一个仅绘制角的图像(或a)重叠
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"
}
}
如果这不是一个选项,但您使用的是OpenGL,那么另一种方法是通过像素着色器对图像应用遮罩。有关在Qt4上工作的插件,请参阅
最后,还可以编写一个预处理图像以使角变圆的程序。如果您有单色背景,您可以在顶部绘制圆角矩形的边框
Image{
id:img
}
Rectangle { // rounded corners for img
anchors.fill: img
color: "transparent"
border.color: "blue" // color of background
border.width: 4
radius: 4
}
这个代码会帮助你
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"
}
}
得益于QtGraphicalEffects
模块,自qt5起就有了一个内置的官方解决方案,我很惊讶地发现没有人提供如此简单的解决方案
在其他影响中,OpacityMask
是用于此目的的类型。这个想法是用一个正确设置了半径的矩形遮罩源图像。下面是最简单的示例,使用:
这个最小代码为正方形图像生成了一个很好的结果,但是
它还通过adapt
变量考虑非方形图像。通过将标志设置为false
生成的遮罩将始终是一个圆形,而不管图像大小如何。这是可能的,因为使用了一个外部项
,它填充了源代码,并允许根据需要调整真实掩码(内部矩形
)的大小。若您只是简单地瞄准一个填充源的掩码,而不管它的纵横比如何,显然可以去掉外部的项
这是一张可爱的猫图片,它是方形格式(左),非方形格式(adapt:true
(center),最后是非方形格式和adapt:false
(右):
此解决方案的实现细节与另一个解决方案中基于着色器的答案非常相似(cfr.OpacityMask
的QML源代码可以找到-SourceProxy
只返回格式良好的ShaderEffectSource
以提供效果)
如果您不想依赖QtGraphicalEffects
模块(实际上,取决于OpacityMask.qml
的存在),可以使用着色器重新实现效果。除了已经提供的解决方案外,另一种方法是使用和功能。代码如下:
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;
}"
}
}
与第一种方法类似,添加了四舍五入
和自适应
属性,以控制上述效果的视觉外观。我知道我参加派对有点晚,但我是通过谷歌搜索来的,所以我想我会帮助后代:)QtGraphicalEffects OpacityMask应该更简单一些(我对图层效果方法有疑问)
虽然这两个被接受的答案对我来说同样有效(Qt 5.9.3),但当应用于光栅图像时,它们都在角落留下了一些像差(没有SVG)。在所有情况下,对我最有效的是将OpacityMask
应用于周围的项目,例如,像原始帖子中的矩形
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"
}
}
他们真的应该做到这一点,而不是他们现在正在做的那些花哨的3D东西:/回答得好,谢谢!我想指出的是,在你的第一种方法中,如果你在一个项目中使用一个矩形,你不需要声明该项目,你可以直接使用矩形,因为矩形继承了该项目。你为什么要包装矩形
在项目
?@Phrogz中,效果是源代码,即使我将自适应
设置为真
我也无法在第一个系列的第三张图片中得到结果。如果你有一张与第一张图片类似的方形图片,那么外部的项目
根本没有用处。要添加吗,如果你的目标是移动设备,你应该设置它layer.textureSize,这样你就可以保持完整的分辨率,只要半径大于border.Width,它就可以工作。虽然这个答案可行,但我偶尔会看到一些渲染人工制品,这意味着它本身看起来不太专业。幸运的是,这些小故障只是垂直线(在win7上),所以两个放置良好的矩形可以清理它。
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"
}
}