Как установить масштабирование для просмотра QML-диаграмм

Я занимаюсь разработкой приложения для представления данных с использованием QT QML и QTCharts. Я использую ChartView и ряд линий для отображения данных XY. Все работает отдельно от сжатия и масштабирования графика. Приложение предназначено для мобильного сенсорного устройства.

Я хочу иметь возможность ущипнуть и увеличить масштаб графика и установить начало масштабирования в центр пинча. В настоящее время у меня это работает, но график всегда увеличивается только от центра графика.

Это возможно в QML?

Спасибо за любую помощь.

2 ответа

Решение состоит в том, чтобы использовать zoomIn(rect rectangle) метод, который может получить в качестве параметра прямоугольник, который будет виден, в вашем случае прямоугольник должен иметь в качестве центра точку, где вы щелкнете.

import QtQuick 2.9
import QtQuick.Window 2.2
import QtCharts 2.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    ChartView {
        id: chartView
        anchors.fill: parent
        theme: ChartView.ChartThemeBrownSand
        antialiasing: true

        LineSeries {
            name: "LineSeries"
            XYPoint { x: 0; y: 0 }
            XYPoint { x: 1.1; y: 2.1 }
            XYPoint { x: 1.9; y: 3.3 }
            XYPoint { x: 2.1; y: 2.1 }
            XYPoint { x: 2.9; y: 4.9 }
            XYPoint { x: 3.4; y: 3.0 }
            XYPoint { x: 4.1; y: 3.3 }
        }

        MouseArea{
            anchors.fill: parent
            onDoubleClicked: chartView.zoomReset();
        }

        PinchArea{
            id: pa
            anchors.fill: parent
            onPinchUpdated: {
                chartView.zoomReset();
                var center_x = pinch.center.x
                var center_y = pinch.center.y
                var width_zoom = height/pinch.scale;
                var height_zoom = width/pinch.scale;
                var r = Qt.rect(center_x-width_zoom/2, center_y - height_zoom/2, width_zoom, height_zoom)
                chartView.zoomIn(r)
            }

        }
    }
}

Я хочу поблагодарить eyllanesc за то, что он направил меня на правильный путь своим ответом. Я сделал несколько улучшений, чтобы добавить возможность объединять последовательные движения щипков и перетаскивать диаграмму жестом перетаскивания. Я также изменил направление движения щипка, чтобы диаграмма двигалась так, как если бы она двигалась щипком (вместо того, чтобы двигаться в противоположном направлении с исходным кодом). Масштаб применяется в направлении угла сжатия, т. е. при вертикальном сжатии будет увеличена только ось Y. Сжатие под углом 45 градусов применяет одинаковое масштабирование к обеим осям. Это дает более интуитивное ощущение.

      import QtQuick 2.9
import QtQuick.Window 2.2
import QtCharts 2.0
    
Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    ChartView {
       id: chart
       anchors.fill: parent
       theme: ChartView.ChartThemeBrownSand
       antialiasing: true

       LineSeries {
           name: "LineSeries"
           XYPoint { x: 0; y: 0 }
           XYPoint { x: 1.1; y: 2.1 }
           XYPoint { x: 1.9; y: 3.3 }
           XYPoint { x: 2.1; y: 2.1 }
           XYPoint { x: 2.9; y: 4.9 }
           XYPoint { x: 3.4; y: 3.0 }
           XYPoint { x: 4.1; y: 3.3 }
       }
       PinchArea{
           id: pa
           anchors.fill: parent
           property real currentPinchScaleX: 1
           property real currentPinchScaleY: 1
           property real pinchStartX : 0
           property real pinchStartY : 0

           onPinchStarted: {
               // Pinching has started. Record the initial center of the pinch
               // so relative motions can be reversed in the pinchUpdated signal
               // handler
               pinchStartX = pinch.center.x;
               pinchStartY = pinch.center.y;
           }

           onPinchUpdated: {
               chart.zoomReset();

               // Reverse pinch center motion direction
               var center_x = pinchStartX + (pinchStartX - pinch.center.x);
               var center_y = pinchStartY + (pinchStartY - pinch.center.y);

               // Compound pinch.scale with prior pinch scale level and apply
               // scale in the absolute direction of the pinch gesture
               var scaleX = currentPinchScaleX * (1 + (pinch.scale - 1) * Math.abs(Math.cos(pinch.angle * Math.PI / 180)));
               var scaleY = currentPinchScaleY * (1 + (pinch.scale - 1) * Math.abs(Math.sin(pinch.angle * Math.PI / 180)));

               // Apply scale to zoom levels according to pinch angle
               var width_zoom = height / scaleX;
               var height_zoom = width / scaleY;

               var r = Qt.rect(center_x - width_zoom / 2, center_y - height_zoom / 2, width_zoom, height_zoom);
               chart.zoomIn(r);
           }

           onPinchFinished: {
               // Pinch finished. Record compounded pinch scale.
               currentPinchScaleX = currentPinchScaleX * (1 + (pinch.scale - 1) * Math.abs(Math.cos(pinch.angle * Math.PI / 180)));
               currentPinchScaleY = currentPinchScaleY * (1 + (pinch.scale - 1) * Math.abs(Math.sin(pinch.angle * Math.PI / 180)));
           }

           MouseArea{
               anchors.fill: parent
               drag.target: dragTarget
               drag.axis: Drag.XAndYAxis

               onDoubleClicked: {                   
                   chart.zoomReset();
                   parent.currentPinchScaleX = 1;
                   parent.currentPinchScaleY = 1;
               }
           }

           Item {
               // A virtual item to receive drag signals from the MouseArea.
               // When x or y properties are changed by the MouseArea's
               // drag signals, the ChartView is scrolled accordingly.
               id: dragTarget

               property real oldX : x
               property real oldY : y

               onXChanged: {
                   chart.scrollLeft( x - oldX );
                   oldX = x;
               }
               onYChanged: {
                   chart.scrollUp( y - oldY );
                   oldY = y;
               }
            }
        }
    }
}
Другие вопросы по тегам