1. 程式人生 > >P5.js:改進創意動態繪板

P5.js:改進創意動態繪板

在互動媒體課上接觸到p5.js這個東西后,我就一直在質疑它的實用性,p5.js用來畫圖並不是那麼的好用,但其和unity差不多的性質為動態繪圖提供了條件(p5.js使用setup()函式初始化,每秒呼叫draw()函式進行繪圖,unity使用start()初始化,每秒呼叫update()函式更新物體的狀態,兩者都有滑鼠、鍵盤等響應函式),接下來我會在西河某人使用p5.js建立的動態繪板的基礎上新增功能,實現使用p5.js來畫動態圖的效果。
西河某人的創意動態繪板連結:https://blog.csdn.net/qq_27534999/article/details/79427721?tdsourcetag=s_pcqq_aiomsg

首先我們來看西河某人制作的動態繪板
在這裡插入圖片描述
可以看到該動態繪板中有多種顏色和三種畫筆供選擇,功能方面,有類似於播放器的播放和停止來控制畫出來的筆跡是否運動,加速時間流逝(這個功能最好在暫停狀態下用),可以調節背景色(兩種),消除功能(選擇性的和全消都有)以及儲存功能。
功能方面作為一個畫板的基礎功能都有了,而且這個動態變換的筆跡非常有創意,接下來看程式碼結構(為改進做準備)。
整個js檔案程式碼量不多,總共分為2個按鈕實現函式(功能按鈕、顏色按鈕)、1個結點實現函式(即畫筆實現函式)、setup()和draw()以及滑鼠和鍵盤的響應函式。詳細程式碼可以去看原貼,下面只給出大概結構圖。
在這裡插入圖片描述
整個繪板的原理就是使用一個objs[]的列表儲存畫過的筆跡資訊,再通過draw()函式不斷的更新狀態、畫出,來達到動態的效果。我們想要新增自己所需要的功能和筆刷,只要在相應的函式中新增程式碼就行。

新增功能
調色盤(可以選擇多種顏色,不再受顏色限制),使用的是Flex ColorPicker控制元件,下載後按照官方文件的流程新增即可。
下載地址:https://webscripts.softpedia.com/script/Forms-and-Controls-C-C/Flexi-Color-Picker-70110.html
在這裡插入圖片描述

自定義背景顏色(不再受原畫板2中背景色的限制,根據所選顏色改變背景色)在這裡插入圖片描述
吸引結點(快捷鍵B),開啟後可以吸附結點,再次開啟後可以爆散結點,第三次開啟後恢復正常。
在這裡插入圖片描述
移動結點(畫出來的結點位置不滿意,移動就完事了)
在這裡插入圖片描述
新增風力(這個是為了後面的雪花和花瓣特效加的),第一按下新增向右的風,第二次向左,第三次無風。

新增筆刷
方塊(和前面的三角和圓形一樣,都是繞著結點位置旋轉,大小、顏色呈週期變換)
在這裡插入圖片描述
彈球(隨機給生成的圓形一個x軸速度和y軸上的速度,並使其撞到牆後速度反轉)
在這裡插入圖片描述
雪花(生成隨機大小雪花,並給其一個重力加速度g使其下落,雪花的尺寸越大,下落的越快,同時給它加一個左右飄蕩的效果,上文的風力按鈕就是為其和花瓣服務的,這裡動圖太大了不給傳)
在這裡插入圖片描述
五角星(類似於髮廊門口的那個柱子,有點無限迴圈的感覺,通過內部小五角星的尺寸週期重置實現)
在這裡插入圖片描述
花瓣(和雪花的原理一樣,把雪花換成花瓣就行)
在這裡插入圖片描述
煙花(連發像噴泉,先生成一堆圓,讓其的座標先上升,再給其隨機的x軸速度和y軸速度,使其呈現出爆散的效果,按空格可以改變顏色)
在這裡插入圖片描述

