且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Java Graphics2D翻译和缩放

更新时间:2023-01-18 10:37:59

基本概念是,您希望使它看起来好像图形仍在可见区域内居中.我首先想到要尝试扩展翻译点,也许这可能有用,但我无法使其正常工作(3岁的小孩子想读书不会给我太多时间进行实验).

The basic idea is, you want to make it appear as if the graphics is remaining centred within the viewable area. I first thought about trying to scale the translation points, and maybe that might work, but I couldn'y get it to work (3 year old wanting to read books didn't give me much time to experiment).

基本上,您需要添加另一个平移,其中根据可见区域和缩放比例将x/y点移动适当的量,以使图像在可见区域内看起来保持静止,然后应用缩放和正常平移在它上面...

Basically, you need to add another translation in which moves the x/y point the appropriate amount based on the viewable area and the zoom so the image appears to remain stationary within the viewable area, then apply the zoom and the normal translation on-top of it...

        double width = getWidth();
        double height = getHeight();

        double zoomWidth = width * zoom;
        double zoomHeight = height * zoom;

        double anchorx = (width - zoomWidth) / 2;
        double anchory = (height - zoomHeight) / 2;

        AffineTransform at = new AffineTransform();
        at.translate(anchorx, anchory);
        at.scale(zoom, zoom);
        at.translate(-100, -100);

因此,anchorx/y表示根据可见区域的宽度和高度需要偏移图形数量的结果,以便图像在其中保持居中"状态.

So, the anchorx/y represent the amount the resulting graphics would need be offset by, based on the viewable areas width and height, so that the image will remain "centred" within in it...

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseWheelEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private double zoom = 1d;
        private BufferedImage img;

        public TestPane() {
            try {
                img = ImageIO.read(new File("..."));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            addMouseWheelListener(new MouseAdapter() {
                @Override
                public void mouseWheelMoved(MouseWheelEvent e) {
                    if (e.getPreciseWheelRotation() < 0) {
                        zoom -= 0.1;
                    } else {
                        zoom += 0.1;
                    }
//                  zoom += e.getPreciseWheelRotation();
                    if (zoom < 0.01) {
                        zoom = 0.01;
                    }

                    repaint();

                }
            });
        }

        public String format(double value) {
            return NumberFormat.getNumberInstance().format(value);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            double width = getWidth();
            double height = getHeight();

            double zoomWidth = width * zoom;
            double zoomHeight = height * zoom;

            double anchorx = (width - zoomWidth) / 2;
            double anchory = (height - zoomHeight) / 2;

            AffineTransform at = new AffineTransform();
            at.translate(anchorx, anchory);
            at.scale(zoom, zoom);
            at.translate(-100, -100);

            g2d.setTransform(at);
            g2d.drawImage(img, 0, 0, this);

            g2d.dispose();
        }

    }

}

可能有一个非常棒的数学公式可供您使用,但是我很愚蠢;)

There's probably a really awesome mathematical formula which you could use instead, but me be dumb ;)