Unity中画2D图表(2)——用XChart包绘制散点分布图 + 一条直线方程

散点图用于显示关系。 对于 【相关性】 ,散点图有助于显示两个变量之间线性关系的强度。 对于 【回归】 ,散点图常常会添加拟合线。

举例1:你可以展示【年降雨量】与【玉米亩产量】的关系
举例2:你也可以分析各个【节假日】与【大盘波动】的关系

一、要画的图

图片来自官方demo

二、画图的过程展示

请添加图片描述

三、画图的要点

  • 添加一个scatter散点图表

  • 设置图表的大小:SetSize(x,y)

  • 设置标题:chart.Title.text|subText = “”

  • 设置提示框【Tooltip】和图例【Legend】是否显示

  • 设置坐标轴的数据刻度信息
    ——X轴的刻度数量,每个刻度对应的标签
    ——Y轴设置

  • 清空默认数据,添加Scatter类型的Serie用于接收数据

  • 添加数据:X轴的刻度数据,Y轴的数据

  • 数据添加到图表上
    ——X轴的刻度标签
    ——Y1,第一组数据
    ——Y2,第二组数据

  • x轴刻度标签旋转(倾斜)设置

  • 设置散点的颜色

  • 设置散点的大小

  • 画拟合的直线
    ——增加两个端点
    ——设置直线的【方程式text】
    ——设置直线的形状

  • 刷新所有的组件

四、代码清单

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cysharp.Threading.Tasks;
using XCharts.Runtime;
using System;
using System.Linq;
using UnityEngine.UI;

public class ExampleScatterChart : MonoBehaviour
{
    /// <summary>
    /// 测试按钮——画线
    /// </summary>
    public Button StartBtn;

    /// <summary>
    /// 刷新图表
    /// </summary>
    public Button RefreshBtn;

    private void Start()
    {
        #region    ==============代码绑定==============begin   
        //开始画图
        StartBtn.onClick.AddListener(() =>
        {
            DrawScatterFlow();
        });


        //刷新组件
        RefreshBtn.onClick.AddListener(()=> 
        {
            var chart = gameObject.GetComponent<ScatterChart>();
            chart.RefreshAllComponent();
        });
        #endregion ==============代码绑定==============end
    }

