diff --git a/example/qml/window/MainWindow.qml b/example/qml/window/MainWindow.qml index cbe46ce1..5046a084 100644 --- a/example/qml/window/MainWindow.qml +++ b/example/qml/window/MainWindow.qml @@ -208,60 +208,12 @@ CustomWindow { } } - //todo CircularReveal{ + id:reveal + target:window.contentItem anchors.fill: parent - } - - Image{ - id:img_cache - visible: false - anchors.fill: parent - } - - Canvas{ - id:canvas - anchors.fill: parent - property int centerX: canvas.width / 2 - property int centerY: canvas.height / 2 - property real radius: 0 - property int maxRadius: 0 - property url imageUrl - Behavior on radius{ - id:anim_radius - NumberAnimation { - target: canvas - property: "radius" - duration: 333 - easing.type: Easing.OutCubic - } - } - onRadiusChanged: { - canvas.requestPaint() - } - onPaint: { - var ctx = canvas.getContext("2d"); - ctx.setTransform(1, 0, 0, 1, 0, 0); - ctx.clearRect(0, 0, canvasSize.width, canvasSize.height); - ctx.save() - if(img_cache.source.toString().length!==0){ - try{ - ctx.drawImage(img_cache.source, 0, 0, canvasSize.width, canvasSize.height, 0, 0, canvasSize.width, canvasSize.height) - }catch(e){ - img_cache.source = "" - } - } - clearArc(ctx, centerX, centerY, radius) - canvas.unloadImage(img_cache.source) - ctx.restore() - } - function clearArc(ctx,x, y, radius, startAngle, endAngle) { - ctx.beginPath() - ctx.globalCompositeOperation = 'destination-out' - ctx.fillStyle = 'black' - ctx.arc(x, y, radius, 0, 2*Math.PI); - ctx.fill(); - ctx.closePath(); + onImageChanged: { + changeDark() } } @@ -270,13 +222,6 @@ CustomWindow { } function handleDarkChanged(button){ - var changeDark = function(){ - if(FluTheme.dark){ - FluTheme.darkMode = FluDarkMode.Light - }else{ - FluTheme.darkMode = FluDarkMode.Dark - } - } if(FluTools.isMacos()){ changeDark() }else{ @@ -284,18 +229,16 @@ CustomWindow { var pos = button.mapToItem(target,0,0) var mouseX = pos.x var mouseY = pos.y - canvas.maxRadius = Math.max(distance(mouseX,mouseY,0,0),distance(mouseX,mouseY,target.width,0),distance(mouseX,mouseY,0,target.height),distance(mouseX,mouseY,target.width,target.height)) - target.grabToImage(function(result) { - img_cache.source = result.url - canvas.requestPaint() - changeDark() - canvas.centerX = mouseX - canvas.centerY = mouseY - anim_radius.enabled = false - canvas.radius = 0 - anim_radius.enabled = true - canvas.radius = canvas.maxRadius - },canvas.canvasSize) + var radius = Math.max(distance(mouseX,mouseY,0,0),distance(mouseX,mouseY,target.width,0),distance(mouseX,mouseY,0,target.height),distance(mouseX,mouseY,target.width,target.height)) + reveal.start(reveal.width*Screen.devicePixelRatio,reveal.height*Screen.devicePixelRatio,Qt.point(mouseX,mouseY),radius) + } + } + + function changeDark(){ + if(FluTheme.dark){ + FluTheme.darkMode = FluDarkMode.Light + }else{ + FluTheme.darkMode = FluDarkMode.Dark } } diff --git a/example/src/component/CircularReveal.cpp b/example/src/component/CircularReveal.cpp index 7fd02327..ec25eee1 100644 --- a/example/src/component/CircularReveal.cpp +++ b/example/src/component/CircularReveal.cpp @@ -1,6 +1,47 @@ #include "CircularReveal.h" +#include +#include +#include -CircularReveal::CircularReveal() +CircularReveal::CircularReveal(QQuickItem* parent) : QQuickPaintedItem(parent) { + _anim = new QPropertyAnimation(this, "radius", this); + _anim->setDuration(333); + _anim->setEasingCurve(QEasingCurve::OutCubic); + connect(_anim, &QPropertyAnimation::finished,this,[=](){ + setVisible(false); + }); + + connect(this,&CircularReveal::radiusChanged,this,[=](){ + update(); + }); +} + +void CircularReveal::paint(QPainter* painter) +{ + painter->save(); + painter->drawImage(QRect(0, 0, static_cast(width()), static_cast(height())), _source); + QPainterPath path; + path.moveTo(_center.x(),_center.y()); + path.addEllipse(QPointF(_center.x(),_center.y()), _radius, _radius); + painter->setCompositionMode(QPainter::CompositionMode_Clear); + painter->fillPath(path, Qt::black); + painter->restore(); +} + +void CircularReveal::start(int w,int h,const QPoint& center,int radius){ + _anim->setStartValue(0); + _anim->setEndValue(radius); + _center = center; + _grabResult = _target->grabToImage(QSize(w,h)); + connect(_grabResult.data(), &QQuickItemGrabResult::ready, this, &CircularReveal::handleGrabResult); +} + +void CircularReveal::handleGrabResult(){ + _grabResult.data()->image().swap(_source); + update(); + setVisible(true); + Q_EMIT imageChanged(); + _anim->start(); } diff --git a/example/src/component/CircularReveal.h b/example/src/component/CircularReveal.h index adc3b41d..ebc891e8 100644 --- a/example/src/component/CircularReveal.h +++ b/example/src/component/CircularReveal.h @@ -2,15 +2,28 @@ #define CIRCULARREVEAL_H #include +#include +#include +#include +#include "src/stdafx.h" -class CircularReveal : public QQuickItem +class CircularReveal : public QQuickPaintedItem { Q_OBJECT + Q_PROPERTY_AUTO(QQuickItem*,target) + Q_PROPERTY_AUTO(int,radius) public: - CircularReveal(); - -signals: + CircularReveal(QQuickItem* parent = nullptr); + void paint(QPainter* painter) override; + Q_INVOKABLE void start(int w,int h,const QPoint& center,int radius); + Q_SIGNAL void imageChanged(); + Q_SLOT void handleGrabResult(); +private: + QImage _source; + QPropertyAnimation* _anim; + QPoint _center; + QSharedPointer _grabResult; }; #endif // CIRCULARREVEAL_H