Processing中实现基于鼠标输入的图形旋转与独立变换教程

Processing中实现基于鼠标输入的图形旋转与独立变换教程

本教程旨在解决pr%ignore_a_1%cessing中图形旋转时出现偏移的问题,并实现多个图形的独立旋转。我们将深入探讨processing的坐标系统、`translate()`、`rotate()`等变换函数,并重点介绍如何利用`pushmatrix()`和`popmatrix()`创建独立的变换上下文,从而使图形在保持自身位置的同时,根据鼠标输入进行平移和独立方向的旋转,最终提供一个结合相对坐标和变换管理的完整解决方案。

Processing中图形变换的挑战与核心概念

在Processing等图形编程环境中,对屏幕上的图形进行移动(平移)、旋转和缩放是常见的操作。然而,初学者常遇到的一个问题是,当尝试旋转图形时,它们往往会“飞出”屏幕,而不是原地旋转。这通常是因为对Processing的坐标系统和变换机制理解不足。

1. 理解Processing的坐标系统与全局变换

Processing的绘图操作默认基于一个全局的坐标系统,其原点(0,0)位于画布的左上角。当您使用translate()、rotate()或scale()等函数时,这些变换会应用于整个坐标系统,影响后续所有绘制操作。

translate(x, y): 将坐标原点移动到(x, y)。这意味着之后所有使用绝对坐标绘制的图形都会相对于这个新的原点进行绘制。rotate(angle): 围绕当前坐标原点旋转整个坐标系统一个指定的角度。

问题在于,如果您的图形是使用绝对坐标(例如triangle(1000,600,900,850,800,600))定义的,并且其中心点与坐标原点不重合,那么直接应用rotate()会导致图形围绕画布的(0,0)点旋转,从而使其看起来像是在“飞出”屏幕。要实现原地旋转,图形需要围绕其自身的中心点旋转。

2. 解决方案核心:pushMatrix() 与 popMatrix()

为了实现图形的独立变换(例如,一个图形旋转,而另一个图形不旋转或以不同方式旋转),我们需要为每个图形创建独立的变换上下文。这就是pushMatrix()和popMatrix()的作用。

pushMatrix(): 保存当前坐标系统的状态(包括当前的平移、旋转、缩放等变换)。popMatrix(): 恢复到最近一次pushMatrix()保存的坐标系统状态。

通过在pushMatrix()和popMatrix()之间执行绘制和变换操作,您可以确保这些变换仅作用于该码块内的图形,而不会影响块外部的图形或全局坐标系统。这使得对不同图形应用独立的平移、旋转和缩放成为可能。

构建可拖动与独立旋转的图形

现在,我们将结合这些概念,逐步构建一个能够通过鼠标拖动平移,并使两个星形图形独立旋转的Processing程序。

步骤一:实现鼠标拖动平移

首先,我们需要一个机制来响应鼠标拖动事件,并更新图形的平移位置。

闪念贝壳 闪念贝壳

闪念贝壳是一款AI 驱动的智能语音笔记,随时随地用语音记录你的每一个想法。

闪念贝壳 218 查看详情 闪念贝壳

float offsetX = 0; // 用于存储全局平移的X偏移量float offsetY = 0; // 用于存储全局平移的Y偏移量float rotationAngle = 0; // 用于存储旋转角度,这里暂不使用void setup(){  size(1800, 1000); // 设置画布大小}void draw() {  background(0); // 清空背景  // 应用全局平移,使整个场景可以被拖动  translate(offsetX, offsetY);  // 在这里绘制您的图形...  // 为了演示平移,我们暂时使用原始的绝对坐标绘制  drawStarsAbsolute();   fill(0,0,0);  ellipse(900 - (1800/2) + offsetX, 500 - (1000/2) + offsetY, 425, 425); // 绘制中心圆,注意需要考虑translate的影响}void mouseDragged(){  // 当鼠标被拖动时,更新偏移量  // 这里的offsetX和offsetY直接设置为mouseX和mouseY,  // 配合translate(offsetX, offsetY)可以将画布原点移动到鼠标位置  offsetX = mouseX;  offsetY = mouseY;}// 原始的图形绘制函数,使用绝对坐标void drawStarsAbsolute() {  beginShape();  fill(139,19,191); triangle(1000,600,900,850,800,600);  fill(20,134,245); triangle (1100,400,1250,600,1000,600);  fill(191,8,8); triangle(800,600,550,600,700,400);  fill(86,165,3); triangle(700,400,550,100,900,350);  fill(167,167,166); triangle(900,350,1250,100,1100,400);  endShape();  beginShape();  fill(139,19,191); triangle(800,350,900,100,1000,350);  fill(86,165,3); triangle(1000,350,1250,350,1100,550);  fill(167,167,166); triangle(700,550,550,350,800,350);  fill(20,134,245); triangle(700,550,550,850,900,650);  fill(191,8,8); triangle(1100,550,1250,850,900,650);  endShape();}

