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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Unity自定义UI组件(八) 颜色拾取器(上)

發布時間:2023/12/10 编程问答 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity自定义UI组件(八) 颜色拾取器(上) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

unity中我們在選取顏色時unity會自動彈出顏色拾取器,通過操作選取自己想要的顏色,但是這個組建在我們自己的應用中無法使用,我們可以通過Windows的組建,但是unity 中調用總是有很多的問題,所以博主就自己開發了一個顏色拾取器,方便使用。我們將完美還原Unity自帶顏色拾取器的全部功能,內容較多,分為兩篇博客講解

組件特點

  • 無需任何asset
  • 導入代碼即可生成
  • 調用接口方便

實現效果

  • 普通狀態

  • 其他調色板模式

  • HSV模式

  • 截圖模式

主要內容

通過博主之前七篇UI組件的講解,這里不再對基礎的代碼進行講解,我們講解一下其中的重點內容。其中的吸管圖標,滑動條的圖標和按鈕圖標都是直接利用代碼繪制,詳細見代碼注解。

  • 顏色原理與顏色模式
  • 漸變色堆疊,實現多種調色板
  • 實現放大部分區域,吸取顏色

詳細講解

1.顏色原理與顏色模式

1.1 色彩原理:

Unity中顏色由R、G、B、A(紅、綠、藍、透明)四個通道組成,所有的顏色都是通過這四個通道混合而成。

1.2 顏色模式

顏色模式是將顏色表現為數學形式的模式,分為RGB模式,CMYK模式(用于打印),HSV模式,灰度模式,位圖模式等,這里我們以顏色拾取器設計的RGB和HSV來講解一下。

1.2.1 RGB模式
  • RGB就是常說的三原色,R代表Red(紅色),G代表Green(綠色),B代表Blue(藍色)
  • 自然界中肉眼所能看到的任何色彩都可以由這三種色彩混合疊加而成,因此也稱為加色模式
  • 計算機定義顏色時R、G、 B三種成分的取值范圍是0-255,0表示沒有刺激量,255表示刺激量達最大值
  • R、G、B均為255時就合成了白光,R、G、B均為0時就形成了黑色
  • 在顯示屏上顯示顏色定義時,往往采用這種模式,圖像如用于電視、幻燈片、網絡、多媒體,一般使用RGB模
1.2.2 HSV模式
  • HSV(Hue, Saturation, Value)是根據顏色的直觀特性由A. R. Smith在1978年創建的一種顏色空間
  • 這個模型中顏色的參數分別是:色調(H),飽和度(S),明度(V)
  • 色調H

    用角度度量,取值范圍為0°~360°,從紅色開始按逆時針方向計算,紅色為0°,綠色為120°,藍色為240°。它們的補色是:黃色為60°,青色為180°,品紅為300°

  • 飽和度S

    飽和度S表示顏色接近光譜色的程度。一種顏色,可以看成是某種光譜色與白色混合的結果。其中光譜色所占的比例愈大,顏色接近光譜色的程度就愈高,顏色的飽和度也就愈高。飽和度高,顏色則深而艷。光譜色的白光成分為0,飽和度達到最高。通常取值范圍為0%~100%,值越大,顏色越飽和

  • 明度V

    明度表示顏色明亮的程度,對于光源色,明度值與發光體的光亮度有關;對于物體色,此值和物體的透射比或反射比有關。通常取值范圍為0%(黑)到100%(白)

以上內容做一個了解,在Unity中我們這里理解,RGB模式是R、G、B三個基本色來構成,而HSV是由H 色調、S 飽和度、V 明度(亮度)來組合構成。

1.3 調色板模式

因為顏色總是由三個分量組成,所有在二維的空間中,我們用兩個分量組成的面和另一個分量來決定的,所以我們可以按照這個單獨的分量來命名

  • Hue模式
  • Brightness模式
  • Saturation模式
  • Red模式
  • Green模式
  • Blue模式

2.漸變色堆疊,實現多種調色板

關于顏色漸變的內容我們在上一篇Unity自定義UI組件 漸變工具中具體講解過,這里我們只討論如何實現多種顏色的疊加

2.1 類型一

2.1.1 實現原理
  • 1.利用ColoredTape調出七色漸變圖
    • a. 設置TapeDirection為Horizontal方向
    • b. 設置Colors尺寸為7,依次七種顏色值

  • 2.再新建一個ColoredTape給七色漸變圖蒙版
    • a. 設置TapeDirection為Vertical方向
    • b. 設置Colors尺寸為2,傳入兩種顏色值

2.1.2 拾取顏色原理

