qml写一个水波纹
时间: 2023-07-01 22:10:46 浏览: 174
可以使用`ShaderEffect`和`Canvas`实现水波纹效果。
首先,需要定义一个`ShaderEffect`,用于渲染水波纹。以下是一个简单的水波纹着色器代码:
```qml
ShaderEffect {
property float amplitude: 0.02
property float frequency: 30.0
property float speed: 0.3
property vec2 center: vec2(0.5, 0.5)
fragmentShader: "
uniform lowp float qt_Opacity;
uniform highp float amplitude;
uniform highp float frequency;
uniform highp float speed;
uniform highp vec2 center;
uniform highp vec2 resolution;
uniform highp sampler2D source;
void main() {
highp vec2 texCoord = gl_FragCoord.xy / resolution;
highp vec4 color = texture2D(source, texCoord);
highp float dist = length(texCoord - center);
highp float offset = amplitude * sin(dist * frequency + qt_TexCoord0.y * speed);
gl_FragColor = color * vec4(1.0, 1.0, 1.0, 1.0 - offset);
}
"
}
```
着色器中定义了一些属性,比如`amplitude`表示水波的振幅,`frequency`表示水波的频率等。在`main`函数中,使用`sin`函数计算出当前像素点的偏移量,并将其应用到像素颜色上。
接下来,我们需要在`Canvas`中绘制一个矩形,并将水波纹效果应用到这个矩形上:
```qml
Canvas {
id: canvas
anchors.fill: parent
onPaint: {
var ctx = getContext("2d");
// 绘制一个矩形
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, width, height);
// 应用水波纹效果
shaderEffect.amplitude = 0.02;
shaderEffect.frequency = 30.0;
shaderEffect.speed = 0.3;
shaderEffect.center = Qt.point(width / 2, height / 2);
shaderEffect.source = canvas;
ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = shaderEffect;
ctx.fillRect(0, 0, width, height);
}
}
```
在`onPaint`事件中,首先使用`fillRect`方法绘制一个蓝色矩形。然后,将水波纹着色器应用到整个画布上,使用`fillStyle`属性设置为着色器对象即可。
最后,我们需要添加一个定时器来不断更新水波纹的效果,让其看起来像是在不停地波动:
```qml
Timer {
interval: 16
running: true
repeat: true
onTriggered: {
shaderEffect.center = Qt.point(canvas.width / 2, canvas.height / 2);
canvas.requestPaint();
}
}
```
在定时器的`onTriggered`事件中,更新水波纹的中心位置,并请求重新绘制画布。这样,每隔一段时间就会更新一次水波纹的效果,使其看起来像是在动态波动。
以上就是使用`ShaderEffect`和`Canvas`实现水波纹效果的方法。完整代码如下:
```qml
import QtQuick 2.15
import QtQuick.Controls 2.15
Page {
title: "Water Ripple"
ShaderEffect {
id: shaderEffect
property float amplitude: 0.02
property float frequency: 30.0
property float speed: 0.3
property vec2 center: vec2(0.5, 0.5)
fragmentShader: "
uniform lowp float qt_Opacity;
uniform highp float amplitude;
uniform highp float frequency;
uniform highp float speed;
uniform highp vec2 center;
uniform highp vec2 resolution;
uniform highp sampler2D source;
void main() {
highp vec2 texCoord = gl_FragCoord.xy / resolution;
highp vec4 color = texture2D(source, texCoord);
highp float dist = length(texCoord - center);
highp float offset = amplitude * sin(dist * frequency + qt_TexCoord0.y * speed);
gl_FragColor = color * vec4(1.0, 1.0, 1.0, 1.0 - offset);
}
"
}
Canvas {
id: canvas
anchors.fill: parent
onPaint: {
var ctx = getContext("2d");
// 绘制一个矩形
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, width, height);
// 应用水波纹效果
shaderEffect.amplitude = 0.02;
shaderEffect.frequency = 30.0;
shaderEffect.speed = 0.3;
shaderEffect.center = Qt.point(width / 2, height / 2);
shaderEffect.source = canvas;
ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = shaderEffect;
ctx.fillRect(0, 0, width, height);
}
}
Timer {
interval: 16
running: true
repeat: true
onTriggered: {
shaderEffect.center = Qt.point(canvas.width / 2, canvas.height / 2);
canvas.requestPaint();
}
}
}
```
阅读全文