首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >JAVA:放大/缩小时,圆被绑定到imageview中的一个位置

JAVA:放大/缩小时,圆被绑定到imageview中的一个位置
EN

Stack Overflow用户
提问于 2019-04-17 07:28:26
回答 1查看 123关注 0票数 0

因此,我正在尝试在图像视图中缩放和平移图像,现在它正在完美地缩放和平移。我面临的问题是,我在图像上添加了圆圈,每当我放大/缩小时,它们总是保持在图像视图的相同位置,而图像正在正确地放大/缩小。我想要的是将圆圈绑定到图像上,这样它们就可以放大/缩小,并作为一个单元与图像一起平移。

我从另一个论坛/帖子中找到了缩放/平移的代码,并对其进行了调整,使其适用于我的代码。事实的确如此。在setImageI()方法中,我试图解决我已经注释掉的问题,但是没有起作用。

代码语言:javascript
复制
 //this function displays nodes(circles) and edges(lines)

 public void displayAllNodes() {
    ...

    mapImgPane.getChildren().remove(1, mapImgPane.getChildren().size());
    double mapX = findPathImgView.getLayoutX();
    double mapY = findPathImgView.getLayoutY();

    final double[] orgSceneX = new double[1];
    final double[] orgSceneY = new double[1];

    for (Node n : nodes) {
        orgSceneX[0] = -1;
        orgSceneY[0] = -1;
        Circle circle = new Circle();

        double mapScale = findPathImgView.getImage().getWidth() / findPathImgView.getFitWidth();
        circle.setCenterX(mapX + n.getX() / mapScale);
        circle.setCenterY(mapY + n.getY() / mapScale);
        circle.setRadius(3.0);
        circle.setFill(black);
        mapImgPane.getChildren().add(circle);
        nodeCircles.put(n.getID(), circle);
    }
    for (Edge e : edges) {
        if (!(nodeCircles.containsKey(e.getStartNode()) && nodeCircles.containsKey(e.getEndNode()))) {
            // this edge is not on this floor so we do not draw it
        } else {
            Line line = new Line();
            line.startXProperty().bind(nodeCircles.get(e.getStartNode()).centerXProperty());
            line.startYProperty().bind(nodeCircles.get(e.getStartNode()).centerYProperty());
            line.endXProperty().bind(nodeCircles.get(e.getEndNode()).centerXProperty());
            line.endYProperty().bind(nodeCircles.get(e.getEndNode()).centerYProperty());
            line.setStroke(black);
            mapImgPane.getChildren().add(line);
        }
    }

    if (findLocationNodeID != null && nodeCircles.containsKey(findLocationNodeID)) {
        Circle foundNode = nodeCircles.get(findLocationNodeID);

        foundNode.setRadius(6.0);
        foundNode.setFill(Color.ORANGERED);
        foundNode.toFront();

        ScaleTransition st = new ScaleTransition(Duration.millis(2000), foundNode);
        st.setByX(1.2);
        st.setByY(1.2);
        st.setCycleCount(Animation.INDEFINITE);
        st.setAutoReverse(true);
        st.play();
    }
 }

 //this function sets the image to the imageview, calls the zoom function setImageI() to add zoom/pan functionality to imageview
 public void updateFloorImg(String floor) {
    ...

    if (imageCache.containsKey(floorURL)) {
        findPathImgView.setImage(imageCache.get(floorURL));
        setImageI(imageCache.get(floorURL));
    } else {
        Image newImage = new Image(String.valueOf(getClass().getResource("/img/" + floorURL)));
        imageCache.put(floorURL, newImage);
        findPathImgView.setImage(newImage);
        setImageI(newImage);
    }
    findPathImgView.fitWidthProperty().bind(mapImgPane.widthProperty());
 }

 //this function and subsequent functions I found from a post enables zoom/pan functionality
 private void setImageI(Image image) {

    double width = findPathImgView.getImage().getWidth();
    double height = findPathImgView.getImage().getHeight();

    findPathImgView.setPreserveRatio(true);
    reset(findPathImgView, width, height);

    ObjectProperty<Point2D> mouseDown = new SimpleObjectProperty<>();

    findPathImgView.setOnMousePressed(e -> {

        Point2D mousePress = imageViewToImage(findPathImgView, new Point2D(e.getX(), e.getY()));
        mouseDown.set(mousePress);
    });

    findPathImgView.setOnMouseDragged(e -> {
        Point2D dragPoint = imageViewToImage(findPathImgView, new Point2D(e.getX(), e.getY()));
        shift(findPathImgView, dragPoint.subtract(mouseDown.get()));
        mouseDown.set(imageViewToImage(findPathImgView, new Point2D(e.getX(), e.getY())));
    });

    findPathImgView.setOnScroll(e -> {
        double delta = e.getDeltaY();
        Rectangle2D viewport = findPathImgView.getViewport();

        double scale = clamp(Math.pow(1.01, delta),

                // don't scale so we're zoomed in to fewer than MIN_PIXELS (1000px) in any direction:
                Math.min(MIN_PIXELS / viewport.getWidth(), MIN_PIXELS / viewport.getHeight()),

                // don't scale so that we're bigger than image dimensions:
                Math.max(width / viewport.getWidth(), height / viewport.getHeight())

        );

        currentZoomLevel /= scale;

        Point2D mouse = imageViewToImage(findPathImgView, new Point2D(e.getX(), e.getY()));

        double newWidth = viewport.getWidth() * scale;
        double newHeight = viewport.getHeight() * scale;

        // To keep the visual point under the mouse from moving, we need
        // (x - newViewportMinX) / (x - currentViewportMinX) = scale
        // where x is the mouse X coordinate in the image

        // solving this for newViewportMinX gives

        // newViewportMinX = x - (x - currentViewportMinX) * scale

        // we then clamp this value so the image never scrolls out
        // of the imageview:

        double newMinX = clamp(mouse.getX() - (mouse.getX() - viewport.getMinX()) * scale,
                0, width - newWidth);
        double newMinY = clamp(mouse.getY() - (mouse.getY() - viewport.getMinY()) * scale,
                0, height - newHeight);

        findPathImgView.setViewport(new Rectangle2D(newMinX, newMinY, newWidth, newHeight));

        // let's do some math to move and scale the nodes

       double mapScale = findPathImgView.getImage().getWidth() / findPathImgView.getFitWidth();

        /*** HERE I included stuff for the circles ***/
        for (Circle c : nodeCircles.values()) {
            c.setScaleX(currentZoomLevel);
            c.setScaleY(currentZoomLevel);


                 /*** This is how I tried to fix it but doesn't really work. ***/
 //                if (mouse.getX() / mapScale > c.getCenterX()) {
 //                    c.setCenterX(c.getCenterX() - Math.abs(c.getCenterX() - mouse.getX() / mapScale) * scale);
 //                } else {
 //                    c.setCenterX(c.getCenterX() + Math.abs(c.getCenterX() - mouse.getX() / mapScale) * scale);
 //                }


 //                c.setCenterX(c.getCenterX() + (scale * mouse.getX()));
 //                c.setCenterY(c.getCenterY() + (scale * mouse.getY()));
 //                c.scaleXProperty().setValue(currentZoomLevel);
 //                c.scaleYProperty().setValue(currentZoomLevel);
        }


    });

    findPathImgView.setOnMouseClicked(e -> {
        if (e.getClickCount() == 2) {
            reset(findPathImgView, width, height);
        }
    });

    findPathImgView.setPreserveRatio(true);


    findPathImgView.fitWidthProperty().bind(mapImgPane.widthProperty());
    findPathImgView.fitHeightProperty().bind(mapImgPane.heightProperty());
 }

 // reset to the top left:
 private void reset(ImageView imageView, double width, double height) {
    imageView.setViewport(new Rectangle2D(0, 0, width, height));
    currentZoomLevel = 1;
 }

 // shift the viewport of the imageView by the specified delta, clamping so
 // the viewport does not move off the actual image:
 private void shift(ImageView imageView, Point2D delta) {
    Rectangle2D viewport = imageView.getViewport();

    double width = imageView.getImage().getWidth() ;
    double height = imageView.getImage().getHeight() ;

    double maxX = width - viewport.getWidth();
    double maxY = height - viewport.getHeight();

    double minX = clamp(viewport.getMinX() - delta.getX(), 0, maxX);
    double minY = clamp(viewport.getMinY() - delta.getY(), 0, maxY);

    imageView.setViewport(new Rectangle2D(minX, minY, viewport.getWidth(), viewport.getHeight()));
 }

 private double clamp(double value, double min, double max) {

    if (value < min)
        return min;
    if (value > max)
        return max;
    return value;
 }

 // convert mouse coordinates in the imageView to coordinates in the actual image:
 private Point2D imageViewToImage(ImageView imageView, Point2D imageViewCoordinates) {
    double xProportion = imageViewCoordinates.getX() / imageView.getBoundsInLocal().getWidth();
    double yProportion = imageViewCoordinates.getY() / imageView.getBoundsInLocal().getHeight();

    Rectangle2D viewport = imageView.getViewport();
    return new Point2D(
            viewport.getMinX() + xProportion * viewport.getWidth(),
            viewport.getMinY() + yProportion * viewport.getHeight());
 }

 private ImageView setImageView(Image image) {
    ImageView imageView = new ImageView();
    imageView.setImage(image);

    double w;
    double h;

    double ratioX = imageView.getFitWidth() / imageView.getImage().getWidth();
    double ratioY = imageView.getFitHeight() / imageView.getImage().getHeight();

    double reducCoeff;
    if(ratioX >= ratioY) {
        reducCoeff = ratioY;
    } else {
        reducCoeff = ratioX;
    }

    w = imageView.getImage().getWidth() * reducCoeff;
    h = imageView.getImage().getHeight() * reducCoeff;

    imageView.setX((imageView.getFitWidth() - w) / 2);
    imageView.setY((imageView.getFitHeight() - h) / 2);

    return imageView;
 }

我希望圆相对于图像移动/缩放/平移,而不是停留在视图的一个位置。任何帮助都是非常感谢的。谢谢。

EN

回答 1

Stack Overflow用户

发布于 2019-04-17 07:33:06

如果你正在使用场景构建器,在你的圆上添加方法,这些方法根据图像发生的事情而起作用。比如当你放大它的时候,让圆圈也变大等等。这可以用基本的JavaFx来实现,但最好是可视化的

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55717877

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档