繪圖效果
在這裡插入圖片描述
在這裡插入圖片描述

與常規繪畫系統作比較

我以前用opengl+c++寫過一個簡單的繪畫系統,主要功能就是畫線,各種幾何形,選擇線寬、填充顏色這些基本操作,後來接觸到opencv後可以為這個系統新增各種影象上的處理功能。從技法上來看,兩者的差別不大,但用p5這個庫寫的動態繪畫系統更需要考慮畫面的整體動態感,通常我們是靠一些速度線、背景的模糊等技法來表現出畫面中的物體是在運動的,但動態繪板他畫出來的東西本身就是動的,不需要我們用一些額外的效果,但那種想象的感覺就會差很多。理念上的差距就不比多說了,一個是主攻靜態畫,以靜造動,一個主攻動態,以動造動。在創作體驗上著兩種畫板給我的感覺其實差不多,都比較難受,沒有用筆畫來的實在,呈現效果也是兩個極端,一個就是純粹的畫,一個是動畫。一幅畫的好畫可以給人以瞎想,令人賞心悅目,而一幅同樣好的動態畫則是把所有想表達的意思直接扔給你,效果也不差,比靜態的也更有衝擊力,但感覺上總是有點微妙。
通過這次動態畫板的改進,感覺p5.js還是有點意思的,起碼在寫自己想要的特效的時候和有趣。

最後附上js程式碼

//全域性變數
var objs = [];  //已畫圖形存放
var btns = [];  //已畫按鈕存放
var FPS = 60;   //幀率
var timepast = 0;   //時間記錄

//畫筆色
var R = 200;
var G = 150;
var B = 50;
//背景色
var bR = 0;
var bG = 0;
var bB = 50;