通過顏色的堆疊我們已經得出了以上的效果,但是我們得通過鼠標移動獲取到混合后的顏色值,我們首先分別獲取鼠標點擊后兩個ColoredTape的兩個顏色值,然后將兩個顏色值進行混合,其中就兩個核心問題,一根據位置獲取ColoredTape上某點的顏色值,二根據將兩種顏色混合

  • 獲取ColoredTape某點顏色值
    根據ColoredTape分為幾個梯度,然后根據位置獲取到這個點前后兩個關鍵色的值,然后根據位置再對這兩個顏色值進行混合
/// /// 獲取色帶上某點的顏色值 /// public virtual Color GetColor( Vector2 position ) {int colorCount = m_Colors.Count;switch (TapeDirection){// 水平色帶case E_DrawDirection.Horizontal:var perX = RectSize.x / ( ( colorCount - 1 ) * 2 );var doubelPer = perX * 2;var lenght0 = position.x + RectSize.x / 2.0f;int index0 = (int)( lenght0 / doubelPer );var temp0 = lenght0 % doubelPer / doubelPer;if (lenght0.Equals(RectSize.x)){index0--;temp0++;}// 獲取離該點最近的兩個顏色值,然后混合Color start = m_Colors[index0];Color end = m_Colors[index0 + 1];return start * ( 1 - temp0 ) + end * temp0;// 垂直色帶case E_DrawDirection.Vertical:var perY = RectSize.y / ( ( colorCount - 1 ) * 2 );var doublePer = perY * 2;var lenght1 = position.y + RectSize.y / 2.0f;var index1 = (int)( lenght1 / doublePer );var temp1 = lenght1 % doublePer / doublePer;if ( lenght1.Equals(RectSize.y) ){index1--;temp1++;}/ 獲取離該點最近的兩個顏色值,然后混合Color start1 = m_Colors[index1];Color end1 = m_Colors[index1 + 1];return start1 * (1 - temp1) + end1 * temp1;default:return Color.white;} }
  • 兩種顏色混合
    兩個ColoredTape通過調用以上方法獲得兩個顏色值,然后對這兩種顏色進行混合
private Color mixedTwoColoredTapeColor( Vector2 noniusPos ) {Color first = m_firstLayerCT.GetColor(noniusPos);// m_secondLayerCT是蒙版色帶Color second = m_secondLayerCT.GetColor(noniusPos);float alpha = second.a;float index = 1 - alpha;// 利用透明度為比例值將兩種顏色混色var color = new Color(second.r * index , second.g * index , second.b * index) + new Color(first.r * alpha , first.g * alpha , first.b * alpha);color.a = Color.a;return color; }

我們調用mexedTwoColoredTapeColor獲取該種混合模式下某點的顏色,下面我們講解另外一種類型

2.2 類型二
![ ](https://img-blog.csdn.net/20170704195431102?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjk1NzkxMzc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
2.2.1 實現原理

與漸變色帶不一樣的是,該種情況不能通過兩個色帶混合獲得,所以編寫一個繼承至ColoredTape 的MultiColoredTape類型實現,我們只需要將圖片的四個頂點設置為不同的顏色即可

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;// 每個頂點設置一種顏色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);} }

在面板中簡單設置即可獲得所要的效果

2.2.2 拾取顏色原理

這種顏色的混合讓獲取某一點色值的邏輯稍微變得復雜一點,總體分為兩步

  • a. 計算四個點與該點的權重,權重通過計算距離比例(以圖片的長寬為基礎值)
// 獲取權重 , 距離頂點超過邊長的權重為0 private float getsacle( Vector2 position , Vector2 index ) {float lenght = Vector3.Distance(position , index);if ( lenght > RectSize.x )return 0;return 1 - lenght / RectSize.x; }
  • b. 然后根據權重值將四個頂點色進行混合
public override Color GetColor( Vector2 position ) {float halfLenght = RectSize.x / 2.0f;var topleft = ( getsacle(position , new Vector2(-halfLenght , halfLenght)) ) * TopLeft;var topright = ( getsacle(position , new Vector2(halfLenght , halfLenght)) ) * TopRight;var bottomleft = ( getsacle(position , new Vector2(-halfLenght , -halfLenght)) ) * BottomLeft;var bottomright = ( getsacle(position , new Vector2(halfLenght , -halfLenght)) ) * BottomRight;// 根據權重值計算混合色var color = topleft + topright + bottomleft + bottomright;return color; }

3.實現放大部分區域,吸取顏色

要實現這個效果,有幾個核心的問題,如下:

  • 1.如何實現網格劃分
  • 2.如何獲取一個像素的顏色
  • 3.如何實現圖像顯示在網格中

接下來我們就挨個解決以上問題:

3.1 網格劃分

其實在Unity自定義UI組件(二)函數圖篇(下)中我們已經講過過如何繪制網格,獲取每個線段兩個端點的位置,然后將其繪制成一條直線,通過循環我們就可以得到網格圖,詳細見代碼

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));}// 將中心一格設置為紅色 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){// 截圖顯示在網格中,每幀刷新StartCoroutine(ScreenShot());if ( Input.GetMouseButtonDown(0) ){// 獲取m_screenImage.sprite 紋理的中心像素的顏色// 獲取的像素是網格的中心像素Color = m_screenImage.sprite.texture.GetPixel(m_imageMesh.XAxisCount / 2 + 1 , m_imageMesh.YAxisCount / 2 + 1);SetNoniusPositionByColor();WorkState = E_WorkState.Normal;}} }

