本文介绍了JavaFx 8 - 相对于鼠标位置缩放/缩放 ScrollPane的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要相对于鼠标位置放大/缩小滚动窗格.

I need to zoom in / out on a scroll pane, relative to the mouse position.

我目前通过将我的内容包装在一个组中并缩放组本身来实现缩放功能.我使用自定义枢轴创建了一个新的 Scale 对象.(Pivot 设置为鼠标位置)

I currently achieve the zooming functionality by wrapping my content in a Group, and scaling the group itself. I create a new Scale object with a custom pivot. (Pivot is set to the mouse position)

这对于组的初始比例为 1.0 的情况非常适用,但是之后的缩放不会在正确的方向上进行缩放 - 我相信这是因为当组被缩放时相对鼠标位置会发生变化.

This works perfectly for where the Group's initial scale is 1.0, however scaling afterwards does not scale in the correct direction - I believe this is because the relative mouse position changes when the Group has been scaled.

我的代码:

@Override
public void initialize(URL location, ResourceBundle resources) {

    Delta initial_mouse_pos = new Delta();

    anchorpane.setOnScrollStarted(event -> {
        initial_mouse_pos.x = event.getX();
        initial_mouse_pos.y = event.getY();
    });

    anchorpane.setOnScroll(event -> {
        double zoom_fac = 1.05;
        double delta_y = event.getDeltaY();

        if(delta_y < 0) {
            zoom_fac = 2.0 - zoom_fac;
        }

        Scale newScale = new Scale();
        newScale.setPivotX(initial_mouse_pos.x);
        newScale.setPivotY(initial_mouse_pos.y);
        newScale.setX( content_group.getScaleX() * zoom_fac );
        newScale.setY( content_group.getScaleY() * zoom_fac );

        content_group.getTransforms().add(newScale);

        event.consume();
    });
}

private class Delta { double x, y; }

如何在不同的缩放级别获得正确的鼠标位置?是否有一种完全不同的方法可以更轻松地缩放 ScrollPane?

How do I get the correct mouse position at different levels of scaling? Is there a completely different way to zooming the ScrollPane that is easier?

推荐答案

这是一个可扩展、可平移的 JavaFX ScrollPane :

This is a scalable, pannable JavaFX ScrollPane :

import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;

public class ZoomableScrollPane extends ScrollPane {
    private double scaleValue = 0.7;
    private double zoomIntensity = 0.02;
    private Node target;
    private Node zoomNode;

    public ZoomableScrollPane(Node target) {
        super();
        this.target = target;
        this.zoomNode = new Group(target);
        setContent(outerNode(zoomNode));

        setPannable(true);
        setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
        setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
        setFitToHeight(true); //center
        setFitToWidth(true); //center

        updateScale();
    }

    private Node outerNode(Node node) {
        Node outerNode = centeredNode(node);
        outerNode.setOnScroll(e -> {
            e.consume();
            onScroll(e.getTextDeltaY(), new Point2D(e.getX(), e.getY()));
        });
        return outerNode;
    }

    private Node centeredNode(Node node) {
        VBox vBox = new VBox(node);
        vBox.setAlignment(Pos.CENTER);
        return vBox;
    }

    private void updateScale() {
        target.setScaleX(scaleValue);
        target.setScaleY(scaleValue);
    }

    private void onScroll(double wheelDelta, Point2D mousePoint) {
        double zoomFactor = Math.exp(wheelDelta * zoomIntensity);

        Bounds innerBounds = zoomNode.getLayoutBounds();
        Bounds viewportBounds = getViewportBounds();

        // calculate pixel offsets from [0, 1] range
        double valX = this.getHvalue() * (innerBounds.getWidth() - viewportBounds.getWidth());
        double valY = this.getVvalue() * (innerBounds.getHeight() - viewportBounds.getHeight());

        scaleValue = scaleValue * zoomFactor;
        updateScale();
        this.layout(); // refresh ScrollPane scroll positions & target bounds

        // convert target coordinates to zoomTarget coordinates
        Point2D posInZoomTarget = target.parentToLocal(zoomNode.parentToLocal(mousePoint));

        // calculate adjustment of scroll position (pixels)
        Point2D adjustment = target.getLocalToParentTransform().deltaTransform(posInZoomTarget.multiply(zoomFactor - 1));

        // convert back to [0, 1] range
        // (too large/small values are automatically corrected by ScrollPane)
        Bounds updatedInnerBounds = zoomNode.getBoundsInLocal();
        this.setHvalue((valX + adjustment.getX()) / (updatedInnerBounds.getWidth() - viewportBounds.getWidth()));
        this.setVvalue((valY + adjustment.getY()) / (updatedInnerBounds.getHeight() - viewportBounds.getHeight()));
    }
}

这篇关于JavaFx 8 - 相对于鼠标位置缩放/缩放 ScrollPane的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-27 09:05
查看更多