    /// <summary>
    /// 绘制散点图的流程
    /// </summary>
    /// <returns></returns>
    private async UniTask DrawScatterFlow()
    {
        //【1】添加一个scatter散点图表
        Debug.Log("添加一个scatter散点图表");
        var chart = gameObject.GetComponent<ScatterChart>();
        if (chart == null)
        {
            chart = gameObject.AddComponent<ScatterChart>();
            chart.Init();
        }

        //【2】设置图表的大小:SetSize(x,y)
        Debug.Log("设置图表的大小(580, 300) ");
        chart.SetSize(580, 300);//代码动态设置尺寸

        Debug.Log("2秒后重新设置大小(1102, 519) ");
        await UniTask.Delay(TimeSpan.FromSeconds(2.0f));
        chart.SetSize(1102, 519);

        //【3】设置标题:chart.Title.text|subText = ""
        Debug.Log("2秒后:设置标题 ");
        await UniTask.Delay(TimeSpan.FromSeconds(2.0f));
        var title = chart.GetOrAddChartComponent<Title>();
        title.text = "森林小气候与碳通量的关系";            //主标题
        title.subText = "温度湿度数据";                     //副标题

        //【4】设置提示框【Tooltip】和图例【Legend】是否显示
        //Tooltip - 鼠标悬停在曲线节点上的时候,显示数据信息 
        //Legend  - 图上数据系列的类别信息【例如[red-白天温度]、[black-晚上温度]】
        Debug.Log("2秒后:设置提示框和图例是否显示");
        await UniTask.Delay(TimeSpan.FromSeconds(2.0f));
        var tooltip = chart.GetOrAddChartComponent<Tooltip>();
        tooltip.show = true;                                //在数据节点上,鼠标悬停时显示的信息框
        var legend = chart.GetOrAddChartComponent<Legend>();
        legend.show = true;

        //【5】设置坐标轴的数据刻度信息
        Debug.Log("2秒后:设置坐标轴");
        await UniTask.Delay(TimeSpan.FromSeconds(2.0f));

        //——x轴设置
        var xAxis = chart.GetOrAddChartComponent<XAxis>();
        xAxis.splitNumber = 24;                            //数据的个数-参数硬编码
        xAxis.boundaryGap = true;
        xAxis.type = Axis.AxisType.Category;

        //——y轴设置
        var yAxis = chart.GetOrAddChartComponent<YAxis>();
        yAxis.type = Axis.AxisType.Value;

        //【6】清空默认数据,添加Scatter类型的Serie用于接收数据
        Debug.Log("2秒后:清空默认数据,添加Scatter类型的Serie用于接收数据");
        await UniTask.Delay(TimeSpan.FromSeconds(2.0f));
        chart.RemoveData();

        //【7】添加数据:X轴的刻度数据,Y轴的数据
        chart.AddSerie<Scatter>("林内温度");
        chart.AddSerie<Scatter>("林外温度");

        Debug.Log("2秒后:添加数据");
        await UniTask.Delay(TimeSpan.FromSeconds(2.0f));
        var series1_24 = Enumerable.Range(1, 24).ToList();
        var xTicks = series1_24.Select(x => $"{x}:00").ToList();
        var yTicks = series1_24.Select(x => UnityEngine.Random.Range(10, 20)).ToList();  //[min,max) 前开后闭
        var yTicks2 = series1_24.Select(x => UnityEngine.Random.Range(10, 20)).ToList();

        //数据添加到图表上
        series1_24.ForEach(idx =>
        {
            chart.AddXAxisData(xTicks[idx - 1]);     //X轴的刻度标签
            chart.AddData(0, yTicks[idx - 1]);       //Y1,第一组数据
            chart.AddData(1, yTicks2[idx - 1]);      //Y2,第二组数据            
        });       

        //【8】x轴刻度标签旋转(倾斜)设置
        Debug.Log("2秒后:x轴刻度标签旋转设置");
        await UniTask.Delay(TimeSpan.FromSeconds(2.0f));
        xAxis.axisLabel.rotate = 45;

        //【9】设置散点的颜色
        Debug.Log("0.4秒后:线条的颜色设置");
        await UniTask.Delay(TimeSpan.FromSeconds(0.4f));
        chart.series[0].itemStyle.color = Color.red;     //第一组散点的颜色 
        chart.series[1].itemStyle.color = Color.green;   //第二组散点的颜色

        //【10】Scatter大小设置:
        await UniTask.Delay(TimeSpan.FromSeconds(2.0f));
        Debug.Log("2秒后:设置散点标记的大小");        
        chart.series[0].symbol.size = 9;
        chart.series[1].symbol.size = 9;

        //【11】画拟合的直线
        await UniTask.Delay(TimeSpan.FromSeconds(2.0f));
        var line1 = chart.AddChartComponent<MarkLine>(); //添加一根直线
        line1.data.Clear();//清空默认值,添加组的时候,会默认包含一个item

        //增加一个端点数据
        var p1 = new MarkLineData();
        p1.type = MarkLineType.None;
        p1.group = 1;
        p1.xPosition = 0;
        p1.yPosition = 0;
        p1.xValue = 0;
        p1.yValue = 15;       
        p1.zeroPosition = false;

        //标注【直线方程式】
        p1.name = "y = 0 * x + 15";
        p1.label.formatter = "{b}";

        //直线的形状设置
        p1.lineStyle.type = LineStyle.Type.Solid;
        p1.startSymbol.type = SymbolType.None;
        p1.endSymbol.type = SymbolType.None;

        //添加第二个端点数据
        var p2 = new MarkLineData();
        p2.type = MarkLineType.None;
        p2.group = 1;
        p2.xPosition = 0;
        p2.yPosition = 0;
        p2.xValue = 23;
        p2.yValue = 15;
        p2.zeroPosition = false;
        p2.name = "y = 0 * x + 15";
        p2.label.formatter = "{b}";

        //直线的形状设置
        p2.lineStyle.type = LineStyle.Type.Solid;
        p2.startSymbol.type = SymbolType.None;
        p2.endSymbol.type = SymbolType.None;

        //端点数据加入直线中
        line1.data.Add(p1);
        line1.data.Add(p2);

        //刷新所有的组件【不刷新的话,发现不能画直线】
        chart.RefreshAllComponent();
    }

#if UNITY_EDITOR
    [ContextMenu("测试")]
#endif
    void Test()
    {
        DrawScatterFlow();
    }
}
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,你可以按照以下步骤在Unity中使用C#代码在RawImage上绘制2D折线: 1. 在场景中创建一个RawImage对象。 2. 在RawImage对象上附加一个CanvasRenderer组件。 3. 在RawImage对象上附加一个RectTransform组件,并将其缩放到所需大小。 4. 在RawImage对象上附加一个空的GameObject,命名为“LineRenderer”。 5. 在“LineRenderer”对象上添加LineRenderer组件。 6. 编写以下C#代码: ``` using UnityEngine; using System.Collections; public class DrawLine : MonoBehaviour { public RawImage rawImage; public LineRenderer lineRenderer; void Start () { lineRenderer = GetComponent<LineRenderer>(); lineRenderer.positionCount = 2; lineRenderer.SetPosition(0, new Vector3(0, 0, 0)); lineRenderer.SetPosition(1, new Vector3(100, 100, 0)); } void Update () { rawImage.texture = RenderTexture.GetTemporary(Screen.width, Screen.height, 16); RenderTexture renderTexture = rawImage.texture as RenderTexture; RenderTexture.active = renderTexture; GL.PushMatrix(); GL.LoadPixelMatrix(0, Screen.width, Screen.height, 0); lineRenderer.SetColors(Color.red, Color.red); lineRenderer.SetWidth(10, 10); lineRenderer.useWorldSpace = false; lineRenderer.material = new Material(Shader.Find("Sprites/Default")); lineRenderer.material.color = Color.red; lineRenderer.SetPosition(0, new Vector3(0, 0, 0)); lineRenderer.SetPosition(1, new Vector3(100, 100, 0)); lineRenderer.enabled = true; lineRenderer.Simplify(0.1f); lineRenderer.useWorldSpace = false; GL.PopMatrix(); RenderTexture.active = null; } } ``` 7. 在Inspector面板上将“RawImage”和“LineRenderer”对象拖动到“DrawLine”脚本中的相应字段中。 8. 运行场景并在RawImage上绘制2D折线。 请注意,这只是一个简单的示例,你可以根据自己的需求进行更改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值