Unity 利用像素点在图片上画线(RawImage)

原理:创建透明度为0的Texture2D,利用改变像素点的颜色,实现画线功能。

创建图片

rawimage 的大小一定要与屏幕大小保持一致

代码部分:

完整代码:挂载RawImage上,对应组件拖进去就行

/*******************************************************************
* 作者:     # maki #
* 创建日期: # 2019年9月4日18:07:57 #
* 描述:  UGUI 图片划线工具
******************************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public enum TextureLineType
{
    none,//不画线
    line,//自由线
    dotLine,//点画线
    eraseLine,//擦除线
}
public class TextureLineTool : MonoBehaviour {

    public static TextureLineTool Instance;
    #region 画线设置
    /// <summary>
    /// 画线风格
    /// </summary>
    [SerializeField]
    private TextureLineType lineType;//画线风格
    /// <summary>
    /// 渲染次数:点画线1000,曲线100  不可过大,太消耗渲染性能
    /// </summary>
    [SerializeField]
    private float lineNum = 100f;
    /// <summary>
    /// 笔刷的宽度
    /// </summary>
    [SerializeField]
    private int lineWidth = 3;
    /// <summary>
    /// 笔刷的颜色
    /// </summary>
    [SerializeField]
    private Color lineColor = new Color(1, 1, 1, 0);
    #endregion

    /// <summary>
    /// 被操作的贴图
    /// </summary>
    [SerializeField]
    private Texture2D targetTexture;
    /// <summary>
    /// 目标图片UI
    /// </summary>
    [SerializeField]
    private RawImage targetRawImage;
    /// <summary>
    /// 划线相机
    /// </summary>
    [SerializeField]
    private Camera line_Camera;
    /// <summary>
    /// 擦除鼠标图片跟随
    /// </summary>
    [SerializeField]
    private Image mouseImage;

    /// <summary>
    /// 上一个点鼠标点
    /// </summary>
    Vector2 lastPoint = Vector2.zero;

    /// <summary>
    /// 被记录的鼠标位置
    /// </summary>
    private List<Vector2> mousePoints;
    /// <summary>
    /// 被记录的步骤
    /// </summary>
   private List<Texture2D> textureRecords;

    /// <summary>
    /// 当前画板下标
    /// </summary>
    int index = 0;


    void Awake()
    {
        Instance = this;
    }
    private void Start()
    {
        lineType = TextureLineType.none;
        mousePoints = new List<Vector2>();
        targetRawImage.texture = new Texture2D(Screen.width, Screen.height);
        targetTexture = targetRawImage.texture as Texture2D;
        ClearTexture();
        textureRecords = new List<Texture2D>();
        RecortStep();
    }


    void Update()
    {
        if (lineType == TextureLineType.line || lineType == TextureLineType.eraseLine)
        {
            if (Input.GetMouseButton(0))
            {
                if (IsPointerOverUI(targetRawImage.transform))
                {
                    Vector2 addPoint = line_Camera.ScreenToViewportPoint(Input.mousePosition);
                    OperateTexture(addPoint, lineType);
                }
                else
                {
                    lastPoint = Vector2.zero;
                }
            }
            if (Input.GetMouseButtonUp(0))
            {
                lastPoint = Vector2.zero;
                RecortStep();
                mouseImage.transform.localPosition = new Vector2(-10000, -10000);
            }
        }
        else if (lineType == TextureLineType.dotLine)
        {
            if (Input.GetMouseButtonDown(0))
            {
                if (IsPointerOverUI(targetRawImage.transform))
                {
                    Vector2 addPoint = line_Camera.ScreenToViewportPoint(Input.mousePosition);
                    OperateTexture(addPoint, lineType);
                }
                else
                {
                    lastPoint = Vector2.zero;
                }
            }

        }
       if (Input.GetMouseButtonDown(1))
        {
            lastPoint = Vector2.zero;
            lineType = TextureLineType.none;
        }
    }

    /// <summary>
    /// 画线
    /// </summary>
    /// <param name="point"></param>
    /// <param name="mColor"></param>
    private  void OperateTexture(Vector2 point, TextureLineType lineType)
    {
        if (lastPoint == Vector2.zero)
        {
            lastPoint = point;
            return;
        }
        for (int j = 0; j < lineNum; j++)
        {
            float scaleX = Mathf.Lerp(lastPoint.x, point.x, j / lineNum);
            float scaleY = Mathf.Lerp(lastPoint.y, point.y, j / lineNum);
            int textureX = (int)(scaleX * Screen.width);
            int textureY = (int)(scaleY * Screen.height);
            // 线条加粗
            for (int a = textureX - lineWidth; a < textureX + lineWidth; a++)
            {
                for (int b = textureY - lineWidth; b < textureY + lineWidth; b++)
                {
                    targetTexture.SetPixel(a, b, lineColor);
                }
            }
        }
        targetTexture.Apply();
        lastPoint = point;
        if (lineType == TextureLineType.dotLine)
            RecortStep();
        else if (lineType == TextureLineType.eraseLine)
        {
            Vector2 pos;
            if(RectTransformUtility.ScreenPointToLocalPointInRectangle(this.transform as RectTransform,Input.mousePosition,line_Camera,out pos))
            {
                mouseImage.transform.localPosition = pos;
            }
        }
    }

    /// <summary>
    /// 重置贴图(全部擦除)
    /// </summary>
    public void ClearTexture()
    {
        int x, y;
        for (x = 0; x < targetTexture.width; x++)
        {
            for (y = 0; y < targetTexture.height; y++)
            {
                targetTexture.SetPixel(x, y, new Color(1, 1, 1, 0));
            }
        }
        targetTexture.Apply();
    }

    /// <summary>
    /// 设置画线模式
    /// </summary>
    public void SetLineType(TextureLineType type)
    {
        lastPoint = Vector2.zero;
        lineType = type;
        switch (lineType)
        {
            case TextureLineType.none:
                break;
            case TextureLineType.line:
                 lineNum = 100f;
                 lineWidth = 3;//设置笔宽
                lineColor = Color.red;
                break;
            case TextureLineType.dotLine:
                lineNum = 1000f;
                lineWidth = 3;//设置笔宽
                lineColor = Color.red;
                break;
            case TextureLineType.eraseLine:
                lineNum = 200f;
                lineWidth = 30;//设置笔宽
                lineColor = new Color(1, 1, 1, 0);
                break;
            default:
                break;
        }
    }

    /// <summary>
    /// 记录步骤
    /// </summary>
    private void RecortStep()
    {
        if (textureRecords.Count > 0)
        {
            if (index != textureRecords.Count - 1)
            {
                textureRecords.RemoveRange((index + 1), textureRecords.Count - (index + 1));
            }
        }
        Texture2D newTexture = Instantiate(targetTexture);
        textureRecords.Add(newTexture);
        index = textureRecords.Count - 1;
    }
    /// <summary>
    /// 上一步
    /// </summary>
    public void StepUp()
    {
        if (index > 0)
        {
            index--;
            targetTexture = Instantiate(textureRecords[index]);
            targetRawImage.texture = targetTexture;
        }
    }
    /// <summary>
    /// 下一步
    /// </summary>
    public void StepDown()
    {
        if (index < textureRecords.Count - 1)
        {
            index++;
            targetTexture = Instantiate(textureRecords[index]);
            targetRawImage.texture = targetTexture;
        }
    }

    /// <summary>
    /// 获取当前UI
    /// </summary>
    private bool IsPointerOverUI(Transform tran)
    {
        if (EventSystem.current.IsPointerOverGameObject())
        {
            PointerEventData pointerEventData = new PointerEventData(EventSystem.current);
            pointerEventData.position = Input.mousePosition;
            List<RaycastResult> result = new List<RaycastResult>();
            EventSystem.current.RaycastAll(pointerEventData, result);
            if (result.Count > 0)
                foreach (var item in result)
                {
                    if (item.gameObject.transform.IsChildOf(tran))
                    {
                        return true;
                    }
                }
        }
        return false;
    }
}

 

测试代码:


public class LineTest : MonoBehaviour {

    public Button Btn_Free;
    public Button Btn_Dolt;
    public Button Btn_Erase;
    public Button Btn_Cancel;
    public Button StepUp;
    public Button StepDown;
    // Use this for initialization
    void Start () {
        Btn_Free.onClick.AddListener(() => TextureLineTool.Instance.SetLineType(TextureLineType.line));
        Btn_Dolt.onClick.AddListener(() => TextureLineTool.Instance.SetLineType(TextureLineType.dotLine));
        Btn_Erase.onClick.AddListener(() => TextureLineTool.Instance.SetLineType(TextureLineType.eraseLine));
        Btn_Cancel.onClick.AddListener(() => TextureLineTool.Instance.ClearTexture());
        StepUp.onClick.AddListener(() => TextureLineTool.Instance.StepUp());
        StepDown.onClick.AddListener(() => TextureLineTool.Instance.StepDown());
    }
    // Update is called once per frame
    void Update () {
		
	}
}

显示效果如下:

说明:上一步和下一步,从项目中扣取下来,需求不大,存在bug,没有做修改

  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值