使用p5.js實現(xiàn)動態(tài)GIF圖片臨摹重現(xiàn)
前言
根據(jù)互動媒體技術(shù)老師的實驗要求,臨摹了一張GIF動態(tài)圖,使用p5.js進(jìn)行重現(xiàn)。
博客里面會有實現(xiàn)邏輯以及實現(xiàn)代碼,在最后還會有一張自己實現(xiàn)的擴(kuò)展圖。
原圖
實現(xiàn)步驟
規(guī)律總結(jié)
1、觀察圖片可以看到,整個圖是由兩個部分組成的,其中一個是棍狀體,一個是螺旋狀體。
2、棍狀體從外到內(nèi)越來越窄,整個圖形在做繞固定旋轉(zhuǎn)圓心的勻速圓周運(yùn)動。
3、螺旋狀體也是在做繞固定旋轉(zhuǎn)圓心的勻速圓周運(yùn)動。
4、螺旋狀體的旋轉(zhuǎn)角速度比棍狀體的旋轉(zhuǎn)角速度大。
具體實現(xiàn)邏輯
為了方便分析,我截取了一個靜態(tài)的瞬間:
那么怎么實現(xiàn)呢?
我們可以創(chuàng)建兩個函數(shù),分別實現(xiàn)棍狀體和螺旋體,然后再在draw()函數(shù)里面去實現(xiàn)這兩個函數(shù)即可。
這是棍狀體的實現(xiàn)函數(shù):
//圓周運(yùn)動棍狀體繪制函數(shù) function drawBoll(r, g, b, interval)
這是螺旋體的實現(xiàn)函數(shù):
//圓周運(yùn)動螺旋體的繪制函數(shù) function drawBoll2( r, g, b, interval)
分兩個部分來講:
1、棍狀體:其實很簡單,我們可以看到靜止的棍狀體就是由14個小圓形組成的,由外到里半徑逐漸減小,然后顏色是赤橙黃綠青藍(lán)紫,赤橙黃綠青藍(lán)紫,每個圓形做的是繞固定圓心的勻速圓周運(yùn)動。那么,我們的實現(xiàn)就是可以先做一個圓形的勻速圓周運(yùn)動,其他的圓形,只需要修改一下旋轉(zhuǎn)半徑、圓形半徑以及顏色就可以了。至于圓周運(yùn)動怎么實現(xiàn),我會在后面講到,往后面看就可以了。
2、螺旋體:螺旋體其實也是一個圓形的重復(fù)變換得來的,可以看到的是,螺旋體的每個圓形都一樣大,不一樣的是什么呢?圓形的顏色和旋轉(zhuǎn)半徑,還有的就是他們初始就存在的弧度間隔。那么,我們要做的其實就是畫出一個勻速圓周運(yùn)動的圓形,其它的就可以通過修改參數(shù)達(dá)到目的。
3、最后一步就是在draw()函數(shù)中去實現(xiàn),我使用了一個for循環(huán)去實現(xiàn):
for (var i =1;i < 15; i++) // for循環(huán)實現(xiàn)變化的重復(fù) { //其中前三個參數(shù)是顏色的RGB值,最后一個參數(shù)i實現(xiàn)各個圓形之間的變化 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); }
代碼實現(xiàn)
關(guān)于這個程序,具體的p5.js代碼在這里:
//準(zhǔn)備畫板 function setup() { createCanvas(1000, 1000); } //開始作畫 function draw() { background(50); //背景顏色 for (var i =1;i < 15; i++) // for循環(huán)實現(xiàn)變化的重復(fù) { //其中前三個參數(shù)是顏色的RGB值,最后一個參數(shù)i實現(xiàn)各個圓形之間的變化 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); } } //圓周運(yùn)動棍狀體繪制函數(shù) function drawBoll(r, g, b, interval){ fill(r, g, b); var x = 500; //圓周運(yùn)動圓心的x坐標(biāo) var y = 500; //圓周運(yùn)動圓心的y坐標(biāo) var t = millis() / 3; // 控制旋轉(zhuǎn)速度的參數(shù) var xChange //圓周運(yùn)動x坐標(biāo)變化值 var yChange; //圓周運(yùn)動y坐標(biāo)變化值 var radius = interval * 15;//圓周運(yùn)動的半徑 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); } //圓周運(yùn)動螺旋體的繪制函數(shù) function drawBoll2( r, g, b, interval){ fill(r, g, b); var x = 500; //圓周運(yùn)動圓心的x坐標(biāo) var y = 500; //圓周運(yùn)動圓心的y坐標(biāo) var t = millis() / 1 + interval * 24; //24是兩個小球之間間隔的角度 var xChange //圓周運(yùn)動x坐標(biāo)變化值 var yChange; //圓周運(yùn)動y坐標(biāo)變化值 var radius = interval * 15;//圓周運(yùn)動的半徑 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、怎樣實現(xiàn)勻速圓周運(yùn)動?
接著上面說的,怎么實現(xiàn)勻速圓周運(yùn)動呢?
關(guān)于勻速圓周運(yùn)動,要實現(xiàn)的話:
首先,我們要知道他的旋轉(zhuǎn)半徑、旋轉(zhuǎn)圓心以及旋轉(zhuǎn)角速度。
其次,就是根據(jù)這些參數(shù),利用三角函數(shù),去計算出運(yùn)動的點的坐標(biāo)與旋轉(zhuǎn)圓心坐標(biāo)之間的差。
最后,就是將圓心坐標(biāo)補(bǔ)上這個計算出來的差,算出圓周運(yùn)動的各個點的坐標(biāo),以這些坐標(biāo)為圓心畫小圓,這些小圓就是我們要的圓形了。
勻速圓周運(yùn)動具體代碼:
var x = 500; //圓周運(yùn)動圓心的x坐標(biāo) var y = 500; //圓周運(yùn)動圓心的y坐標(biāo) var t = millis() / 3; // 控制旋轉(zhuǎn)速度的參數(shù) var xChange //圓周運(yùn)動x坐標(biāo)變化值 var yChange; //圓周運(yùn)動y坐標(biāo)變化值 var radius = interval * 15;//圓周運(yùn)動的半徑 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中寫函數(shù)的時候,括號里面的形參不需要聲明,舉個例子吧:
function drawBoll(r, g, b, interval)
上面這個就是正確的示例,下面是錯誤的例子:
function drawBoll(var r, var g, var b, var interval)
也就是說,形參里面不可以寫var聲明,不然會報錯。
還有一個就是p5.js中聲明變量用 var 就可以了,不要用int, char, string這些。
結(jié)果圖
擴(kuò)展作品
擴(kuò)展作品介紹
這是我的擴(kuò)展作品,是一個時鐘,加上一個鼠標(biāo)的交互
中間的分別是時針,分針,秒針,他們的實現(xiàn)就和上面那個gif圖中的棍狀體的實現(xiàn)一樣,改了一下角速度和圓形大小。改了 參數(shù)而已,我就不再細(xì)說。
主要來介紹一下這個簡單的鼠標(biāo)交互事件。
關(guān)于交互的話,可以看到的是這個律動的心是由兩個部分組成的。
一個部分是外圍的律動的粉色圓形,通過ellipse函數(shù),這個圓形的圓心坐標(biāo)就是當(dāng)前鼠標(biāo)的坐標(biāo),寬和高是變化的,我們可以設(shè)置一個變量size,size不斷變大,到達(dá)臨界值就減少,然后繼續(xù)增大就可以了,代碼如下:
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);//半圓
具體代碼實現(xiàn)
//準(zhǔn)備畫板 function setup() { createCanvas(1000, 1000); } //開始作畫 function draw() { background(50); //背景顏色 for (var i =1;i < 15; i++) // for循環(huán)實現(xiàn)變化的重復(fù) { //其中前三個參數(shù)是顏色的RGB值,最后一個參數(shù)i實現(xiàn)各個圓形之間的變化 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); } //時針繪制函數(shù) function drawBoll(r, g, b, interval){ fill(r, g, b); var x = 500; //圓周運(yùn)動圓心的x坐標(biāo) var y = 500; //圓周運(yùn)動圓心的y坐標(biāo) var t = 6 * millis() / 3600000; // 控制旋轉(zhuǎn)速度的參數(shù) var xChange //圓周運(yùn)動x坐標(biāo)變化值 var yChange; //圓周運(yùn)動y坐標(biāo)變化值 var radius = interval * 15;//圓周運(yùn)動的半徑 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); } //分針繪制函數(shù) function drawBoll2( r, g, b, interval){ fill(r, g, b); var x = 500; //圓周運(yùn)動圓心的x坐標(biāo) var y = 500; //圓周運(yùn)動圓心的y坐標(biāo) var t = 6 * millis() / 60000; // 控制旋轉(zhuǎn)速度的參數(shù) var xChange //圓周運(yùn)動x坐標(biāo)變化值 var yChange; //圓周運(yùn)動y坐標(biāo)變化值 var radius = interval * 15;//圓周運(yùn)動的半徑 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); } //秒針繪制函數(shù) function drawBoll3( r, g, b, interval){ fill(r, g, b); var x = 500; //圓周運(yùn)動圓心的x坐標(biāo) var y = 500; //圓周運(yùn)動圓心的y坐標(biāo) var t = 6 * millis() / 1000; // 控制旋轉(zhuǎn)速度的參數(shù) var xChange //圓周運(yùn)動x坐標(biāo)變化值 var yChange; //圓周運(yùn)動y坐標(biāo)變化值 var radius = interval * 15;//圓周運(yùn)動的半徑 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; // 實現(xiàn)鼠標(biāo)交互的函數(shù)(律動的愛心) 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);//半圓 }
以上便是此次實驗的全部內(nèi)容。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript使用ZeroClipboard操作剪切板
這篇文章主要為大家詳細(xì)介紹了JavaScript使用ZeroClipboard操作剪切板的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05