日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

人性化的绘画界面设计-屁民科普

發布時間:2023/12/20 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 人性化的绘画界面设计-屁民科普 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

人性化的繪畫界面設計-屁民科普

寫在前面:感覺對于這次的繪畫系統,我和其他同學不同,他們比較專注于不同筆的效果的比較,我在這里是更專注于用戶進行繪畫時的交互體驗,繪畫的娛樂性和創新性體驗較少。這里面的面板控件都是自己畫的233.

設計思路

(1)由動態和交互,我想把第二次的作業結合進去,作為我這次大作業的UI開始界面。相當于將繪畫系統,當作適合人們玩的小游戲的樣式。
(2)根據老師上課講的內容,忽然想到可以做成一個像素風的繪畫形式。可以自己選擇顏色,有顏色面板。
(3)在完成第(2)步以后,我在想要做點更有意思的東西,能夠將自己的繪制完成的圖畫讓他有某種效果。因為前幾天下雪,所以想做一圣誕特別版。
(4)之前看同學做了有點萌的開關還有音樂可視化的下雪的季節,自己也想讓界面變的更可愛一點,所以自己也嘗試了一下這兩種我比較喜歡的作品,放入我的繪畫界面中。

創作步驟

繪制畫布

首先,我要有一個網格作為畫紙,相當于畫布的界面。
部分代碼:
聲明部分:

int bar_num=5;//bar color num float bar_length=width;//bar width and length float box_length=bar_length/bar_num;//box length and width PVector p[]=new PVector[1000]; float p_y[]=new float[1000];

在setup()當中初始化:

for (int i=0;i<=1000-1;i++){p[i]=new PVector(box_length*i+box_length/2,box_length);}for (int i=0;i<=1000-1;i++){p_y[i]=p[i].y*i;}

繪制畫布部分:

//set a canva void drawcanva() {for (int j=0;j<=1000-1;j++){ for (int i=0;i<=1000-1;i++){fill(255,255,255);stroke(157,170,173,30);rect(p[i].x,p_y[j],box_length,box_length);}} }

效果:

繪制調色板

第二步就是要有調色板了,為了好看,我在調色板下畫了一個半透明的矩形,生成調色板也非常簡單,定好了畫板板面的位置也就是選好了第一個格子的位置,定好了畫板的大小,花瓣中的格子的寬度就和畫布的格子大小一樣。寫一個循環,將所有的格子位置在setup中存儲起來,將格子要填充的顏色也存儲起來。格子的位置和填充的顏色都在數組中。
于是就形成了下面這種效果,值得一說的就是文字,我這里找了幾種好看的文字,選定與主題最相符的格式就?了。

PFont myfont;//create font

setup()函數中選擇了一種字體

// Herculanum HiraginoSans-W0 MarkerFelt-Thinmyfont=createFont("NanumBrush",20);//set fonttextFont(myfont); fill(0,0,0);//text colortextSize(20);text("Palette",35,22);//add context and pos

那我是怎么選擇這種字體的呢,那字體有什么屬性可以通過代碼調節呢
可以參考:processing字體

核心部分:增加調色板交互效果

獲取調色板的顏色

第三步:也是這里最核心的,就是點擊調色板,獲取調色板的顏色,再點擊畫布,在畫布上顯示我選擇的顏色,并且繪制。
首先先說說怎么獲取顏色,processing自帶了獲取顏色的函數,非常簡單也非常方便。
當然這些要建立在點擊事件當中,我在編寫的時候,想過用什么樣的交互方式會更加便于用戶去選取顏色并且繪制,而且代碼還比較容易編寫。
那就選擇不同的按鍵來代表不同的操作!
這里鼠標左鍵選取顏色,右鍵繪制,有點類似于blender的操作。
以下代碼在mousePressed()中

