您的位置:首页 > 产品设计 > UI/UE

[UGUI]实现色环和拾色

2015-12-26 23:56 537 查看

最终效果



实现过程

1.相关API

Texture2D文档
SetPixels方法,用来设置一块颜色。 
GetPixel方法,获取对应位置的颜色。 
GetPixelBilinear方法,获取对应UV的颜色。 
Apply方法,告诉GPU应用新的颜色纹理。
EventSystems下的接口文档 
IPointerDownHandler 实现鼠标按下UI事件 
IDragHandler 实现鼠标拖拽UI事件 
IPointerUpHandler 实现鼠标离开UI事件
Color文档
HSVToRGB和RGBToHSV 方法实现两种色彩空间的互转

2.实现色板

_colorZone = new Texture2D(64, 64, TextureFormat.ARGB32, false);
//首先new一个Texture2D来充当画布。
public void UpdateColorAtlas(float h)//通过i变量来更改色调
{
h = Mathf.Abs(i % 1f);//保证i在0-1
Color[] c = new Color[_colorZone.GetPixels().Length];//创建颜色数组
//根据图片的尺寸,给每个像素设置颜色
for (int y = 0; y <  _colorZone.height; y++)
for (int x = 0; x < _colorZone.width; x++)
c[x + y * size] = Color.HSVToRGB(h, (float)x / _colorZone.width, (float)y / _colorZone.height);
//如果后面滑动Slider时,色调是反的,也可以1-h,也可以反转Slider,根据情况改变
_colorZone.SetPixels(c);//用SetPixels将颜色整块赋值
_colorZone.Apply();//应用
}

3.实现Hue条

Texture2D CreateHue(int width, int height)
{
Texture2D h = new Texture2D(width, height, TextureFormat.RGBA32, false);
Color[] hc = new Color[width * height];
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
hc[x + y * width] = Color.HSVToRGB((float)y / height, 1f, 1f);
//用HSVToRGB将颜色变换
h.SetPixels(hc);
h.Apply();
return h;//最终返回一张Texture2D
}

4.UI拼装

有了上面两段代码,就能拼装简单的色环了。
创建两个RawImage,因为只有RawImage才接受Texture



一个用来当画布,再创建一个Slider,把另一个RawImage放到它下面,用来当色环,
目录结构如下:



然后我们只需要ColorAtlas类的对象给Slider的value调用UpdateColorAtlas方法,就能拖拽动态改变画布的色调。

//给Slider关联方法
HueSlider.onValueChanged.AddListener(UpdateColorAtlas);
当然,也可以用GUI来直接绘制。

5.拾色

拾色这一步比较麻烦,我没有找到直接获取图片UV的办法,只能通过获取画布比例,转换为对应的屏幕比例来获得对应的坐标。以下是画布转换为屏幕。

public Vector2 edge=Vector2.zero;//定义边框
RectTransform _m;
CanvasScaler _c;
void Start()
{
_m = GetComponent<RectTransform>();
_c = transform.GetComponentInParent<CanvasScaler>();
if (_c == null)//寻找画布
while (true)
{
_c = _c.GetComponentInParent<CanvasScaler>();
if (_c != null)
break;
}
}
Vector2 GetCursorUV(ref Vector2 pos)//限制坐标范围,返回坐标在UI上的UV
{
Rect r = MyRectToScreen();
pos = new Vector2(Mathf.Clamp(pos.x, r.xMin + edge.x, r.xMax - edge.x), Mathf.Clamp(pos.y, r.yMin + edge.y, r.yMax - edge.y));
Vector2 v = new Vector2(Mathf.InverseLerp(r.xMin, r.xMax, pos.x), Mathf.InverseLerp(r.yMin, r.yMax, pos.y));
return v;
}
Rect MyRectToScreen()//将UI的画布尺寸转换为屏幕尺寸
{
Vector2 size = new Vector2(_m.rect.width / _c.referenceResolution.x * Screen.width, _m.rect.height / _c.referenceResolution.y * Screen.height);
Vector2 pos = new Vector2(_m.position.x - size.x / 2, _m.position.y - size.y / 2);
Rect r = new Rect(pos, size);
return r;
}
如果有人有更好的办法直接获取鼠标点击的UI位置的UV,请告诉我。

6.给Color添加事件

现在我们能获得颜色了,为了方便其他脚本响应颜色的改变,我们应该给颜色添加事件,这样颜色一改就可以通知其他脚本。

public event Action<ColorAtlas, Color> ChangeColor;//新建事件
[SerializeField]
private Color color = Color.white;
public Color Color//Color属性
{
get { return color; }
set
{
if (ChangeColor != null)
ChangeColor(this, value);//颜色改变触发事件
color = value;
}
}


7.Slider注册事件

Slider _s;
void Start()
{
_s = gameObject.GetComponent<Slider>();
//还记得之前写的匿名方法和Lambda表达式吗?
colorAtlas.ChangeColor += (a, c) => { Color _c = new Color(); Color.RGBToHSV(c, out _c.r, out _c.g, out _c.b); _s.value = _c.r; };
}

工程文件下载

百度网盘地址
密码:0rxw
使用版本:Unity5.3
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Unity color