注意: 在上述代码中,为了演示全局平移,我们直接使用了offsetX = mouseX; offsetY = mouseY;。当translate(offsetX, offsetY)被调用时,画布的原点会被移动到鼠标当前的位置。如果您的图形是使用绝对坐标(例如900,500)绘制的,那么它们也会随着这个原点的移动而移动。为了使图形围绕一个固定的逻辑中心点(例如width/2, height/2)进行拖动,并且图形本身是相对该中心点绘制的,通常会在mouseDragged中计算偏移量:offsetX = mouseX – width/2; offsetY = mouseY – height/2;,但这要求图形的绘制也以(0,0)为中心。

步骤二:图形中心化与相对坐标

要实现原地旋转,图形的定义必须是相对于其旋转中心的。如果图形的中心点是(Cx, Cy),那么图形的所有顶点坐标都应该表示为(Vx – Cx, Vy – Cy)。这样,当您对图形应用translate(Cx, Cy)将其移动到屏幕上的目标位置,再应用rotate(angle)时,它就会围绕其自身新的原点(即(Cx, Cy))旋转。

原始代码中的星形图形是使用绝对坐标绘制的,它们的逻辑中心大致在(900, 500)附近。为了方便旋转,我们需要将这些坐标转换为相对于(900, 500)的相对坐标。例如,如果一个顶点是(1000, 600),那么相对于中心(900, 500),它的相对坐标就是(1000-900, 600-500),即(100, 100)。

步骤三:独立旋转实现与完整代码

现在,我们将结合pushMatrix()、popMatrix()、translate()、rotate()以及相对坐标来构建最终的解决方案。我们将使用frameCount作为旋转角度的来源,以实现连续旋转,并通过正负值控制旋转方向。

float globalOffsetX = 0; // 全局平移的X偏移量float globalOffsetY = 0; // 全局平移的Y偏移量void setup(){  size (1800,1000); // 设置画布大小  // 确保平滑绘制,避免锯齿  smooth(); }void draw() {  background (0); // 清空背景  // 1. 应用全局平移:整个场景随鼠标拖动  // 这里的globalOffsetX和globalOffsetY直接是鼠标位置,  // 意味着整个画布的原点被移动到鼠标位置。  // 因为下面的图形都以(0,0)为中心绘制,所以translate(globalOffsetX, globalOffsetY)  // 相当于将所有图形的逻辑中心移动到鼠标位置。  translate(globalOffsetX, globalOffsetY);   // 第一个星形:顺时针旋转  pushMatrix(); // 保存当前坐标系统状态    // 旋转变换:围绕当前原点(即translate(globalOffsetX, globalOffsetY)后的位置)旋转    rotate(frameCount * 0.01); // frameCount是一个递增的变量,用于连续旋转    // 绘制第一个星形(使用相对于其中心点的坐标)    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()之前的坐标系统状态  // 第二个星形:逆时针旋转  pushMatrix(); // 再次保存当前坐标系统状态    // 旋转变换:逆时针旋转    rotate(frameCount * -0.01);     // 绘制第二个星形(使用相对于其中心点的坐标)    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()之前的坐标系统状态  // 绘制中心圆(同样使用相对于当前原点(0,0)的坐标)  fill(0,0,0);  // 这里使用ellipse而不是circle,因为Processing自带的circle可能与自定义的冲突  ellipse(0, 0, 425, 425); }// 鼠标拖动事件处理void mouseDragged(){  // 更新全局平移偏移量,使图形跟随鼠标移动  globalOffsetX = mouseX;  globalOffsetY = mouseY;}// 如果您需要一个自定义的circle函数,可以这样定义// void circle(float x, float y, float r){//   ellipse(x, y, r, r);// }

