qtqmlqtquick2qtquickcontrols

Mask from pictures, crop image behind cursor


I have a basic background from a blue image with a transparent background (PNG), how can I make a different background from the image after the arrow?

I tried the option using a mask, but it cuts the picture either in width or in height, this does not work

blue background:

blue background

it should be:

it should be

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Window 2.15
import QtQuick.Controls.Styles 1.4
import QtQuick.Extras 1.4
import QtQuick.Extras.Private 1.0
import QtGraphicalEffects 1.0
Window {
width: 1280
height: 480
visible: true
title: qsTr("Hello World")
color: "#000"


CircularGauge {
    id:gauge
    property bool accelerating
    width: 377
    height: 377
    anchors.top: parent.top
    anchors.horizontalCenter: parent.horizontalCenter
    anchors.topMargin: 101
    maximumValue:8
    value:  accelerating ? maximumValue : 0

    Component.onCompleted: forceActiveFocus()
    Behavior on value { NumberAnimation { duration: 1500 }}
    Keys.onSpacePressed: accelerating = true
    Keys.onReleased: {
        if (event.key === Qt.Key_Space) {
            accelerating = false;
            event.accepted = true;
        }
    } 
    style: CircularGaugeStyle { 
        labelStepSize: 1
        labelInset: outerRadius / 6
        minimumValueAngle: -110
        maximumValueAngle: 110 
        background: Rectangle {
            id: rectangle
            implicitHeight: gauge.height
            implicitWidth: gauge.width
            color:"Transparent"
            anchors.centerIn: parent
            radius: 360

            Image {
                width: 417
                height: 287
                anchors.top: parent.top
                source: "Blue_bg.png"
                anchors.topMargin:  -23
                anchors.horizontalCenter: parent.horizontalCenter
                asynchronous: true
                sourceSize {
                }
            }


        }

        

        foreground: Item {
            Text {
                id: speedLabel
                anchors.centerIn: parent
                anchors.verticalCenterOffset: -20
                text: "126"
                font.pixelSize:76
                color: "white"
                antialiasing: true
            }
        }

        tickmarkLabel:  Text {
            font.italic: true
            font.bold: true
            text: styleData.value
            font.pixelSize: 30
            color: styleData.value <= gauge.value ? "white" : "#ffffff"
            antialiasing: true
        }

    }

}

}

How can I achieve this effect?


Solution

  • You can use a Canvas to draw an arc (see Draw an arc/circle sector in QML?). If you combine this with an OpacityMask (see QML Circular Gauge) you can mask the blue "background" (it's more like a foreground in the given example) to make that cool speedometer :-)

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtGraphicalEffects 1.0
    
    Window {
        width: 640
        height: 480
        visible: true
    
        Image {
            id: img
            source: "blue.png"
            visible: false
        }
    
        Canvas {
            id: mask
            anchors.fill: img
    
            property double angle: 45
            onPaint: {
                var ctx = getContext("2d");
                var centerX = width / 2;
                var centerY = height / 2;
    
                ctx.beginPath();
                ctx.fillStyle = "black";
                ctx.moveTo(centerX, centerY);
                ctx.arc(centerX, centerY, width / 4, (Math.PI) * (1 + angle / 180), 0, false);
                ctx.lineTo(centerX, centerY);
                ctx.fill();
            }
        }
    
        OpacityMask {
            anchors.fill: img
            source: img
            maskSource: mask
        }
    }