本文基于互动媒体技术实验,使用p5.js库对动态GIF图像进行临摹重现。文章详细解析了棍状体与螺旋体两个核心部分的运动规律,重点阐述如何利用三角函数实现匀速圆周运动,并提供了完整的p5.js代码实现。此外,还总结了p5.js在函数参数声明与变量类型使用上的特性,并展示了一个结合鼠标交互的时钟扩展作品。
前言与实验背景
前言
根据互动媒体技术课程实验要求,本文对一张GIF动态图进行了临摹,并采用p5.js库完成了图像的重现。文中将详细阐述实现逻辑与相关代码,并在末尾展示一个基于此原理的扩展作品。
原图

原图分析与运动规律
实现步骤
规律总结
通过观察原图,可以发现图像主要由两部分构成:棍状体和螺旋状体。
棍状体呈现从外到内逐渐变窄的特征,整体图形围绕固定的旋转圆心进行匀速圆周运动。
螺旋状体同样围绕该固定旋转圆心进行匀速圆周运动。
螺旋状体的旋转角速度大于棍状体的旋转角速度。
p5.js实现逻辑与代码
具体实现逻辑
为了便于分析,这里截取一个静态瞬间进行观察:

接下来探讨具体的实现方法。
我们可以分别编写两个函数来绘制棍状体和螺旋体,然后在draw()函数中调用这两个函数即可完成整体效果。
以下是棍状体的实现函数:
//圆周运动棍状体绘制函数
function drawBoll(r, g, b, interval)
以下是螺旋体的实现函数:
//圆周运动螺旋体的绘制函数
function drawBoll2( r, g, b, interval)
下面分两部分详细说明实现过程:
首先是棍状体部分。观察静止状态下的棍状体,它由14个小圆形组成,从外到内半径逐渐减小,颜色依次为红、橙、黄、绿、青、蓝、紫。每个小圆形都绕固定圆心做匀速圆周运动。实现思路是:先绘制一个做匀速圆周运动的小圆,其他小圆只需调整旋转半径、自身半径及颜色即可。关于匀速圆周运动的具体实现,将在后文详述。
其次是螺旋体部分。螺旋体同样由圆形重复变换生成,各圆形大小一致,区别在于颜色、旋转半径以及初始存在的弧度间隔。实现方法是:先绘制一个做匀速圆周运动的圆形,通过修改相关参数来生成其他部分。
最后一步是在draw()函数中通过for循环调用上述函数来实现整体动画。
for (var i =1;i < 15; i++) // for循环实现变化的重复
{
//其中前三个参数是颜色的RGB值,最后一个参数i实现各个圆形之间的变化
drawBoll(139, 0, 255, i);
drawBoll2(139, 0, 255, i);
i++;
drawBoll(0, 0, 255, i);
drawBoll2(0, 0, 255, i);
i++;
drawBoll(0, 255, 255, i);
drawBoll2(0, 255, 255, i);
i++;
drawBoll(0, 255, 0, i);
drawBoll2(0, 255, 0, i);
i++;
drawBoll(255, 255, 0, i);
drawBoll2(255, 255, 0, i);
i++;
drawBoll(255, 165, 0, i);
drawBoll2(255, 165, 0, i);
i++;
drawBoll(255, 0, 0, i);
drawBoll2(255, 0, 0, i);
}
代码实现
以下是该程序完整的p5.js代码:
//准备画板
function setup() {
createCanvas(1000, 1000);
}
//开始作画
function draw() {
background(50); //背景颜色
for (var i =1;i < 15; i++) // for循环实现变化的重复
{
//其中前三个参数是颜色的RGB值,最后一个参数i实现各个圆形之间的变化
drawBoll(139, 0, 255, i);
drawBoll2(139, 0, 255, i);
i++;
drawBoll(0, 0, 255, i);
drawBoll2(0, 0, 255, i);
i++;
drawBoll(0, 255, 255, i);
drawBoll2(0, 255, 255, i);
i++;
drawBoll(0, 255, 0, i);
drawBoll2(0, 255, 0, i);
i++;
drawBoll(255, 255, 0, i);
drawBoll2(255, 255, 0, i);
i++;
drawBoll(255, 165, 0, i);
drawBoll2(255, 165, 0, i);
i++;
drawBoll(255, 0, 0, i);
drawBoll2(255, 0, 0, i);
}
}
//圆周运动棍状体绘制函数
function drawBoll(r, g, b, interval){
fill(r, g, b);
var x = 500; //圆周运动圆心的x坐标
var y = 500; //圆周运动圆心的y坐标
var t = millis() / 3; // 控制旋转速度的参数
var xChange //圆周运动x坐标变化值
var yChange; //圆周运动y坐标变化值
var radius = interval * 15;//圆周运动的半径
xChange = radius * Math.cos(t * Math.PI/180);
yChange = radius * Math.sin(t * Math.PI/180);
x += xChange;
y += yChange;
ellipse(x, y, interval * 5, interval * 5);
}
//圆周运动螺旋体的绘制函数
function drawBoll2( r, g, b, interval){
fill(r, g, b);
var x = 500; //圆周运动圆心的x坐标
var y = 500; //圆周运动圆心的y坐标
var t = millis() / 1 + interval * 24; //24是两个小球之间间隔的角度
var xChange //圆周运动x坐标变化值
var yChange; //圆周运动y坐标变化值
var radius = interval * 15;//圆周运动的半径
xChange = radius * Math.cos(t * Math.PI/180);
yChange = radius * Math.sin(t * Math.PI/180);
x += xChange;
y += yChange;
ellipse(x, y, 30, 30);
}
常见问题与p5.js特性
遇到的问题以及解决方案
1、如何实现匀速圆周运动?
承接上文,具体如何计算并实现匀速圆周运动?
实现匀速圆周运动需遵循以下步骤:首先确定旋转半径、旋转圆心坐标及旋转角速度;其次,利用三角函数计算运动点坐标与圆心坐标的差值;最后,将圆心坐标加上该差值得到圆周上各点的坐标,并以这些坐标为圆心绘制小圆,从而构成所需的图形。
匀速圆周运动的具体代码实现如下:
var x = 500; //圆周运动圆心的x坐标
var y = 500; //圆周运动圆心的y坐标
var t = millis() / 3; // 控制旋转速度的参数
var xChange //圆周运动x坐标变化值
var yChange; //圆周运动y坐标变化值
var radius = interval * 15;//圆周运动的半径
xChange = radius * Math.cos(t * Math.PI/180);
yChange = radius * Math.sin(t * Math.PI/180);
x += xChange;
y += yChange;
ellipse(x, y, interval * 5, interval * 5);
2、p5.js与其他编程语言的区别
在p5.js中定义函数时,形参无需声明类型,例如:
function drawBoll(r, g, b, interval)
上述为正确写法,以下为错误写法:
function drawBoll(var r, var g, var b, var interval)
即在形参中不能使用var进行声明,否则会导致报错。
此外,在p5.js中声明变量使用var即可,无需使用int、char、string等类型声明。
结果图