var eraserRange = 20;         //消除範圍大小
var timerRange = 50;          //時停範圍大小
var controlRange=20;
var brushType = "CIRCLE";     //當前畫筆模式
var pbrushType = "CIRCLE";    //之前畫筆模式
var isPlaying = true;         //是否暫停
var isMenuHide = false;       //選單是否隱藏
var wind=10;
var isWindR=false;
var isWindL=false;
var isBlackHOle=false;
var isreleased=false;
//功能按鈕函式
function FuncBtn(X, Y, W, H, CMD) {
    //位置
    this.x = X;
    this.y = Y;
    //大小
    this.w = W;
    this.h = H;
    //模式
    this.cmd = CMD;
  }

  //為FuncBtn新增isMouseInBtn()函式,判斷滑鼠是否在按鈕上
  FuncBtn.prototype.isMouseInBtn = function() {
    if (mouseX >= this.x && mouseX <= this.x + this.w &&
      mouseY >= this.y && mouseY <= this.y + this.h) {
      return true;
    } else {
      return false;
    }
  }
  //為FuncBtn新增clickBtn()函式,判斷滑鼠按下了哪個按鈕
  FuncBtn.prototype.clickBtn = function() {
    print("ClickBtn!");
    if (this.cmd == "sun") {
        //背景色改為白天,切換圖示改為黑夜
      bR = 200;
      bG = 255;
      bB = 255;
      this.cmd = "moon";
  
    } else if (this.cmd == "moon") {
        //背景色改為黑夜,切換圖片改為白天
      bR = 0;
      bG = 0;
      bB = 50;
      this.cmd = "setcolor";
    } else if (this.cmd == "setcolor") {
      //背景色改為黑夜,切換圖片改為白天
    bR = R;
    bG = G;
    bB = B;
    this.cmd = "sun";
  } else if (this.cmd == "pause") {
        //停止所有已有影象的運動,切換圖示改為播放
      isPlaying = false;
      for (var i = 0; i < objs.length; i++) {
        objs[i].isPlaying = false;
      }
      this.cmd = "play";
  
    } else if (this.cmd == "play") {
        //解除所有影象的運動限制,切換圖示改為暫停
      isPlaying = true;
      for (var i = 0; i < objs.length; i++) {
        objs[i].isPlaying = true;
      }
      this.cmd = "pause";
  
    } else if (this.cmd == "timer") {
        //畫筆型別改為時間畫筆
      brushType = "TIMER";
  
    } else if (this.cmd == "eraser") {
        //畫筆型別改為消除
      brushType = "ERASER";
    } else if (this.cmd == "clear") {
        //清空畫布
      objs = [];
   } else if (this.cmd == "save") {
       //儲存當前畫布的影象
       saveCanvas("Painting", "png")
    } else if (this.cmd == "wind") {
      //清空畫布
      if(isWindR==false&&isWindL==false){
        isWindR=true;
        wind=10;
      }
      else if(isWindR==true&&isWindL==false){
        isWindL=true;
        isWindR=false;
        wind=-10;
      }
      else if(isWindL==true&&isWindR==false)
        isWindL=false;
   } else if (this.cmd == "blackhole") {
    //清空畫布
      if(!isBlackHOle&&!isreleased)
        isBlackHOle=true;
      else if(isBlackHOle&&!isreleased){
        isBlackHOle=false;
        isreleased=true;
      }else{
        isreleased=false;
      }
    }else if (this.cmd == "control") {
      brushType = "CONTROL";
        
      }else if (this.cmd == "circle") {
        //畫筆由圓形切換至三角形
      brushType = "TRIANGLE";
      pbrushType = "CIRCLE";
      this.cmd = "triangle";
  
    } else if (this.cmd == "triangle") {
        //畫筆由三角形切換至直線
      brushType = "LINES";
      pbrushType = "TRIANGLE";
      this.cmd = "lines";
  
    } else if (this.cmd == "lines") {
       
      brushType = "CUBE";
      pbrushType = "LINES";
      this.cmd = "cube";
    }else if (this.cmd == "cube") {
  
    brushType = "BALL";
    pbrushType = "CUBE";
    this.cmd = "ball";
    }else if (this.cmd == "ball") {
  
    brushType = "SNOW";
    pbrushType = "BALL";
    this.cmd = "snow";
    }else if (this.cmd == "snow") {
 
    brushType = "CIRCLE";
    pbrushType = "SNOW";
    this.cmd = "circle";
    }
    else if (this.cmd == "star") {
   
    brushType = "STAR";
    this.cmd="sakura";
    }else if (this.cmd == "sakura") {
  
    brushType = "SAKURA";
    this.cmd="hanabi";
    }else if (this.cmd == "hanabi") {

    brushType = "HANABI";
    this.cmd="star";
    }
    
  }