代码解析:

globalOffsetX, globalOffsetY: 这两个变量存储了鼠标拖动带来的全局平移量。在draw()函数开始时,translate(globalOffsetX, globalOffsetY)将整个绘图的原点移动到鼠标的当前位置。相对坐标绘制: 两个星形的所有顶点坐标都已转换为相对于其自身中心点的坐标。例如,如果原始中心是(900, 500),那么所有顶点都减去了(900, 500)。这样,当translate()将绘图原点移动到(globalOffsetX, globalOffsetY)后,这些相对坐标的图形就会以(globalOffsetX, globalOffsetY)为中心进行绘制。pushMatrix() / popMatrix():在绘制每个星形之前调用pushMatrix(),保存当前(已全局平移)的坐标系统状态。在pushMatrix()和popMatrix()之间,对该星形应用rotate()变换。这个rotate()只影响当前星形,因为它在独立的变换上下文中。popMatrix()恢复到pushMatrix()之前的状态,确保下一个星形的绘制从相同的全局平移状态开始,而不受前一个星形旋转的影响。*`rotate(frameCount 0.01)**:frameCount是Processing内置的一个变量,表示程序运行至今的帧数。通过乘以一个小的浮点数(例如0.01`),我们可以实现平滑、连续的旋转动画。正值表示顺时针旋转,负值表示逆时针旋转。中心圆: 同样使用相对坐标(0,0)绘制,确保它始终位于星形的中心。

注意事项与最佳实践

变换顺序的重要性: 在pushMatrix()和popMatrix()之间,变换的顺序通常是translate() -> rotate() -> scale()。先平移到图形的中心,再进行旋转,最后进行缩放,这样可以确保旋转和缩放都围绕图形自身的中心进行。图形的中心点: 始终将图形的几何中心定义为相对坐标的(0,0)点,这样在应用translate()和rotate()时会更加直观和有效。嵌套使用pushMatrix() / popMatrix(): 您可以根据需要嵌套使用pushMatrix()和popMatrix()来管理更复杂的场景,例如一个旋转的行星系统,其中每个行星自身也在旋转。性能考量: 对于大量图形,频繁的pushMatrix()/popMatrix()和复杂的变换可能会影响性能。在必要时,可以考虑使用P3D渲染模式或自定义着色器。角度单位: Processing的rotate()函数默认使用弧度(radians)。如果您习惯使用角度(degrees),可以使用radians()函数进行转换,例如rotate(radians(45))。

总结

通过本教程,我们学习了如何在Processing中利用translate()、rotate()以及关键的pushMatrix()和popMatrix()函数,实现对图形的精确控制。理解这些变换的工作原理,尤其是如何通过相对坐标和独立的变换上下文来管理图形,是创建复杂、交互式Processing动画和应用程序的基础。掌握这些技巧,您将能够让屏幕上的图形按照您的意愿灵活舞动,而不再担心它们会“飞出”画面。

以上就是Processing中实现基于鼠标输入的图形旋转与独立变换教程的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/978218.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月1日 20:20:42
下一篇 2025年12月1日 20:21:04