if (mouseButton==LEFT){if (mo==0){ mo=1;}int imgC=get(mouseX,mouseY);//get rightnow posR=(imgC>>16)&0xFF;G=(imgC>>8)&0xFF;B=imgC&0xFF;}

特別的意外創新點
這里的rgb獲取到了左鍵取到的顏色,而且這也帶來一個特別方便的地方,也是在我編寫之后發現的。因為畫布是白色的,所以我如果畫到了錯誤的地方,左鍵空白處,再右鍵錯誤的地方,就可以實現橡皮擦的功能,我覺得我這里是創新點!哈哈

將獲取到的顏色繪制到調色板上鼠標點擊的指定位置

我這里判斷了mouseX mouseY所處的位置,以一個方格為范圍,如果鼠標位于該方格內,則將這個方格用剛獲取的顏色填充。
而這里面的難點在于哪里呢?
我如何保存方格所在的位置,來繪制方格。因為鼠標可能點擊方格內部的任何區域,而我要保存的僅僅是方格的左上角點的坐標,至于方格的大小我們已經在setup的時候確定好了。
解決的方法是,首先做一步判斷,鼠標點擊的位置位于哪個方格內,那我返回該方格的坐標就好了。因為之前在繪制畫布的時候,我們已經存儲了所有格子的坐標,放在了p[]數組里。
那就直接暴力遍歷,我們就能找到目標格子索引及坐標。
在右鍵操作中添加如下代碼:其中fill()填充的顏色就是我們剛才獲取到的顏色。

if(mouseButton==RIGHT){noStroke();fill(R,G,B);int k=0;for(int i=0;i<=1000-1;i++){ for(int j=0;j<=1000-1;j++){if (mouseX>=p[i].x&&mouseX<=p[i].x+box_length&&mouseY>=p_y[j]&&mouseY<=p_y[j]+box_length&&k<=1000-1){rect(p[i].x,p_y[j],box_length,box_length);index_cx[k]=p[i].x;index_cy[k]=p_y[j];k=k+1;}}}}

嘗試有點萌的開關挑戰

我這里看了其他同學的博文,根據上面的提示自己編寫了一下,但是對于刷新變成橢圓的那個地方并沒有去實現。
我這里也為了配合整體效果,選擇了半透明的樣式,比較淡一點的顏色。

開關的繪制這里就不放了。
因為要每一幀都繪制,所以開關的動畫要寫在draw當中,開關的移動我沒有用到鼠標的點擊,這里是如果鼠標放置在這個圓形區域以內,則判定為要進行開關操作。

在on時的眨眼,在off時的眨眼

//OFF void animation() {for (int i=1;i<=80;i++){pushMatrix();translate(i,0);fill(255,255,255);//draw buttomellipse(25,width/5+10,25,25);fill(173,158,157,90);ellipse(25-5,width/5+10,8,3+7*abs(sin(second()*8)));ellipse(25+5,width/5+10,8,3+7*abs(sin(second()*8)));popMatrix();} } //ON void animation1() {for (int i=1;i<=80;i++){pushMatrix();translate(-i,0);fill(255,255,255);//draw buttomellipse(105,width/5+10,25,25);fill(173,158,157,90);ellipse(105-5,width/5+10,8,3+7*abs(sin(second()*8)));ellipse(105+5,width/5+10,8,3+7*abs(sin(second()*8)));popMatrix();} }

因為是截圖所以大小會有點問題,看上去怪怪得,實際上我這個開關有兩種眨眼睛的方式,一種是完全閉上,然后睜開,另一種是半閉然后睜開。不論開關在左邊還是在右邊都有眨眼睛的效果,有點呼吸的活的感覺。

//switch animation OFF wink eyesif ((mouseX-25)*(mouseX-25)+(mouseY-width/5-10)*(mouseY-width/5-10)<=25*25&&tag==0){animation();tag=1;// changeclr();}// move();//switch animation ON wink eyesif ((mouseX-105)*(mouseX-105)+(mouseY-width/5-10)*(mouseY-width/5-10)<=25*25&&tag==1){animation1();clearcanva();tag=0;// move();}

添加開關操作

這里我剛開始編寫的時候,一直都沒太想好讓我的圖像有什么樣子的動態的效果,后來想到了要加入音樂,于是我就增加了透明度和下雪的效果。

因此在此之前先說說音樂可視化

音樂可視化

做一個類似于cd的播放器,網上有很多音樂可視化的例子,我想做成的效果圖,和我實際做出來的還是有差距的。
想做個這個,結果做成了另外一種樣子233

import processing.sound.*; float ampvalue=0;//this will be our height's parameter float lucency; SoundFile file; AudioIn in; // AudioIn let's you grab the audio input from your soundcard Amplitude amp;// anaylis the sounds

在文件夾下建立一個data文件,將音頻放入。
在網易云上2塊錢買的音樂有8分鐘,是mp4格式,有幾百兆,因為文件太大了,所以無法導入,一直報錯,一開始不知道是因為音頻文件過大的原因,后來我用蘋果的iTunes按照網上的步驟截取了一部分,就能讀取了,并且查閱了processing官方文檔,發現wav格式的音頻格式加載會更快,于是轉換了格式。這里為road.wav
蘋果剪輯音樂并保存為其他格式方法:
https://jingyan.baidu.com/album/ce4366494223ff3773afd391.html?picindex=5
初始化:

//cd playerfile = new SoundFile(this, "road.wav");//file pathin = new AudioIn(this,0); // Starts the input streamamp = new Amplitude(this); in.start(); // Starts the input streamamp.input(in); // Defines the audio input source of the amplitude analyzefor (int i=0;i<=120-1;i++){cd_angle=cd_angle+3;cd_bar[i]=new PVector(cd_x+(cd_r-65)*cos(PI*cd_angle/180),cd_y+(cd_r-65 )*sin(PI*cd_angle/180));}

我將cd周圍畫出細小的豎線,他可以根據聲卡中音量來調節自身的透明度值。
繪制豎線:

void drawstring() {ampvalue = amp.analyze();//this value will be between 0~1strokeWeight(1);lucency = ampvalue*100000;stroke(255,226,229,lucency); // stroke(172,123,255,lucency);// stroke(172,123,255,90);cd_angle=0;for (int i=0;i<=120-1;i++){cd_angle=cd_angle+3;line(cd_bar[i].x,cd_bar[i].y,cd_bar[i].x+random(20)*noise(ampvalue*500)*cos(PI*cd_angle/180),cd_bar[i].y+random(20)*noise(ampvalue*500)*sin(PI*cd_angle/180));//line(cd_bar[i].x,cd_bar[i].y,cd_bar[i].x+10*noise(ampvalue*100)*cos(PI*cd_angle/180),cd_bar[i].y+ampvalue*100*sin(PI*cd_angle/180));// line(cd_bar[i].x,cd_bar[i].y,cd_bar[i].x+15*cos(PI*cd_angle/180),cd_bar[i].y+15*sin(PI*cd_angle/180));} } void playmusic() {file.play(); }


另外值得一提的是,在processing幫助文檔當中,有介紹音樂的播放,如果鼠標點擊按鈕,則音樂暫停,重新點擊,則音樂會接著剛才暫停的地方繼續播放。

開關開啟之后增加效果

(1)添加雪花效果:
代碼如下,雪花效果就非常簡單了,其實我覺得這里面最麻煩的就是要進行判斷,還有把代碼放在哪個地方是符合我的想法的。
https://blog.csdn.net/qq_39097425/article/details/85016837

//when press OFF buttom get snow void snowdown() {int i=0;while (i<=snow_identity-1){noStroke();fill(255,211,235);ellipse(snow_x[i],snow_y[i],snow_r[i],snow_r[i]);snow_y[i]=snow_y[i]+snow_speed[i];if (snow_y[i]>=570)// if out of boundary{snow_y[i]=105;//get to the start edge}i=i+1;} }

雪花效果: 什么都不添加,畫布會呈現白色,并且有粉色的雪球效果

(2)改變填充色塊的顏色
細心的朋友可能會注意到,我并不是把整張屏幕size全部作為我的畫布,而是自己又框選了邊界,重新設置了一下畫布:

那我這樣做的道理是什么呢?
因為我要獲取用戶繪制的點的位置,以及他們的顏色,所以我要找畫布中顏色不為255的點。但這樣有個問題,如果我的畫布是全部界面,我在開始繪制的面板,cd,開關,他們都是有顏色的。這樣會影響我的判斷,所以我在這里選取了一塊空白的區域。
接著對這個區域進行遍歷:
尋找畫布中顏色不是255的點,我這里尋找的點是位于格子中心位置,因為考慮到邊界處會有畫布的邊界線,會影響顏色的判斷。所以我這里選取的格子中心。
下面這個代碼是遍歷畫布:

//collect the fill box index //width 24 length 24 //150,100 630,580 box_length=20 //width*3/5+150,100+height*4/5 void searchfill() {int index=0;for (int i=0;i<=1000-1;i++){for (int j=0;j<=1000-1;j++){ if ((p[i].x>150)&&(p[i].x<=630)&&(p_y[j]>=100)&&(p_y[j]<=570)){ temp_x=int(p[i].x+box_length/2);temp_y=int(p_y[j]+box_length/2);// println(temp_x,temp_y);temp_img=get(temp_x,temp_y);temp_R=(temp_img>>16)&0xFF;temp_G=(temp_img>>8)&0xFF;temp_B=temp_img&0xFF;if((temp_R!=255)&&(temp_G!=255)&&(temp_B!=255)&&index<=575){fillimg[index]=new PVector(temp_x-box_length/2,temp_y-box_length/2);R_tmp[index]=temp_R;G_tmp[index]=temp_G;B_tmp[index]=temp_B;index=index+1;}}}} } //change the fill image color through the music void changeclr() {fill(255,255,255);rect(150,100,width*3/5,height*4/5);ampvalue = amp.analyze();//this value will be between 0~1lucency = ampvalue*100000;for (int k=0;k<=575;k++){ fill(R_tmp[k],G_tmp[k],B_tmp[k],lucency);rect(fillimg[k].x,fillimg[k].y,box_length,box_length);} }

最后結合我之前做的ui界面

我在這之后還做了改動,讓他有景深的效果:
前面深顏色的樹移動的速度快,后面淺顏色的因為距離遠,所以要稍微小一些,移動的速度我也調節到了最慢。
下面其實是路但是很多人都說這個看起來像云,這些是由四個橢圓組成的。想要做出來的效果就是一直往前奔跑的感覺。
在做界面跳轉的時候,有點懵,因為我一開始把畫布,paintUI中要用東西都寫到了setup中,setup只能顯示一次,所以不知道要怎么實現跳轉。后來把繪制的部分單獨拿出來,寫個函數。
這是看了這個例子后才后知后覺。
開始界面的UI繪制:

void startUI() {background(238,239,255);noStroke();draw_tree();draw_leaf();draw_leaves();draw_hill();draw_road();draw_wind();fill(#E3E3E3);textAlign(CENTER);textSize(44);fill(#EE6AA7);// fill( 255,255,255);text("START",0.5*width,height-50);//add context and pos }

draw()界面跳轉的標簽設置,以及更新動畫眨眼睛,更新cd中的string等主要操作。

void draw() {//the start UIif (mo==0){startUI(); //switch buttom// tag=0 OFF }if(mo==1){ paintUI();mo=2;}if (mo==2){ if(tag==0){ fill(255,255,255);//draw buttomellipse(25,width/5+10,25,25);fill(173,158,157,90);ellipse(25-5,width/5+10,8,3+7*abs(sin(second()*8)));ellipse(25+5,width/5+10,8,3+7*abs(sin(second()*8)));searchfill();}//tag=1 ONif(tag==1){ fill(255,255,255);//draw buttomellipse(105,width/5+10,25,25);fill(173,158,157,90);ellipse(105-5,width/5+10,8,3+7*abs(sin(second()*8)));ellipse(105+5,width/5+10,8,3+7*abs(sin(second()*8)));changeclr();snowdown();}//switch animation OFF wink eyesif ((mouseX-25)*(mouseX-25)+(mouseY-width/5-10)*(mouseY-width/5-10)<=25*25&&tag==0){animation();tag=1;// changeclr();}// move();//switch animation ON wink eyesif ((mouseX-105)*(mouseX-105)+(mouseY-width/5-10)*(mouseY-width/5-10)<=25*25&&tag==1){animation1();clearcanva();tag=0;// move();} drawcdall();/* for (int i=0;i<=3;i++){println(fillimg[i].x,fillimg[i].y);}*/ } }

繪圖部分的效果展示

我畫了幾張丑圖,給你們看看~


看一下效果動圖:
沒有音樂就非常可惜了,配合著音樂在這樣的氛圍中,繪制屬于你自己的圖畫,豈不是一件美事233
![在這里插入圖片描述](https://img-blog.csdnimg.cn/2018123012362385.gif

總結

以上是生活随笔為你收集整理的人性化的绘画界面设计-屁民科普的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。