使用p5.js實現動態GIF圖片臨摹重現

 更新時間:2019年10月23日 14:21:11   作者:顧清宇   我要評論
這篇文章主要為大家詳細介紹了使用p5.js實現動態GIF圖片臨摹重現,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

前言

根據互動媒體技術老師的實驗要求,臨摹了一張GIF動態圖,使用p5.js進行重現。
博客里面會有實現邏輯以及實現代碼,在最后還會有一張自己實現的擴展圖。

原圖

實現步驟

規律總結

1、觀察圖片可以看到,整個圖是由兩個部分組成的,其中一個是棍狀體,一個是螺旋狀體。

2、棍狀體從外到內越來越窄,整個圖形在做繞固定旋轉圓心的勻速圓周運動。

3、螺旋狀體也是在做繞固定旋轉圓心的勻速圓周運動。

4、螺旋狀體的旋轉角速度比棍狀體的旋轉角速度大。

具體實現邏輯

為了方便分析,我截取了一個靜態的瞬間:

那么怎么實現呢?

我們可以創建兩個函數,分別實現棍狀體和螺旋體,然后再在draw()函數里面去實現這兩個函數即可。

這是棍狀體的實現函數:

//圓周運動棍狀體繪制函數
function drawBoll(r, g, b, interval)

這是螺旋體的實現函數:

//圓周運動螺旋體的繪制函數
function drawBoll2( r, g, b, interval)

分兩個部分來講:

1、棍狀體:其實很簡單,我們可以看到靜止的棍狀體就是由14個小圓形組成的,由外到里半徑逐漸減小,然后顏色是赤橙黃綠青藍紫,赤橙黃綠青藍紫,每個圓形做的是繞固定圓心的勻速圓周運動。那么,我們的實現就是可以先做一個圓形的勻速圓周運動,其他的圓形,只需要修改一下旋轉半徑、圓形半徑以及顏色就可以了。至于圓周運動怎么實現,我會在后面講到,往后面看就可以了。

2、螺旋體:螺旋體其實也是一個圓形的重復變換得來的,可以看到的是,螺旋體的每個圓形都一樣大,不一樣的是什么呢?圓形的顏色和旋轉半徑,還有的就是他們初始就存在的弧度間隔。那么,我們要做的其實就是畫出一個勻速圓周運動的圓形,其它的就可以通過修改參數達到目的。

3、最后一步就是在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);
}

遇到的問題以及解決方案

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 = 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);//半圓
}

以上便是此次實驗的全部內容。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

最新評論

2019开奖结果