Unity

[Unity] LINE CHART 그래프 만들기 (1)

usingsystem 2023. 11. 20. 14:53
728x90

UI작업

1. LineChart를 담을 가장 부모 오브젝트를 만든다. 

먼저 LineChar트를 담을 빈 오브젝트를 캔버스에 추가한다.

사이즈는 자유롭게 정의 하며 앵커는 중앙값으로 놓는다.

2. LineChart의 배경과 라인과 점이 그려질 Container 오브젝트를 만든다.

사이즈는 부모오브젝트를 벗어나지 않는 선에서 만들며 가장 왼쪽에서부터 그래프가 그려져 야하기 때문에 가장 오른쪽 밑으로 앵커속성을 놓는다.(중요)

3. Graph container에 Image를 넣어 백그라운드를 채워 넣는다.

4. 차트를 그려줄 Script를 만든다.

 

UI_LineChart.cs작업

1. 점찍기(1)

Sprite는 SerializeField로 만들었기 때문에 에디터에서 적당한 Sprite 모양을 연결시켜 줘야 한다.

CreateCircle메서드는 내가 설정한 포지션에 Sprite image를 통해 점을 찍는 함수이다.

using UnityEngine;
using UnityEngine.UI;

public class UI_LineChart : MonoBehaviour
{
    [SerializeField]
    private Sprite _circleSprite;
    private RectTransform _graphContainer;
    void Start()
    {
        _graphContainer = transform.Find("GraphContainer").GetComponent<RectTransform>();
        CreateCircle(new Vector2(100, 100));
    }
    private GameObject CreateCircle(Vector2 anchoredPosition)
    {
        GameObject gameObject = new GameObject("circle", typeof(Image));
        gameObject.transform.SetParent(_graphContainer, false);
        gameObject.GetComponent<Image>().sprite = _circleSprite;
        RectTransform rectTransform = gameObject.GetComponent<RectTransform>();
        rectTransform.anchoredPosition = anchoredPosition;
        rectTransform.sizeDelta = new Vector2(11, 11);//그래프 점크기 설정.
        rectTransform.anchorMin = new Vector2(0, 0);//앵커min초기화
        rectTransform.anchorMax = new Vector2(0, 0);//앵커max초기화

        return gameObject;
    }
}

 

에디터 시작 결과 UI_LineChart에서 작성한 CreateCircle가 실행되면서 circle이 x  100 y 100 위치에  11, 11 크기로 생성되었다.

2. 점찍기(2)

여러 개의 점을 원하는 곳에 찍는 함수를 추가해 보자.

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UI_LineChart : MonoBehaviour
{
    [SerializeField]
    private Sprite _circleSprite;
    private RectTransform _graphContainer;
    void Start()
    {
        _graphContainer = transform.Find("GraphContainer").GetComponent<RectTransform>();
        List<int> valueList = new List<int>() { 5, 10, 98, 56, 45, 30, 22, 17, 15, 13, 17, 25, 37, 40, 36, 33 };
        ShowGraph(valueList);
    }
    private GameObject CreateCircle(Vector2 anchoredPosition)
    {
        GameObject gameObject = new GameObject("circle", typeof(Image));
        gameObject.transform.SetParent(_graphContainer, false);
        gameObject.GetComponent<Image>().sprite = _circleSprite;
        RectTransform rectTransform = gameObject.GetComponent<RectTransform>();
        rectTransform.anchoredPosition = anchoredPosition;
        rectTransform.sizeDelta = new Vector2(11, 11);//그래프 점크기 설정.
        rectTransform.anchorMin = new Vector2(0, 0);//앵커min초기화
        rectTransform.anchorMax = new Vector2(0, 0);//앵커max초기화

        return gameObject;
    }
    void ShowGraph(List<int> valueList)
    {
        float graphHeight = _graphContainer.sizeDelta.y;
        float yMaimum = 100f;
        float xSize = 50f;

        for (int i = 0; i < valueList.Count; i++)
        {
            float xPostion = xSize + i * xSize;
            float yPosition = (valueList[i] / yMaimum) * graphHeight;

            GameObject circleGameObject = CreateCircle(new Vector2(xPostion, yPosition));
        }
    }
}

valueList에서 설정한 값이 화면에 표시된다.

3. 선 그리기.

CreateDotConnection를 통해 두 점 오브젝트사이를 새로운 image를 통해 라인을 생성한다.

 float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;를 사용하여 ui 간 방향을 구한다.

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UI_LineChart : MonoBehaviour
{
    [SerializeField]
    private Sprite _circleSprite;
    private RectTransform _graphContainer;
    void Start()
    {
        _graphContainer = transform.Find("GraphContainer").GetComponent<RectTransform>();
        List<int> valueList = new List<int>() { 5, 10, 98, 56, 45, 30, 22, 17, 15, 13, 17, 25, 37, 40, 36, 33 };
        ShowGraph(valueList);
    }
    private GameObject CreateCircle(Vector2 anchoredPosition)
    {
        GameObject gameObject = new GameObject("circle", typeof(Image));
        gameObject.transform.SetParent(_graphContainer, false);
        gameObject.GetComponent<Image>().sprite = _circleSprite;
        RectTransform rectTransform = gameObject.GetComponent<RectTransform>();
        rectTransform.anchoredPosition = anchoredPosition;
        rectTransform.sizeDelta = new Vector2(11, 11);//그래프 점크기 설정.
        rectTransform.anchorMin = new Vector2(0, 0);//앵커min초기화
        rectTransform.anchorMax = new Vector2(0, 0);//앵커max초기화

        return gameObject;
    }
    void ShowGraph(List<int> valueList)
    {
        float graphHeight = _graphContainer.sizeDelta.y;
        float yMaimum = 100f;
        float xSize = 50f;

        GameObject lastCircleGameObject = null;
        for (int i = 0; i < valueList.Count; i++)
        {
            float xPostion = xSize + i * xSize;
            float yPosition = (valueList[i] / yMaimum) * graphHeight;
            GameObject circleGameObject = CreateCircle(new Vector2(xPostion, yPosition));
            if (lastCircleGameObject != null)
                CreateDotConnection(lastCircleGameObject.GetComponent<RectTransform>().anchoredPosition, circleGameObject.GetComponent<RectTransform>().anchoredPosition);
            lastCircleGameObject = circleGameObject;
        }
    }
    void CreateDotConnection(Vector2 dotPositionA, Vector2 dotPositionB)
    {
        GameObject gameObject = new GameObject("dotConnection", typeof(Image));
        gameObject.transform.SetParent(_graphContainer, false);
        gameObject.GetComponent<Image>().color = new Color(1, 1, 1, 0.5f);
        RectTransform rectTransform = gameObject.GetComponent<RectTransform>();
        Vector2 dir = (dotPositionB - dotPositionA).normalized;
        float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
        float distance = Vector2.Distance(dotPositionA, dotPositionB);
        rectTransform.anchorMin = new Vector2(0, 0);
        rectTransform.anchorMax = new Vector2(0, 0);
        rectTransform.sizeDelta = new Vector2(distance, 3f);
        rectTransform.anchoredPosition = dotPositionA + (dir) * distance * 0.5f;
        rectTransform.localEulerAngles = new Vector3(0, 0, angle);
    }
}

 

 

참조 - https://www.youtube.com/watch?v=QmU57Ka9H0E

728x90