Unity自定义UI组件(八) 颜色拾取器(上)
前言
unity中我們在選取顏色時unity會自動彈出顏色拾取器,通過操作選取自己想要的顏色,但是這個組建在我們自己的應(yīng)用中無法使用,我們可以通過Windows的組建,但是unity 中調(diào)用總是有很多的問題,所以博主就自己開發(fā)了一個顏色拾取器,方便使用。我們將完美還原Unity自帶顏色拾取器的全部功能,內(nèi)容較多,分為兩篇博客講解
組件特點
- 無需任何asset
- 導(dǎo)入代碼即可生成
- 調(diào)用接口方便
實現(xiàn)效果
普通狀態(tài)
其他調(diào)色板模式
HSV模式
截圖模式
主要內(nèi)容
通過博主之前七篇UI組件的講解,這里不再對基礎(chǔ)的代碼進(jìn)行講解,我們講解一下其中的重點內(nèi)容。其中的吸管圖標(biāo),滑動條的圖標(biāo)和按鈕圖標(biāo)都是直接利用代碼繪制,詳細(xì)見代碼注解。
- 顏色原理與顏色模式
- 漸變色堆疊,實現(xiàn)多種調(diào)色板
- 實現(xiàn)放大部分區(qū)域,吸取顏色
詳細(xì)講解
1.顏色原理與顏色模式
1.1 色彩原理:
Unity中顏色由R、G、B、A(紅、綠、藍(lán)、透明)四個通道組成,所有的顏色都是通過這四個通道混合而成。
1.2 顏色模式
顏色模式是將顏色表現(xiàn)為數(shù)學(xué)形式的模式,分為RGB模式,CMYK模式(用于打印),HSV模式,灰度模式,位圖模式等,這里我們以顏色拾取器設(shè)計的RGB和HSV來講解一下。
1.2.1 RGB模式
- RGB就是常說的三原色,R代表Red(紅色),G代表Green(綠色),B代表Blue(藍(lán)色)
- 自然界中肉眼所能看到的任何色彩都可以由這三種色彩混合疊加而成,因此也稱為加色模式
- 計算機(jī)定義顏色時R、G、 B三種成分的取值范圍是0-255,0表示沒有刺激量,255表示刺激量達(dá)最大值
- R、G、B均為255時就合成了白光,R、G、B均為0時就形成了黑色
- 在顯示屏上顯示顏色定義時,往往采用這種模式,圖像如用于電視、幻燈片、網(wǎng)絡(luò)、多媒體,一般使用RGB模
1.2.2 HSV模式
- HSV(Hue, Saturation, Value)是根據(jù)顏色的直觀特性由A. R. Smith在1978年創(chuàng)建的一種顏色空間
- 這個模型中顏色的參數(shù)分別是:色調(diào)(H),飽和度(S),明度(V)
色調(diào)H
用角度度量,取值范圍為0°~360°,從紅色開始按逆時針方向計算,紅色為0°,綠色為120°,藍(lán)色為240°。它們的補(bǔ)色是:黃色為60°,青色為180°,品紅為300°
飽和度S
飽和度S表示顏色接近光譜色的程度。一種顏色,可以看成是某種光譜色與白色混合的結(jié)果。其中光譜色所占的比例愈大,顏色接近光譜色的程度就愈高,顏色的飽和度也就愈高。飽和度高,顏色則深而艷。光譜色的白光成分為0,飽和度達(dá)到最高。通常取值范圍為0%~100%,值越大,顏色越飽和
明度V
明度表示顏色明亮的程度,對于光源色,明度值與發(fā)光體的光亮度有關(guān);對于物體色,此值和物體的透射比或反射比有關(guān)。通常取值范圍為0%(黑)到100%(白)
以上內(nèi)容做一個了解,在Unity中我們這里理解,RGB模式是R、G、B三個基本色來構(gòu)成,而HSV是由H 色調(diào)、S 飽和度、V 明度(亮度)來組合構(gòu)成。
1.3 調(diào)色板模式
因為顏色總是由三個分量組成,所有在二維的空間中,我們用兩個分量組成的面和另一個分量來決定的,所以我們可以按照這個單獨的分量來命名
- Hue模式
- Brightness模式
- Saturation模式
- Red模式
- Green模式
- Blue模式
2.漸變色堆疊,實現(xiàn)多種調(diào)色板
關(guān)于顏色漸變的內(nèi)容我們在上一篇Unity自定義UI組件 漸變工具中具體講解過,這里我們只討論如何實現(xiàn)多種顏色的疊加
2.1 類型一
2.1.1 實現(xiàn)原理
- 1.利用ColoredTape調(diào)出七色漸變圖
- a. 設(shè)置TapeDirection為Horizontal方向
- b. 設(shè)置Colors尺寸為7,依次七種顏色值
- a. 設(shè)置TapeDirection為Horizontal方向
- 2.再新建一個ColoredTape給七色漸變圖蒙版
- a. 設(shè)置TapeDirection為Vertical方向
- b. 設(shè)置Colors尺寸為2,傳入兩種顏色值
- a. 設(shè)置TapeDirection為Vertical方向
2.1.2 拾取顏色原理
通過顏色的堆疊我們已經(jīng)得出了以上的效果,但是我們得通過鼠標(biāo)移動獲取到混合后的顏色值,我們首先分別獲取鼠標(biāo)點擊后兩個ColoredTape的兩個顏色值,然后將兩個顏色值進(jìn)行混合,其中就兩個核心問題,一根據(jù)位置獲取ColoredTape上某點的顏色值,二根據(jù)將兩種顏色混合
- 獲取ColoredTape某點顏色值
根據(jù)ColoredTape分為幾個梯度,然后根據(jù)位置獲取到這個點前后兩個關(guān)鍵色的值,然后根據(jù)位置再對這兩個顏色值進(jìn)行混合
- 兩種顏色混合
兩個ColoredTape通過調(diào)用以上方法獲得兩個顏色值,然后對這兩種顏色進(jìn)行混合
我們調(diào)用mexedTwoColoredTapeColor獲取該種混合模式下某點的顏色,下面我們講解另外一種類型
2.2 類型二
2.2.1 實現(xiàn)原理
與漸變色帶不一樣的是,該種情況不能通過兩個色帶混合獲得,所以編寫一個繼承至ColoredTape 的MultiColoredTape類型實現(xiàn),我們只需要將圖片的四個頂點設(shè)置為不同的顏色即可
public class MultiColoredTape : MainColorTape {public Color TopLeft = Color.yellow;public Color TopRight = Color.white;public Color BottomLeft = Color.red;public Color BottomRight = Color.magenta;protected override void OnPopulateMesh(VertexHelper vh){vh.Clear();RectSize = GetPixelAdjustedRect().size;var halfX = RectSize.x / 2.0f;var halfY = RectSize.y / 2.0f;// 每個頂點設(shè)置一種顏色UIVertex topLeft = GetUIVertex(new Vector2(-halfX , halfY) , TopLeft);UIVertex topRight = GetUIVertex(new Vector2(halfX , halfY) , TopRight);UIVertex bottomLeft = GetUIVertex(new Vector2(-halfX , -halfY) , BottomLeft);UIVertex bottomRight = GetUIVertex(new Vector2(halfX , -halfY) , BottomRight);vh.AddUIVertexQuad(new UIVertex[] { topLeft , topRight , bottomRight , bottomLeft });if ( Outline ) DrawOutline(vh);} }在面板中簡單設(shè)置即可獲得所要的效果
2.2.2 拾取顏色原理
這種顏色的混合讓獲取某一點色值的邏輯稍微變得復(fù)雜一點,總體分為兩步
- a. 計算四個點與該點的權(quán)重,權(quán)重通過計算距離比例(以圖片的長寬為基礎(chǔ)值)
- b. 然后根據(jù)權(quán)重值將四個頂點色進(jìn)行混合
3.實現(xiàn)放大部分區(qū)域,吸取顏色
要實現(xiàn)這個效果,有幾個核心的問題,如下:
- 1.如何實現(xiàn)網(wǎng)格劃分
- 2.如何獲取一個像素的顏色
- 3.如何實現(xiàn)圖像顯示在網(wǎng)格中
接下來我們就挨個解決以上問題:
3.1 網(wǎng)格劃分
其實在Unity自定義UI組件(二)函數(shù)圖篇(下)中我們已經(jīng)講過過如何繪制網(wǎng)格,獲取每個線段兩個端點的位置,然后將其繪制成一條直線,通過循環(huán)我們就可以得到網(wǎng)格圖,詳細(xì)見代碼
protected override void OnPopulateMesh(VertexHelper vh) {vh.Clear();var rectSize = GetPixelAdjustedRect().size;var width = rectSize.x;var height = rectSize.y;var perWidth = width / XAxisCount;var perHeight = height / YAxisCount;Vector2 origin = new Vector2(-rectSize.x / 2.0f , -rectSize.y / 2.0f);//x axis 繪制x軸for ( int i = 0 ; i <= YAxisCount ; i++ ){Vector2 startPos = origin + new Vector2(0 , i * perHeight);Vector2 endPos = startPos + new Vector2(width , 0);vh.AddUIVertexQuad(GetQuad(startPos , endPos , Color , LineWidth));}//y axis 繪制y軸for ( int i = 0 ; i <= XAxisCount ; i++ ){Vector2 startPos = origin + new Vector2(i * perWidth , 0);Vector2 endPos = startPos + new Vector2(0 , height);vh.AddUIVertexQuad(GetQuad(startPos , endPos , Color , LineWidth));}// 將中心一格設(shè)置為紅色 var x = (int)( XAxisCount / 2 );var y = (int)( YAxisCount / 2 );var bottomLeft = origin + new Vector2(perWidth * x , perHeight * y);var bottomRight = bottomLeft + new Vector2(perWidth , 0);var topLeft = bottomLeft + new Vector2(0 , perHeight);var topRight = topLeft + new Vector2(perWidth , 0);vh.AddUIVertexQuad(GetQuad(topLeft , topRight , FocusColor , FocuslineWidth));vh.AddUIVertexQuad(GetQuad(bottomLeft , bottomRight , FocusColor , FocuslineWidth));vh.AddUIVertexQuad(GetQuad(topLeft , bottomLeft , FocusColor , FocuslineWidth));vh.AddUIVertexQuad(GetQuad(topRight , bottomRight , FocusColor , FocuslineWidth)); }3.2 獲取像素顏色
Unity提供了一個方法UnityEngine.Texture2D.GetPixel(x,y),利用這個方法我們可以獲取一個紋理上某個點的顏色值。
protected virtual void Update() { //吸取顏色if (WorkState == E_WorkState.Sucker){// 截圖顯示在網(wǎng)格中,每幀刷新StartCoroutine(ScreenShot());if ( Input.GetMouseButtonDown(0) ){// 獲取m_screenImage.sprite 紋理的中心像素的顏色// 獲取的像素是網(wǎng)格的中心像素Color = m_screenImage.sprite.texture.GetPixel(m_imageMesh.XAxisCount / 2 + 1 , m_imageMesh.YAxisCount / 2 + 1);SetNoniusPositionByColor();WorkState = E_WorkState.Normal;}} }知道了如何獲取圖像上某一點像素顏色之后,我們來看看如何截圖并顯示
3.3 獲取截圖并在網(wǎng)格中顯示
我們將Image組建和網(wǎng)格組建(IamgeMesh)放置在同一層級,并讓后網(wǎng)格組建的Slibing大于Image組建,我們給Image賦值即可實現(xiàn)在網(wǎng)格中顯示圖片的效果。
// 按網(wǎng)格像素截屏并顯示 private IEnumerator ScreenShot( ) {// 獲取截圖的尺寸 x , y var xCount = m_imageMesh.XAxisCount;var yCount = m_imageMesh.YAxisCount;// 新建紋理,參數(shù)為尺寸,格式,是否帶有mipmapm_texture = new Texture2D(xCount , yCount , TextureFormat.RGB24 , false);// 等待幀結(jié)束yield return new WaitForEndOfFrame();// 讀取Rect范圍內(nèi)的像素并存入紋理中m_texture.ReadPixels(new Rect((int)Input.mousePosition.x - (int)( xCount / 2 ) ,(int)Input.mousePosition.y - (int)( yCount / 2 ) , xCount , yCount) , 0 , 0);// 實際應(yīng)用紋理m_texture.Apply();// 賦值給Image組建m_screenImage.sprite = Sprite.Create(m_texture , new Rect(0 , 0 , xCount , yCount) , Vector2.zero); }通過以上重點講解大家應(yīng)該對顏色拾取器中核心的問題有所掌握,通過以上學(xué)習(xí)大家可以創(chuàng)建一個基礎(chǔ)的顏色拾取器,但是如果要實現(xiàn)調(diào)色板不同的模式和不同顏色模式需要對顏色屬性有個深度的了解,下一篇我們繼續(xù)完善顏色拾取器,以完美復(fù)刻Unity自帶顏色拾取器。下一篇我們重點講解一下內(nèi)容:
- 如何實現(xiàn)不同模式的調(diào)色板
- 如何實現(xiàn)不同的顏色模式
- 如何在自己的工程中使用顏色拾取器工具
- 如何使用顏色拾取器的接口
后續(xù)拓展
- Unity中只提供這樣一種顏色拾取器,用過Photoshop的同學(xué)知道ps中的顏色拾取器與unity中是不一樣的,或者是一些視頻剪輯軟件中的顏色拾取器是環(huán)形的,我們通過這篇的學(xué)習(xí),可以自己拓展出更多類型的顏色拾取器,有時間我也會奉上我的代碼,以供學(xué)習(xí)參考
- 在Untiy UGUI中繪制圖形圖像接口還是過于繁瑣,必須自己寫一個類繼承Graphic或其子類,重新OnPopulateMesh來繪制圖形,我們可以簡化這一步驟以實現(xiàn)QT中的QPainter和QPen類似的功能,提供繪制同行更加簡單的API,接下來,我們將實現(xiàn)這個功能
Unity自定義UI組件系列
- Unity自定義UI組件(七)漸變工具、漸變色圖片、漸變遮罩
- Unity自定義UI組件(六)日歷、日期拾取器
- Unity自定義組件之(五) 目錄樹 UITree
- Unity自定義UI組件(四)雙擊按鈕、長按按鈕
- Unity自定義UI組件(三)餅圖篇
- Unity自定義UI組件(二)函數(shù)圖篇(下)
- Unity自定義UI組件(一)函數(shù)圖篇(上)
Unity框架解讀系列
- [Unity]PureMVC框架解讀(下)
- [Unity]PureMVC框架解讀(上)
分享地址
- Github :https://github.com/ll4080333/UnityCodes
- CSDN : http://blog.csdn.net/qq_29579137
如果你想了解UGUI的更多拓展組件,歡迎關(guān)注我的博客,我會持續(xù)更新,支持一下我這個博客新手。如果以上文章對你有幫助,點個贊,讓更多的人看到這篇文章,我們一起學(xué)習(xí)。如果有什么指點的地方歡迎在評論區(qū)留言,秒回復(fù)。
總結(jié)
以上是生活随笔為你收集整理的Unity自定义UI组件(八) 颜色拾取器(上)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux实用指令
- 下一篇: java word转图片tiff_不怕复