AffineTransform 是 Java 中一个神奇的 “变形魔法书”!它能让你在画布上对图像、文字或任何图形施展各种变换魔法:
- 移动(平移):让东西从一个地方跑到另一个地方
- 旋转:让东西像陀螺一样转圈圈
- 放大缩小(缩放):让东西变大像巨人,变小像蚂蚁
- 倾斜(剪切):让东西像被风吹歪的树一样倾斜
- 组合变换:比如边转边跑,或者边缩小边倾斜
想象你是一个动画片导演,AffineTransform 就是你的 “动画特效遥控器”,按不同按钮就能实现不同的画面效果!
构造方法:创建你的变形魔法书
AffineTransform 有几种不同的 “咒语” 来创建它:
-
空白魔法书:
new AffineTransform()- 这是一本全新的、空白的魔法书,上面没有任何变形效果,就像一张白纸。
-
复制魔法书:
new AffineTransform(AffineTransform at)- 复制另一本魔法书的所有变形效果,就像复印一样。
-
设置缩放的魔法书:
new AffineTransform(double sx, double sy)- 创建一本魔法书,上面已经写好了 “放大缩小” 的咒语,sx 和 sy 是缩放比例。
-
设置平移的魔法书:
new AffineTransform(double tx, double ty)- 创建一本魔法书,上面已经写好了 “移动” 的咒语,tx 和 ty 是移动的距离。
-
设置旋转变换的魔法书:
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); } } }
- 创建一本魔法书,上面已经写好了 “旋转” 的咒语,theta 是旋转角度(以弧度为单位)。

被折叠的 条评论
为什么被折叠?