扩展作品:鼠标交互时钟
扩展作品

扩展作品介绍
这是一个时钟扩展作品,增加了鼠标交互功能。
中间的时针、分针和秒针实现方式与前述GIF中的棍状体相同,仅调整了角速度和圆形大小参数,此处不再赘述。
重点介绍简单的鼠标交互事件。
交互效果由两部分组成:外围律动的粉色圆形和中间的爱心。
外围部分通过ellipse函数实现,圆心坐标跟随当前鼠标位置,宽高动态变化。设置一个变量size,使其不断增大,达到临界值后减小,再重新增大,代码如下:
size = size + 3;
if (size > 50)
size = 20;
ellipse(mouseX, mouseY, 20+size, 20+size);
中间部分由三个半圆组成:上方两个小半圆和下方一个大半圆,律动效果与外围部分一致。代码如下:
size = size + 3;
if (size > 50)
size = 20;
fill(255,0,0);//红色
arc(mouseX+size/4, mouseY, size/2, size/2, PI, 0);//半圆
arc(mouseX-size/4, mouseY, size/2, size/2, PI, 0);//半圆
arc(mouseX, mouseY, size, size, 0*PI, 1*PI);//半圆
具体代码实现
//准备画板
function setup() {
createCanvas(1000, 1000);
}
//开始作画
function draw() {
background(50); //背景颜色
for (var i =1;i < 15; i++) // for循环实现变化的重复
{
//其中前三个参数是颜色的RGB值,最后一个参数i实现各个圆形之间的变化
drawBoll(139, 0, 255, i);
drawBoll2(139, 0, 255, i);
drawBoll3(139, 0, 255, i);
i++;
drawBoll(0, 0, 255, i);
drawBoll2(0, 0, 255, i);
drawBoll3(0, 0, 255, i);
i++;
drawBoll(0, 255, 255, i);
drawBoll2(0, 255, 255, i);
drawBoll3(0, 255, 255, i);
i++;
drawBoll(0, 255, 0, i);
drawBoll2(0, 255, 0, i);
drawBoll3(0, 255, 0, i);
i++;
drawBoll(255, 255, 0, i);
drawBoll2(255, 255, 0, i);
drawBoll3(255, 255, 0, i);
i++;
drawBoll(255, 165, 0, i);
drawBoll2(255, 165, 0, i);
drawBoll3(255, 165, 0, i);
i++;
drawBoll(255, 0, 0, i);
drawBoll2(255, 0, 0, i);
drawBoll3(255, 0, 0, i);
}
mouse(255, 192, 203);
}
//时针绘制函数
function drawBoll(r, g, b, interval){
fill(r, g, b);
var x = 500; //圆周运动圆心的x坐标
var y = 500; //圆周运动圆心的y坐标
var t = 6 * millis() / 3600000; // 控制旋转速度的参数
var xChange //圆周运动x坐标变化值
var yChange; //圆周运动y坐标变化值
var radius = interval * 15;//圆周运动的半径
xChange = radius * Math.cos(t * Math.PI/180 - Math.PI / 2);
yChange = radius * Math.sin(t * Math.PI/180 - Math.PI / 2);
x += xChange;
y += yChange;
ellipse(x, y, 30, 30);
}
//分针绘制函数
function drawBoll2( r, g, b, interval){
fill(r, g, b);
var x = 500; //圆周运动圆心的x坐标
var y = 500; //圆周运动圆心的y坐标
var t = 6 * millis() / 60000; // 控制旋转速度的参数
var xChange //圆周运动x坐标变化值
var yChange; //圆周运动y坐标变化值
var radius = interval * 15;//圆周运动的半径
xChange = radius * Math.cos(t * Math.PI/180 - Math.PI / 2);
yChange = radius * Math.sin(t * Math.PI/180 - Math.PI / 2);
x += xChange;
y += yChange;
ellipse(x, y, 20, 20);
}
//秒针绘制函数
function drawBoll3( r, g, b, interval){
fill(r, g, b);
var x = 500; //圆周运动圆心的x坐标
var y = 500; //圆周运动圆心的y坐标
var t = 6 * millis() / 1000; // 控制旋转速度的参数
var xChange //圆周运动x坐标变化值
var yChange; //圆周运动y坐标变化值
var radius = interval * 15;//圆周运动的半径
xChange = radius * Math.cos(t * Math.PI/180 - Math.PI / 2);
yChange = radius * Math.sin(t * Math.PI/180 - Math.PI / 2);
x += xChange;
y += yChange;
ellipse(x, y, 10, 10);
}
var size = 0;
// 实现鼠标交互的函数(律动的爱心)
function mouse(r, g, b){
fill(r, g, b);
size = size + 3;
if (size > 50)
size = 20;
ellipse(mouseX, mouseY, 20+size, 20+size);
fill(255,0,0);//红色
arc(mouseX+size/4, mouseY, size/2, size/2, PI, 0);//半圆
arc(mouseX-size/4, mouseY, size/2, size/2, PI, 0);//半圆
arc(mouseX, mouseY, size, size, 0*PI, 1*PI);//半圆
}
以上为本次实验的全部内容。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。