1. 程式人生 > >利用p5.js進行“運動”主題的繪畫創作

利用p5.js進行“運動”主題的繪畫創作

利用p5.js進行“運動”主題的繪畫創作

主題

用碼繪和手繪兩種方式創作“運動”主題的作品,對比二者在表現“動態”方面的異同。

碼繪

工具

p5.js

創作理念

因為喜歡Apple,當提到“運動”或者“動態”這個主題時,腦海中第一個冒出來的就是Siri動態的水波紋形狀,所以決定用p5.js實現Siri的動態效果。

Siri的實際效果如下:(右側為動態圖片,圖片源自網路)
Siri效果圖 圖片源自網路 Siri效果圖 圖片源自網路

實現過程
分析

Siri是由紅黃藍綠等多種顏色的波紋混合起來的,每種波紋都有較低的透明度,並且不同顏色的波紋重疊部分要顯示多種顏色混合的效果;波紋的運動方式比較平滑自然,要考慮使用比random()更自然的隨機數函式來實現;不同顏色的波紋起始位置也不同,所以初始化每種波紋的時候要注意錯開起始位置;

程式碼實現

sketch.js中的一些基本設定:

//定義幾個全域性變數
var w;
var h;
var mult = 75;
//初始函式
function setup() {
    createCanvas(windowWidth, windowHeight);
    background(51);
    }
//繪製函式
function draw() {
    background(51);
    push();
    blendMode(ADD);//混合顏色
    
    //紅
    stroke(255, 0, 255, 3);
    drawLine(w, h,
2000); //黃 stroke(255, 255, 0, 3);//stroke()四個引數:R、G、B、透明度 drawLine(w, h, 0); //藍 stroke(0, 0, 255, 3); drawLine(w, h, 3000); //綠 stroke(0, 255, 0, 3); drawLine(w, h, 4000); pop(); }

重點是drawLine()函式的編寫:

function drawLine(w, h, d) {
    //w為可以控制波紋寬度的變數;h為可以控制波紋高度的變數;d為每種顏色波紋的偏移量
for (var i = 0; i < w; i++) { var s = (noise(i / (w / 10), frameCount / 25 + d) * mult) - map(abs(i - w / 2), 0, w / 2, 0, mult) + h; strokeWeight(s); if (s > 1) line(i + (width / 2 - w / 2), height / 2, i + 1 + (width / 2 - w / 2), height / 2); }

drawLine()函式的具體思路是隨機的更改線條的寬度,在給定範圍內繪製線條;其中noise(i / (w / 10))中,替換“10“為其他數字可以改變波紋的顆粒感。

新增互動功能

為了能讓自己編寫的Siri繼續向現實中的Siri看齊,我給它增加了聲音互動的功能,即可以根據聲音的強度對波形和整體的大小做出相應的變換,這就要求在用網頁開啟的時候要開啟麥克風的許可權,獲取聲音的實現方式也很簡單,用到了p5.js中的AudioIn模組,具體程式碼如下(包括前面用過的程式碼):
[當一直點選滑鼠的時候就會進入聲音互動模式]

var mic;
var volume;
var w;
var h;
var mult = 75;

function setup() {
    createCanvas(windowWidth, windowHeight);
    background(51);
    mic = new p5.AudioIn();
    mic.start();//啟動麥克風

}

function draw() {
    background(51);
    push();
    blendMode(ADD);//混合顏色

    if (mouseIsPressed) {
        //w = width;//width為儲存畫布寬度的系統變數
        //h = 10;
        volumeLevel = mic.getLevel();
        w = map(volumeLevel, 0, 1, 0, 6000);//w為可以控制波紋寬度的變數
        h = map(volumeLevel, 0, 1, 0, 600);//h為可以控制博文高度的變數

    } else {
        w = width;//width為儲存畫布寬度的系統變數
        h = 10;

        //volumeLevel = mic.getLevel();
        //w = map(volumeLevel, 0, 1, 0, 6000);//w為可以控制波紋寬度的變數
        //h = map(volumeLevel, 0, 1, 0, 600);//h為可以控制博文高度的變數
    }
    //黃
    stroke(255, 255, 0, 3);//stroke()四個引數:R、G、B、透明度
    drawLine(w, h, 0);

    // stroke(0, 255, 255, 3);
    // drawLine(w, h, 1000);

    //紅
    stroke(255, 0, 255, 3);
    drawLine(w, h, 2000);

    //藍
    stroke(0, 0, 255, 3);
    drawLine(w, h, 3000);

    //綠
    stroke(0, 255, 0, 3);
    drawLine(w, h, 4000);

    pop();
}

function drawLine(w, h, d) {
    //w為可以控制波紋寬度的變數;h為可以控制博文高度的變數;d為每種顏色波紋的偏移量
    for (var i = 0; i < w; i++) {
        var s = (noise(i / (w / 10), frameCount / 25 + d) * mult) - map(abs(i - w / 2), 0, w / 2, 0, mult) + h;
        strokeWeight(s);
        if (s > 1) line(i + (width / 2 - w / 2), height / 2, i + 2 + (width / 2 - w / 2), height / 2);
    }

}
執行結果

(建議用Google Chrome瀏覽器開啟,並且允許開啟麥克風許可權)
正常模式下:

執行效果
這個執行結果和實際的Siri還是有些差距的,一開始以為實現起來會很簡單,但是上手了才知道里面的道道,再次佩服Apple牛逼!

聲音互動模式下:(按住滑鼠進入聲音互動模式)

聲音互動效果(背景音樂為Good Form-Nicki Minaj,播放音樂時需一直點選滑鼠,進入聲音互動模式)
Nicki Minaj

手繪

手繪效果圖(利用iPad繪製)手繪效果圖

創作體驗

1.對於我的選題手繪要比碼繪簡單,難點在於Siri的自然的波形效果如何用程式碼來實現,一開始用了random()函式生成隨機位置,這樣會出現非常不自然的效果,隨後選用了noise()函式,得到現在的效果。
2.每條波紋的透明度始終沒有除錯的特別理想,以至於呈現出一種混合在一起的感覺,實際的Siri則是每種波紋可以被區分的特別明顯,這也是以後需要改進的地方。
3.還得感嘆一下Apple的設計,我找了很多資料,但是沒找到具體介紹iOS12上Siri 的設計理念,不過應該會比較複雜。不知道是不是因為自己親自動手實現了一下,發現最近對Siri的好感度大大提升,雖然不如其他語音助手那麼“聰明”,但是愛Apple不需要理由!!!