效果
Unity 通过UGUI实现无级变色的调色板功能,非常的简单好用。
项目git地址
https://github.com/zrzhang76/UnityColorBoard
代码(写这个完全是因为CSDN嫌我字数少,建议直接看项目)
颜色板部分
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace CSharp.UI.ColorBoard
{
public class ColorBoard : MonoBehaviour, IPointerClickHandler, IDragHandler
{
//显示颜色的Texture
Texture2D tex2d;
//RawImage组件
RawImage ri;
//像素宽度高度256(默认值)
int TexPixelLength = 256;
int TexPixelHeight = 256;
//公共组件
public Slider sliderCRGB;
public ColorHue colorHue;
//颜色数组
UnityEngine.Color[,] arrayColor;
//自身的Transform
RectTransform rt;
//颜色聚焦点的圆圈
public RectTransform circleRect;
public delegate void ColorChangeDelegate(Color color);
public event ColorChangeDelegate OnColorChanged;
private void Awake()
{
ri = GetComponent<RawImage>();
rt = GetComponent<RectTransform>();
circleRect = transform.Find("img_cursor").GetComponent<RectTransform>();
TexPixelLength = (int)rt.sizeDelta.x;
TexPixelHeight = (int)rt.sizeDelta.y;
//初始化颜色数组
arrayColor = new UnityEngine.Color[TexPixelLength, TexPixelHeight];
//创建一个固定长宽的Texture
tex2d = new Texture2D(TexPixelLength, TexPixelHeight, TextureFormat.RGB24, true);
//组件赋值图片
ri.texture = tex2d;
ri.texture.wrapMode = TextureWrapMode.Clamp;
//初始化设置板子的颜色为红色
SetColorPanel(UnityEngine.Color.red);
sliderCRGB.onValueChanged.AddListener(OnCRGBValueChanged);
}
//颜色放生变化的监听
void OnCRGBValueChanged(float value)
{
UnityEngine.Color endColor=colorHue.GetColorBySliderValue(value);
SetColorPanel(endColor);
var color = GetColorByPosition(circleRect.anchoredPosition);
OnColorChanged?.Invoke(color);
}
//设置板子的颜色
public void SetColorPanel(UnityEngine.Color endColor)
{
UnityEngine.Color[] CalcArray = CalcArrayColor(endColor);
//给颜色板子填入颜色,并且应用
tex2d.SetPixels(CalcArray);
tex2d.Apply();
}
//通过一个最终颜色值,计算板子上所有像素点应该的颜色,并返回一个数组
UnityEngine.Color[] CalcArrayColor(UnityEngine.Color endColor)
{
//计算最终值和白色的差值在水平方向的平均值,用于计算水平每个像素点的色值
UnityEngine.Color value = (endColor - UnityEngine.Color.white) / (TexPixelLength - 1);
for (int i = 0; i < TexPixelLength; i++)
{
arrayColor[i, TexPixelHeight - 1] = UnityEngine.Color.white + value * i;
}
// 同理,垂直方向
for (int i = 0; i < TexPixelLength; i++)
{
value = (arrayColor[i, TexPixelHeight - 1] - UnityEngine.Color.black) / (TexPixelHeight - 1);
for (int j = 0; j < TexPixelHeight; j++)
{
arrayColor[i, j] = UnityEngine.Color.black + value * j;
}
}
//返回一个数组,保存了所有颜色色值
List<UnityEngine.Color> listColor = new List<UnityEngine.Color>();
for (int i = 0; i < TexPixelHeight; i++)
{
for (int j = 0; j < TexPixelLength; j++)
{
listColor.Add(arrayColor[j, i]);
}
}
return listColor.ToArray();
}
/// <summary>
/// 获取颜色by坐标,坐标是Texture上面的二维坐标
/// </summary>
/// <param name="pos"></param>
/// <returns></returns>
public UnityEngine.Color GetColorByPosition(Vector2 pos)
{
Texture2D tempTex2d = (Texture2D)ri.texture;
UnityEngine.Color getColor = tempTex2d.GetPixel((int)pos.x, (int)pos.y);
return getColor;
}
public Vector2 GetClampPosition(Vector2 touchPos)
{
Vector2 vector2 = new Vector2(touchPos.x, touchPos.y);
vector2.x = Mathf.Clamp(vector2.x, 0.001f, rt.sizeDelta.x);
vector2.y = Mathf.Clamp(vector2.y, 0.001f, rt.sizeDelta.y);
return vector2;
}
//点击事件
public void OnPointerClick(PointerEventData eventData)
{
Vector3 wordPos;
//将UGUI的坐标转为世界坐标
if (RectTransformUtility.ScreenPointToWorldPointInRectangle(rt, eventData.position, eventData.pressEventCamera, out wordPos))
circleRect.position = wordPos;
circleRect.anchoredPosition = GetClampPosition(circleRect.anchoredPosition);
var color = GetColorByPosition(circleRect.anchoredPosition);
OnColorChanged?.Invoke(color);
}
//拖拽事件
public void OnDrag(PointerEventData eventData)
{
Vector3 wordPos;
//将UGUI的坐标转为世界坐标
if (RectTransformUtility.ScreenPointToWorldPointInRectangle(rt, eventData.position, eventData.pressEventCamera, out wordPos))
circleRect.position = wordPos;
circleRect.anchoredPosition = GetClampPosition(circleRect.anchoredPosition);
var color = GetColorByPosition(circleRect.anchoredPosition);
OnColorChanged?.Invoke(color);
}
}
}
色相条部分
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ColorHue : MonoBehaviour
{
//绘制颜色的Texture
Texture2D tex2d;
//图片展示组件
RawImage ri;
//长宽
int TexPixelWdith = 952;
int TexPixelHeight = 16;
//颜色的数组
UnityEngine.Color[,] arrayColor;
private void Awake()
{
ri = gameObject.GetComponent<RawImage>();
//初始化颜色和Texture
arrayColor = new UnityEngine.Color[TexPixelWdith, TexPixelHeight];
tex2d = new Texture2D(TexPixelWdith, TexPixelHeight, TextureFormat.RGB24,true);
//计算颜色
UnityEngine.Color[] calcArray = CalcArrayColor();
//展示出来
tex2d.SetPixels(calcArray);
tex2d.Apply();
ri.texture = tex2d;
ri.texture.wrapMode = TextureWrapMode.Clamp;
}
//计算色相条上面需要展示的颜色数组
UnityEngine.Color[] CalcArrayColor()
{
//计算水平像素的等分增量
int addValue = (TexPixelWdith - 1) / 3;
//
for (int i = 0; i < TexPixelHeight; i++)
{
arrayColor[0, i] = UnityEngine.Color.red;
arrayColor[addValue, i] = UnityEngine.Color.green;
arrayColor[addValue+addValue, i] = UnityEngine.Color.blue;
arrayColor[TexPixelHeight - 1, i] = UnityEngine.Color.red;
}
UnityEngine.Color value = (UnityEngine.Color.green - UnityEngine.Color.red)/addValue;
for (int i = 0; i < TexPixelHeight; i++)
{
for (int j = 0; j < addValue; j++)
{
arrayColor[j, i] = UnityEngine.Color.red + value * j;
}
}
value = (UnityEngine.Color.blue - UnityEngine.Color.green)/ addValue;
for (int i = 0; i < TexPixelHeight; i++)
{
for (int j = addValue; j < addValue*2; j++)
{
arrayColor[j, i] = UnityEngine.Color.green + value * (j-addValue);
}
}
value = (UnityEngine.Color.red - UnityEngine.Color.blue) / ((TexPixelWdith - 1)-addValue-addValue);
for (int i = 0; i < TexPixelHeight; i++)
{
for (int j = addValue*2; j < TexPixelWdith - 1; j++)
{
arrayColor[j, i] = UnityEngine.Color.blue + value * (j- addValue * 2);
}
}
List<UnityEngine.Color> listColor = new List<UnityEngine.Color>();
for (int i = 0; i < TexPixelHeight; i++)
{
for (int j = 0; j < TexPixelWdith; j++)
{
listColor.Add(arrayColor[j, i]);
}
}
return listColor.ToArray();
}
/// <summary>
/// 获取颜色 根据高度
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public Color GetColorBySliderValue(float value)
{
float clampValue = Mathf.Clamp(value, 0.001f, 0.999f);
Color getColor=tex2d.GetPixel((int)((TexPixelWdith-1)*clampValue),0);
return getColor;
}
}
制作不易,给个赞呗~~