相关推荐

  • Uniapp 中如何不拉伸不裁剪地展示图片?

    灵活展示图片:如何不拉伸不裁剪 在界面设计中,常常需要以原尺寸展示用户上传的图片。本文将介绍一种在 uniapp 框架中实现该功能的简单方法。 对于不同尺寸的图片,可以采用以下处理方式: 极端宽高比:撑满屏幕宽度或高度,再等比缩放居中。非极端宽高比:居中显示,若能撑满则撑满。 然而,如果需要不拉伸不…

    2025年12月24日
    400
  • 如何让小说网站控制台显示乱码,同时网页内容正常显示?

    如何在不影响用户界面的情况下实现控制台乱码? 当在小说网站上下载小说时,大家可能会遇到一个问题:网站上的文本在网页内正常显示,但是在控制台中却是乱码。如何实现此类操作,从而在不影响用户界面(UI)的情况下保持控制台乱码呢? 答案在于使用自定义字体。网站可以通过在服务器端配置自定义字体,并通过在客户端…

    2025年12月24日
    800
  • 如何在地图上轻松创建气泡信息框?

    地图上气泡信息框的巧妙生成 地图上气泡信息框是一种常用的交互功能,它简便易用,能够为用户提供额外信息。本文将探讨如何借助地图库的功能轻松创建这一功能。 利用地图库的原生功能 大多数地图库,如高德地图,都提供了现成的信息窗体和右键菜单功能。这些功能可以通过以下途径实现: 高德地图 JS API 参考文…

    2025年12月24日
    400
  • 如何使用 scroll-behavior 属性实现元素scrollLeft变化时的平滑动画?

    如何实现元素scrollleft变化时的平滑动画效果? 在许多网页应用中,滚动容器的水平滚动条(scrollleft)需要频繁使用。为了让滚动动作更加自然,你希望给scrollleft的变化添加动画效果。 解决方案:scroll-behavior 属性 要实现scrollleft变化时的平滑动画效果…

    2025年12月24日
    000
  • 如何为滚动元素添加平滑过渡,使滚动条滑动时更自然流畅?

    给滚动元素平滑过渡 如何在滚动条属性(scrollleft)发生改变时为元素添加平滑的过渡效果? 解决方案:scroll-behavior 属性 为滚动容器设置 scroll-behavior 属性可以实现平滑滚动。 html 代码: click the button to slide right!…

    2025年12月24日
    500
  • 如何选择元素个数不固定的指定类名子元素?

    灵活选择元素个数不固定的指定类名子元素 在网页布局中,有时需要选择特定类名的子元素,但这些元素的数量并不固定。例如,下面这段 html 代码中,activebar 和 item 元素的数量均不固定: *n *n 如果需要选择第一个 item元素,可以使用 css 选择器 :nth-child()。该…

    2025年12月24日
    200
  • 使用 SVG 如何实现自定义宽度、间距和半径的虚线边框?

    使用 svg 实现自定义虚线边框 如何实现一个具有自定义宽度、间距和半径的虚线边框是一个常见的前端开发问题。传统的解决方案通常涉及使用 border-image 引入切片图片,但是这种方法存在引入外部资源、性能低下的缺点。 为了避免上述问题,可以使用 svg(可缩放矢量图形)来创建纯代码实现。一种方…

    2025年12月24日
    100
  • 如何让“元素跟随文本高度,而不是撑高父容器?

    如何让 元素跟随文本高度,而不是撑高父容器 在页面布局中,经常遇到父容器高度被子元素撑开的问题。在图例所示的案例中,父容器被较高的图片撑开,而文本的高度没有被考虑。本问答将提供纯css解决方案,让图片跟随文本高度,确保父容器的高度不会被图片影响。 解决方法 为了解决这个问题,需要将图片从文档流中脱离…

    2025年12月24日
    000
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200
  • 如何利用 CSS 选中激活标签并影响相邻元素的样式?

    如何利用 css 选中激活标签并影响相邻元素? 为了实现激活标签影响相邻元素的样式需求,可以通过 :has 选择器来实现。以下是如何具体操作: 对于激活标签相邻后的元素,可以在 css 中使用以下代码进行设置: li:has(+li.active) { border-radius: 0 0 10px…

    2025年12月24日
    100
  • 如何模拟Windows 10 设置界面中的鼠标悬浮放大效果?

    win10设置界面的鼠标移动显示周边的样式(探照灯效果)的实现方式 在windows设置界面的鼠标悬浮效果中,光标周围会显示一个放大区域。在前端开发中,可以通过多种方式实现类似的效果。 使用css 使用css的transform和box-shadow属性。通过将transform: scale(1.…

    2025年12月24日
    200
  • 为什么我的 Safari 自定义样式表在百度页面上失效了?

    为什么在 Safari 中自定义样式表未能正常工作? 在 Safari 的偏好设置中设置自定义样式表后,您对其进行测试却发现效果不同。在您自己的网页中,样式有效,而在百度页面中却失效。 造成这种情况的原因是,第一个访问的项目使用了文件协议,可以访问本地目录中的图片文件。而第二个访问的百度使用了 ht…

    2025年12月24日
    000
  • 如何用前端实现 Windows 10 设置界面的鼠标移动探照灯效果?

    如何在前端实现 Windows 10 设置界面中的鼠标移动探照灯效果 想要在前端开发中实现 Windows 10 设置界面中类似的鼠标移动探照灯效果,可以通过以下途径: CSS 解决方案 DEMO 1: Windows 10 网格悬停效果:https://codepen.io/tr4553r7/pe…

    2025年12月24日
    000
  • 使用CSS mask属性指定图片URL时,为什么浏览器无法加载图片?

    css mask属性未能加载图片的解决方法 使用css mask属性指定图片url时,如示例中所示: mask: url(“https://api.iconify.design/mdi:apple-icloud.svg”) center / contain no-repeat; 但是,在网络面板中却…

    2025年12月24日
    000
  • 如何用CSS Paint API为网页元素添加时尚的斑马线边框?

    为元素添加时尚的斑马线边框 在网页设计中,有时我们需要添加时尚的边框来提升元素的视觉效果。其中,斑马线边框是一种既醒目又别致的设计元素。 实现斜向斑马线边框 要实现斜向斑马线间隔圆环,我们可以使用css paint api。该api提供了强大的功能,可以让我们在元素上绘制复杂的图形。 立即学习“前端…

    2025年12月24日
    000
  • 图片如何不撑高父容器?

    如何让图片不撑高父容器? 当父容器包含不同高度的子元素时,父容器的高度通常会被最高元素撑开。如果你希望父容器的高度由文本内容撑开,避免图片对其产生影响,可以通过以下 css 解决方法: 绝对定位元素: .child-image { position: absolute; top: 0; left: …

    2025年12月24日
    000
  • CSS 帮助

    我正在尝试将文本附加到棕色框的左侧。我不能。我不知道代码有什么问题。请帮助我。 css .hero { position: relative; bottom: 80px; display: flex; justify-content: left; align-items: start; color:…

    2025年12月24日 好文分享
    200
  • 前端代码辅助工具:如何选择最可靠的AI工具?

    前端代码辅助工具:可靠性探讨 对于前端工程师来说,在HTML、CSS和JavaScript开发中借助AI工具是司空见惯的事情。然而,并非所有工具都能提供同等的可靠性。 个性化需求 关于哪个AI工具最可靠,这个问题没有一刀切的答案。每个人的使用习惯和项目需求各不相同。以下是一些影响选择的重要因素: 立…

    2025年12月24日
    300
  • 如何用 CSS Paint API 实现倾斜的斑马线间隔圆环?

    实现斑马线边框样式:探究 css paint api 本文将探究如何使用 css paint api 实现倾斜的斑马线间隔圆环。 问题: 给定一个有多个圆圈组成的斑马线图案,如何使用 css 实现倾斜的斑马线间隔圆环? 答案: 立即学习“前端免费学习笔记(深入)”; 使用 css paint api…

    2025年12月24日
    000
  • 如何使用CSS Paint API实现倾斜斑马线间隔圆环边框?

    css实现斑马线边框样式 想定制一个带有倾斜斑马线间隔圆环的边框?现在使用css paint api,定制任何样式都轻而易举。 css paint api 这是一个新的css特性,允许开发人员创建自定义形状和图案,其中包括斑马线样式。 立即学习“前端免费学习笔记(深入)”; 实现倾斜斑马线间隔圆环 …

    2025年12月24日
    100

发表回复

登录后才能评论
关注微信