Java 中的AffineTransform 是什么?

AffineTransform 是 Java 中一个神奇的 “变形魔法书”!它能让你在画布上对图像、文字或任何图形施展各种变换魔法:

  • 移动(平移):让东西从一个地方跑到另一个地方
  • 旋转:让东西像陀螺一样转圈圈
  • 放大缩小(缩放):让东西变大像巨人,变小像蚂蚁
  • 倾斜(剪切):让东西像被风吹歪的树一样倾斜
  • 组合变换:比如边转边跑,或者边缩小边倾斜

想象你是一个动画片导演,AffineTransform 就是你的 “动画特效遥控器”,按不同按钮就能实现不同的画面效果!

构造方法:创建你的变形魔法书

AffineTransform 有几种不同的 “咒语” 来创建它:

  1. 空白魔法书new AffineTransform()

    • 这是一本全新的、空白的魔法书,上面没有任何变形效果,就像一张白纸。
  2. 复制魔法书new AffineTransform(AffineTransform at)

    • 复制另一本魔法书的所有变形效果,就像复印一样。
  3. 设置缩放的魔法书new AffineTransform(double sx, double sy)

    • 创建一本魔法书,上面已经写好了 “放大缩小” 的咒语,sx 和 sy 是缩放比例。
  4. 设置平移的魔法书new AffineTransform(double tx, double ty)

    • 创建一本魔法书,上面已经写好了 “移动” 的咒语,tx 和 ty 是移动的距离。
  5. 设置旋转变换的魔法书new AffineTransform(double theta)

    • 创建一本魔法书,上面已经写好了 “旋转” 的咒语,theta 是旋转角度(以弧度为单位)。

      常用方法:变形魔法咒语

    • 移动魔法

      • translate(double tx, double ty):让东西向右移动 tx 像素,向下移动 ty 像素。
      • 就像你用手把桌上的杯子往右推、往下推一样。
    • 旋转魔法

      • rotate(double theta):让东西绕原点(0,0)旋转 theta 弧度。
      • rotate(double theta, double x, double y):让东西绕点 (x,y) 旋转 theta 弧度。
      • 就像你用手指顶着杯子底部转圈圈。
    • 缩放魔法

      • scale(double sx, double sy):让东西在 x 方向放大 sx 倍,在 y 方向放大 sy 倍。
      • 就像你用放大镜看东西,或者用缩小镜把东西变小。
    • 倾斜魔法

      • shear(double shx, double shy):让东西在 x 方向倾斜 shx,在 y 方向倾斜 shy。
      • 就像你用手把一叠扑克牌推斜了一样。
    • 清除魔法

      • setToIdentity():清除所有变形效果,让魔法书变回空白。
      • 就像你用橡皮擦把魔法书上的咒语都擦掉。
    • 应用魔法

      • transform(Point2D src, Point2D dst):计算一个点经过变形后的新位置。
      • 就像你预测杯子被推、被转后会在哪里。

        注意事项:变形魔法的小陷阱

      • 魔法顺序很重要

        • 先旋转再移动,和先移动再旋转,效果是不一样的。
        • 就像你先把杯子转半圈再推,和先推再转半圈,杯子最后停的位置不一样。
      • 角度单位是弧度

        • Java 中角度默认用弧度表示,不是我们熟悉的角度。
        • 如果你想用角度(比如 30 度、90 度),需要先转换成弧度:Math.toRadians(角度)
      • 原点位置

        • 旋转、缩放等变形默认是绕原点 (0,0) 进行的,这通常是窗口的左上角。
        • 如果想绕其他点变形,需要用带 x,y 参数的方法。
      • 变形会叠加

        • 如果不清除之前的变形,新的变形会叠加在旧的上面。
        • 就像你先把杯子转半圈,再转半圈,杯子就转了一圈。
          import javax.swing.*;
          import java.awt.*;
          import java.awt.event.ActionEvent;
          import java.awt.event.ActionListener;
          import java.awt.geom.AffineTransform;
          
          public class AffineTransformDemo extends JFrame {
          
              // 构造方法:创建窗口
              public AffineTransformDemo() {
                  super("AffineTransform 旋转方块示例");
                  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  setSize(400, 400);
                  setLocationRelativeTo(null);
                  
                  // 创建并添加旋转面板
                  RotatingPanel panel = new RotatingPanel();
                  add(panel);
                  
                  // 创建一个定时器,每50毫秒触发一次面板重绘
                  Timer timer = new Timer(50, new ActionListener() {
                      @Override
                      public void actionPerformed(ActionEvent e) {
                          panel.rotate(); // 旋转角度增加
                          panel.repaint(); // 重绘面板
                      }
                  });
                  timer.start(); // 启动定时器
              }
          
              public static void main(String[] args) {
                  // 在事件调度线程中创建和显示GUI
                  SwingUtilities.invokeLater(() -> {
                      AffineTransformDemo demo = new AffineTransformDemo();
                      demo.setVisible(true);
                  });
              }
          
              // 旋转面板类:负责绘制和旋转方块
              class RotatingPanel extends JPanel {
                  private double angle = 0; // 当前旋转角度(弧度)
          
                  // 旋转方法:每次增加5度(转换为弧度)
                  public void rotate() {
                      angle += Math.toRadians(5); // 每次增加5度
                  }
          
                  @Override
                  protected void paintComponent(Graphics g) {
                      super.paintComponent(g);
                      Graphics2D g2 = (Graphics2D) g;
                      
                      // 启用抗锯齿,让图形更平滑
                      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                                          RenderingHints.VALUE_ANTIALIAS_ON);
                      
                      // 保存当前的变换状态(就像保存游戏进度)
                      AffineTransform originalTransform = g2.getTransform();
                      
                      // 计算窗口中心点
                      int centerX = getWidth() / 2;
                      int centerY = getHeight() / 2;
                      
                      // 创建一个新的变换:先平移到中心点,再旋转,再平移回原来的位置
                      AffineTransform transform = new AffineTransform();
                      transform.translate(centerX, centerY); // 平移到中心点
                      transform.rotate(angle); // 绕中心点旋转
                      transform.translate(-centerX, -centerY); // 平移回原来的位置
                      
                      // 应用变换
                      g2.transform(transform);
                      
                      // 绘制一个彩色方块
                      g2.setColor(Color.RED);
                      g2.fillRect(centerX - 50, centerY - 50, 100, 100);
                      
                      // 绘制一个蓝色小方块,显示旋转中心
                      g2.setColor(Color.BLUE);
                      g2.fillRect(centerX - 5, centerY - 5, 10, 10);
                      
                      // 恢复原来的变换状态(就像读取游戏进度)
                      g2.setTransform(originalTransform);
                      
                      // 在窗口底部显示当前角度
                      g2.setColor(Color.BLACK);
                      g2.drawString("当前角度: " + Math.toDegrees(angle) + "度", 10, getHeight() - 10);
                  }
              }
          }
          

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值