知道了如何獲取圖像上某一點像素顏色之后,我們來看看如何截圖并顯示

3.3 獲取截圖并在網格中顯示

我們將Image組建和網格組建(IamgeMesh)放置在同一層級,并讓后網格組建的Slibing大于Image組建,我們給Image賦值即可實現在網格中顯示圖片的效果。

// 按網格像素截屏并顯示 private IEnumerator ScreenShot( ) {// 獲取截圖的尺寸 x , y var xCount = m_imageMesh.XAxisCount;var yCount = m_imageMesh.YAxisCount;// 新建紋理,參數為尺寸,格式,是否帶有mipmapm_texture = new Texture2D(xCount , yCount , TextureFormat.RGB24 , false);// 等待幀結束yield return new WaitForEndOfFrame();// 讀取Rect范圍內的像素并存入紋理中m_texture.ReadPixels(new Rect((int)Input.mousePosition.x - (int)( xCount / 2 ) ,(int)Input.mousePosition.y - (int)( yCount / 2 ) , xCount , yCount) , 0 , 0);// 實際應用紋理m_texture.Apply();// 賦值給Image組建m_screenImage.sprite = Sprite.Create(m_texture , new Rect(0 , 0 , xCount , yCount) , Vector2.zero); }

通過以上重點講解大家應該對顏色拾取器中核心的問題有所掌握,通過以上學習大家可以創建一個基礎的顏色拾取器,但是如果要實現調色板不同的模式和不同顏色模式需要對顏色屬性有個深度的了解,下一篇我們繼續完善顏色拾取器,以完美復刻Unity自帶顏色拾取器。下一篇我們重點講解一下內容:

  • 如何實現不同模式的調色板
  • 如何實現不同的顏色模式
  • 如何在自己的工程中使用顏色拾取器工具
  • 如何使用顏色拾取器的接口

后續拓展

  • Unity中只提供這樣一種顏色拾取器,用過Photoshop的同學知道ps中的顏色拾取器與unity中是不一樣的,或者是一些視頻剪輯軟件中的顏色拾取器是環形的,我們通過這篇的學習,可以自己拓展出更多類型的顏色拾取器,有時間我也會奉上我的代碼,以供學習參考
  • 在Untiy UGUI中繪制圖形圖像接口還是過于繁瑣,必須自己寫一個類繼承Graphic或其子類,重新OnPopulateMesh來繪制圖形,我們可以簡化這一步驟以實現QT中的QPainter和QPen類似的功能,提供繪制同行更加簡單的API,接下來,我們將實現這個功能

Unity自定義UI組件系列

  • Unity自定義UI組件(七)漸變工具、漸變色圖片、漸變遮罩
  • Unity自定義UI組件(六)日歷、日期拾取器
  • Unity自定義組件之(五) 目錄樹 UITree
  • Unity自定義UI組件(四)雙擊按鈕、長按按鈕
  • Unity自定義UI組件(三)餅圖篇
  • Unity自定義UI組件(二)函數圖篇(下)
  • Unity自定義UI組件(一)函數圖篇(上)

Unity框架解讀系列

  • [Unity]PureMVC框架解讀(下)
  • [Unity]PureMVC框架解讀(上)

分享地址

  • Github :https://github.com/ll4080333/UnityCodes
  • CSDN : http://blog.csdn.net/qq_29579137
    如果你想了解UGUI的更多拓展組件,歡迎關注我的博客,我會持續更新,支持一下我這個博客新手。如果以上文章對你有幫助,點個贊,讓更多的人看到這篇文章,我們一起學習。如果有什么指點的地方歡迎在評論區留言,秒回復。

總結

以上是生活随笔為你收集整理的Unity自定义UI组件(八) 颜色拾取器(上)的全部內容,希望文章能夠幫你解決所遇到的問題。

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