
本教程旨在解决Processing中图形旋转和拖动时出现偏移的问题。我们将深入探讨Processing的二维坐标变换原理,包括`translate()`、`rotate()`以及`pushMatrix()`和`popMatrix()`的协同应用。通过将图形定义为相对坐标并利用独立的变换上下文,你将学会如何实现复杂场景中多个对象在鼠标输入下进行独立、精确的旋转与平移,确保图形保持在屏幕上的预期位置。
在Processing中,所有绘图操作都基于一个二维坐标系统。默认情况下,画布的左上角是(0,0)点。当直接使用triangle(1000,600,...)这样的绝对坐标绘制图形时,图形的位置是固定的。直接应用rotate()或translate()函数而不理解其作用机制,很容易导致图形“飞出”屏幕。
1. 绝对坐标的局限性
当你使用triangle(x1, y1, x2, y2, x3, y3)这样的方式定义图形时,这些(x,y)值是相对于画布原点(0,0)的绝对位置。如果你随后调用rotate(),Processing会围绕当前的坐标原点(默认为(0,0))旋转整个坐标系。由于你的图形离(0,0)很远,它会围绕一个遥远的轴心旋转,看起来就像是飞走了。
2. translate() 平移变换
translate(x, y)函数的作用是将整个坐标系统原点从(0,0)移动到新的(x, y)位置。这意味着之后所有的绘图操作都将以这个新的原点为参照。这是实现图形拖动的基础。
我们可以结合mouseDragged()事件来动态更新平移量:
float currentX = 0;
float currentY = 0;
void setup(){
size (800, 600);
}
void draw() {
background (0);
// 将坐标原点移动到 (currentX, currentY)
translate(currentX, currentY);
// 在新的坐标系中绘制一个矩形,它的左上角将位于 (currentX, currentY)
fill(255, 0, 0);
rect(0, 0, 100, 100);
}
// 当鼠标被拖动时调用
void mouseDragged(){
// 更新平移量,使图形中心跟随鼠标
// 如果图形的中心是(0,0),直接使用mouseX, mouseY即可
currentX = mouseX;
currentY = mouseY;
}在上述代码中,rect(0,0,100,100)实际上被绘制在画布的(currentX, currentY)位置。
要让图形围绕其自身中心旋转,而不是画布原点,我们需要做两件事:
1. rotate() 旋转变换
rotate(angle)函数会围绕当前的坐标原点旋转整个坐标系。angle参数通常以弧度表示。如果想让图形围绕自身中心旋转,就必须先将坐标原点移动到图形的中心。
2. pushMatrix() 和 popMatrix() 的重要性
当你在Processing中应用translate()、rotate()或scale()等变换时,这些变换会影响之后所有的绘图操作。如果想让不同的图形拥有独立的变换,就需要使用pushMatrix()和popMatrix()。
通过将一组绘图操作封装在pushMatrix()和popMatrix()之间,可以确保这些操作的变换只影响其内部的图形,而不会干扰其他图形或全局坐标系统。
3. 相对坐标的优势
为了让旋转变得简单直观,强烈建议将图形的顶点坐标定义为相对于其自身中心点(0,0)的坐标。例如,一个中心在(0,0)的正方形,其顶点可以是(-50, -50), (50, -50), (50, 50), (-50, 50)。这样,当你translate()到它的目标位置后再rotate(),它就会围绕其自身中心旋转。
现在,我们将结合上述概念,创建一个可以整体拖动,并包含两个独立旋转的星形图案的Processing草图。一个星形顺时针旋转,另一个逆时针旋转。
float globalTranslateX = 0; // 全局平移的X坐标
float globalTranslateY = 0; // 全局平移的Y坐标
void setup(){
size (1800, 1000); // 设置画布大小
// 初始时将全局平移量设置为画布中心,使图形在屏幕中央
globalTranslateX = width / 2;
globalTranslateY = height / 2;
}
void draw() {
background (0); // 清空背景
// 1. 应用全局平移:根据鼠标拖动来移动整个场景
translate(globalTranslateX, globalTranslateY);
// 2. 绘制第一个星形图案 (顺时针旋转)
pushMatrix(); // 保存当前坐标系统状态
// 应用旋转:frameCount是一个内置变量,每帧递增,用于实现连续动画
// 0.01是旋转速度,正值表示顺时针
rotate(frameCount * 0.01);
// 绘制第一个星形(由多个三角形组成),所有坐标都相对于(0,0)
fill(139, 19, 191);
triangle( 100, 100, 0, 350, -100, 100);
fill(20, 134, 245);
triangle( 200, -100, 350, 100, 100, 100);
fill(191, 8, 8);
triangle(-100, 100, -350, 100, -200, -100);
fill(86, 165, 3);
triangle(-200, -100, -350, -400, 0, -150);
fill(167, 167, 166);
triangle( 0, -150, 350, -400, 200, -100);
popMatrix(); // 恢复到pushMatrix()之前的坐标系统状态
// 3. 绘制第二个星形图案 (逆时针旋转)
pushMatrix(); // 再次保存当前坐标系统状态
// 应用旋转:负值表示逆时针
rotate(frameCount * -0.01);
// 绘制第二个星形,所有坐标同样相对于(0,0)
fill(139, 19, 191);
triangle(-100, -150, 0, -400, 100, -150);
fill(86, 165, 3);
triangle( 100, -150, 350, -150, 200, 50);
fill(167, 167, 166);
triangle(-200, 50, -350, -150, -100, -150);
fill(20, 134, 245);
triangle(-200, 50, -350, 350, 0, 150);
fill(191, 8, 8);
triangle( 200, 50, 350, 350, 0, 150);
popMatrix(); // 恢复到pushMatrix()之前的坐标系统状态
// 4. 绘制中心圆,它会随着全局平移而移动,但不会旋转
fill(0,0,0);
// 注意这里circle的坐标是(0,0),因为它将在当前的坐标原点绘制
circle(0, 0, 425);
}
// 鼠标拖动事件处理函数
void mouseDragged(){
// 更新全局平移量,使画布的(0,0)点跟随鼠标位置
// 因为我们的星形图案都是围绕(0,0)绘制的,所以这样可以拖动星形的中心
globalTranslateX = mouseX;
globalTranslateY = mouseY;
}
// Processing中没有内置的circle函数,这里提供一个辅助函数
// 它使用ellipse来绘制一个正圆
void circle(float x, float y, float r){
ellipse(x, y, r, r);
}代码解释:
通过本教程,你已经掌握了Processing中二维坐标变换的核心概念。理解translate()、rotate()以及pushMatrix()和popMatrix()的协同作用,并结合相对坐标的绘图策略,你现在能够创建出在鼠标控制下进行精确平移和独立旋转的动态图形。这些技能是构建更复杂交互式Processing应用的基础。
以上就是Processing中实现图形的精确旋转与拖动:基于坐标变换的教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号