使用QtQuick,是否可以采用RGB定义的现有颜色并使其去饱和而无需诉诸Javascript?
function desaturate(colorString)
{
let c = Qt.darker(colorString, 1.0);
return Qt.hsla(c.hslHue, 0.0, c.hslLightness, c.a);
}
看到QtQuick是如何在Javascript引擎上运行的,我想说,如果不借助Javascript,在QML中不可能做任何事情。
为了调整饱和度,你必须将RGB转换为HSL颜色,然后再转换回RGB。QML有Qt.hsla()
为后者,但上次我检查它没有提供从RGB到HSL的转换,所以我最终使用这个:
function rgbToHsl(r, g, b) {
r /= 255
g /= 255
b /= 255
var max = Math.max(r, g, b), min = Math.min(r, g, b)
var h, s, l = (max + min) / 2
if (max == min) {
h = s = 0
} else {
var d = max - min
s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0)
break
case g:
h = (b - r) / d + 2
break
case b:
h = (r - g) / d + 4
break
}
h /= 6;
}
return {"h":h, "s":s, "l":l};
}
所以你基本上是:
var ic = yourRGBColor.toString()
var r = parseInt(ic.substr(1, 2), 16)
var g = parseInt(ic.substr(3, 2), 16)
var b = parseInt(ic.substr(5, 2), 16)
var hsl = rgbToHsl(r, g, b)
hsl.s *= .5 // desaturate 50%
yourRGBColor = Qt.hsla(hsl.h, hsl.s, hsl.l, 1)
根据颜色模型修改颜色的hsvSaturation
或hslSaturation
属性。
每秒逐渐使一个蓝色矩形去饱和的Test.qml
示例(与qmlscene Test.qml
一起运行):
import QtQuick 2.7
Item {
width: 100
height: 100
Rectangle {
anchors.fill: parent
objectName: "precious"
color: "#0000FF"
Timer {
running: true
repeat: true
onTriggered: parent.color.hslSaturation *= 0.8;
}
}
}
隐藏在大量文本中,在两个代码块之间,这些属性实际上以彩色QML基本类型记录。它们似乎对应于c++中颜色组件属性的qreal
版本(名称以...F()
结尾)。
正如@dtech所说,onTriggered:...
在法律上已经是一行JavaScript了。如果你需要,你也可以在c++中找到元素的属性,并在那里修改属性。
示例main.cpp
,显示上面的Test.qml
,从一个已经非常不饱和的(纯c++)蓝色矩形开始,然后逐渐去饱和它(仍然在QML/JavaScript中完成):
#include <QGuiApplication>
#include <QQuickView>
#include <QQuickItem>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView view(QUrl(QLatin1String("qrc:/Test.qml")));
view.show();
if ( QObject * rectangle = view.rootObject()->findChild<QObject*>("precious") )
{
qreal h, s, l, a;
rectangle->property("color").value<QColor>().getHslF( &h, &s, &l, &a );
s *= 0.2;
rectangle->setProperty( "color", QVariant::fromValue(QColor::fromHsvF( h, s, l, a )) );
}
return app.exec();
}
现在您可以从Test.qml
中删除明显的JavaScript行。
注意,我演示了一个非常粗糙的彩色动画。有一个特殊的ColorAnimation
工具可以做得更好。