//為FuncBtn新增displayBtn()函式,顯示按鈕
  FuncBtn.prototype.displayBtn = function() {
      //在指定位置畫出按鈕
    stroke(0);
    strokeWeight(1);
    fill(255, 255, 255);
    rect(this.x, this.y, this.w, this.h, 5);
  
  
    if (this.cmd == "sun") {
        //畫出太陽形狀
      fill(255, 50, 50);
      translate(this.x + this.w / 2, this.y + this.h / 2);
      for (var i = 0; i < 8; i++) {
        rotate(PI / 4.0);
        line(0, 0, 8, 8);
      }
      resetMatrix();
      ellipse(this.x + this.w / 2, this.y + this.h / 2, 15, 15);
  
  
    } else if (this.cmd == "moon") {
        //畫出月亮
      fill(255, 255, 50);
      translate(this.x + this.w / 2, this.y + this.h / 2);
      arc(-5, 0, 25, 25, PI + HALF_PI, HALF_PI, CHORD);
      resetMatrix();
  
    } else if (this.cmd == "setcolor") {
    fill(R, G, B);
    translate(this.x + this.w / 2, this.y + this.h / 2);
   rect(-7.5,-7.5,15,15);
    resetMatrix();

  } else if (this.cmd == "pause") {
        //畫出暫停形狀
      fill(0);
      translate(this.x + this.w / 2, this.y + this.h / 2);
      rectMode(CENTER);
      rect(-4, 0, 4, 15);
      rect(4, 0, 4, 15);
      rectMode(CORNER);
      resetMatrix();
    } else if (this.cmd == "play") {
      fill(0);
      translate(this.x + this.w / 2, this.y + this.h / 2);
      triangle(-2, -8, -2, 8, 6, 0);
      resetMatrix();
    } else if (this.cmd == "timer") {
  
      translate(this.x + this.w / 2, this.y + this.h / 2);
      noFill();
      ellipse(0, 0, 22, 22);
      ellipse(0, 0, 25, 25);
      fill(0);
      ellipse(0, 0, 3, 3);
      strokeWeight(2);
      line(0, 0, 5, 0);
      line(0, 0, 0, -7);
      resetMatrix();
    } else if (this.cmd == "control") {
  
      translate(this.x + this.w / 2, this.y + this.h / 2);
      fill(0,0,0);
      rect(-8.5, -2, 16, 4);
      rect(-2.5, -8, 4,16);
      triangle(-3,-8,3,-8,0,-12);
      triangle(-3,8,3,8,0,12);
      triangle(7.5,3.5,7.5,-2.5,12,0.5);
      triangle(-7.5,3.5,-7.5,-2.5,-12,0.5);

      resetMatrix();
    }else if (this.cmd == "eraser") {
      fill(0);
      noStroke();
      translate(this.x + this.w / 2, this.y + this.h / 2);
      textSize(25);
      textAlign(
            
           

相關推薦

P5.js:改進創意動態

在互動媒體課上接觸到p5.js這個東西后,我就一直在質疑它的實用性,p5.js用來畫圖並不是那麼的好用,但其和unity差不多的性質為動態繪圖提供了條件(p5.js使用setup()函式初始化,每秒呼叫draw()函式進行繪圖,unity使用start()初始化,每秒呼叫update()函式

p5.js可以做什麼 之 創意動態繪圖板

p5.js可以用來做什麼呢?在此給出我的課程作業,可是絞盡腦汁地挖掘p5.js的功能了~這是一個創意動態繪圖板。有三種創意畫筆,分別是點,三角,線。你可以隨意的進行創作,畫出來的東西可是會動的哦!自帶截圖儲存功能——請點選左下角的S圖示。還有神奇的時間控制畫筆——請點選左下角

P5.JS和碼兩種方式“運動”主題作品的對比研究

這次作業我針對的主題是“斐波那契螺旋線” 背景知識:斐波那契螺旋線,也稱“黃金螺旋”,是根據斐波那契數列畫出來的螺旋曲線,自然界中存在許多斐波那契螺旋線的圖案,是自然界最完美的經典黃金比例。作圖規則是在以斐波那契數為邊的正方形拼成的長方形中畫一個90度的扇形,連起來的弧線就是斐波那契螺旋線。在這

p5.js創作動態圖畫

本文主要談一下個人的一幅碼繪作品的創作過程和對碼繪與手繪優缺點的一些簡單的思考。 #創作工具 1、p5.js 2、photoshop #最終效果圖 飄落的雪花是這幅圖的動態元素 #創作過程 ##第一步,在photoshop裡畫出背景圖,即樹幹,因為樹幹用p5.js實在是無法畫出,好在p5提供

p5.js:手與碼,靜態

手繪和碼繪———靜態繪圖 碼繪圖: 手繪: 程式碼: function setup() { createCanvas(600, 1200); } function draw() { background(255,255,0); stroke(0,0,0);

VS碼(一):靜態圖繪製(碼使用P5.js)

首先讓我們來看看原圖: 出於想要簡單一點的考慮,手繪和碼繪就都不畫右下角的頭啦! 手繪: 先來看看手繪的效果圖吧(手殘ing…) emmmm大概是真的有點醜 碼繪 先來看看效果圖,然後再一部分一部分的來看繪圖過程吧! 還是挺像的對吧!!! 就是腦袋好像小

1.2 開始第一幅“碼”——Javascript、p5.js及HTML5簡介

Javascript、p5.js及HTML5辨析 在正式學習前,還有必要對我們要用到的幾個玩意進行理解和辨析,它們是 Javascript(簡稱JS), HTML5(簡稱H5), P5.js (簡稱

1.3 開始第一幅“碼”——開始使用p5.js,畫一個懵逼臉

下載P5.js並寫一段程式 下面我們就開始使用p5.js來畫點東西。 第一步,下載p5.js到本機。 到官網下載頁面(https://p5js.org/download/) ,從”Complete L

Js 添加動態修改id

input ace htm table tr roo net [0 oom html //HTML代碼 <table id="templateTable" > <tr>

fullPage.js—全屏動態滾動插件

https 模塊 ngs 參考 事件 style ive http slide 1.前言   全屏大圖、簡約風的網頁給人第一印象就是高端大氣上檔次,很多手機廠商的手機宣傳頁面都是采用了這種設計風格,蘋果的官網更是體現的淋漓盡致(栗子?)。   fullPage.js就是專門

js】setInterval動態改變定時器時間周期

-type IT set ble java val 如果 In TE setInterval動態改變定時器時間周期 一、目標: setInterval初始時間間隔為500ms,動態更改為2s/5s/暫停。 二、效果(//gif,如果看到的是靜態的png,你該去換臺能看動圖的

CSS或JS實現gif動態圖片的停止與播放

 by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wordpress/?p=5081  一、 對於習慣性刷微博的我,總時不時

js中 ajax動態新增節點無法觸發點選事件

在寫ajax載入資料的時候發現,後面新增進來的demo節點元素,失去了之前的點選事件。 其實最簡單的方法就是直接在標籤中寫onclick="",但是這樣寫有些場景的是實現不了的,最好的方式還是通過給類名繫結一個click事件。 方法一:使用live: live()函式會給被選的元素繫結上一個或者多個事件

artTemplate js模板引擎動態給html賦值

html放到$("#area").append(html);之前,否則文件流獲取不到#area <table width="90%" class="table" cellspacing="0" cellpadding="0"> <thead> <tr> <th

arcgis api for js - 圖上標及測量

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewp

【前端】p5.js建立的Canvas儲存到localStorage

// it should be stored in localStorage function saveMyCanvas(e) { console.log('Saving...') // saveCanvas(canvas, dishName, 'png') // this way

【浮動導航欄的定位】JS監聽動態頁面元素距離底部距離,並修改定位樣式

需求:一個定位position:fixed;的選單欄,移動到底部時依然存在,影響頁面美觀,我們希望當滾輪移到頁面末尾時選單欄更換為絕對定位。 解決:JS沒有直接獲取元素距離頁面底部距離的函式,因此可利用全文高度-當前高度取得差值來間接判斷。 <!DOCTYPE html

selenium+chromedrive 爬取js載入的動態網頁(下拉才能顯示內容)

from selenium import webdriver from selenium.webdriver.common.keys import Keys #呼叫鍵盤操作 from selenium.webdriver.chrome.options import Opt

JS實現網頁動態時鐘

問題 我們時常在網頁上能看到動態的時間顯示,那麼是如何實現的呢? 解決方案 原理是利用js的定時效果,每隔0.5s呼叫一次獲取時間的函式,然後進行渲染到需要放置的地方。程式碼如下:

使用p5.js畫出動畫滑稽碰撞圖

使用p5.js做了一個動態碰撞的滑稽笑臉,效果如圖 首先是定義了一個畫滑稽的函式,其中引數分別是滑稽的橫縱座標、大小以及眼珠的朝向,L可取-1和1兩個值,-1向右,1向左。臉用了兩個填充的圓重疊(也可一個圓加邊框)。嘴和眼睛以及眉毛是分別畫兩個圓弧相重疊而成。