using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; using Newtonsoft.Json; using SkiaSharp; using UnityEngine; using UnityEngine.UIElements; namespace BITKit.UX { public class SkiaChart : VisualElement { public new class UxmlTraits : VisualElement.UxmlTraits { private readonly UxmlStringAttributeDescription m_JsonAttribute = new () { name = "Json" }; private readonly UxmlBoolAttributeDescription m_allowWarningsAttribute = new () { name = "allowWarnings", defaultValue = false }; public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc) { base.Init(ve, bag, cc); var x = (SkiaChart)ve; x.Json = m_JsonAttribute.GetValueFromBag(bag, cc); x.AllowWarning = m_allowWarningsAttribute.GetValueFromBag(bag, cc); } } public new class UxmlFactory : UxmlFactory { } public SkiaChart() { RegisterCallback(x => { if (visible) { Rebuild(); } }); RegisterCallback(OnCustomStyleResolved); style.flexDirection = FlexDirection.Row; _dataContainer = this.Create(); _chartContainer = this.Create(); _chartContainer.style.flexGrow = 1; _dataContainer.style.justifyContent = Justify.SpaceBetween; _dataContainer.name = "Data"; _chartContainer.name = "Chart"; } private void OnCustomStyleResolved(CustomStyleResolvedEvent evt) { if(evt.customStyle.TryGetValue(new CustomStyleProperty("--chart-secondary-color"), out var helpLineColor)) { _secondaryColor = helpLineColor; } Rebuild(); } public string Json { get => _json; set { _json = value; Rebuild(); } } private string _json; public bool AllowWarning { get; set; } public Color SecondaryColor { get => _secondaryColor; set { _secondaryColor = value; Rebuild(); } } private Color _secondaryColor; private readonly VisualElement _dataContainer; private readonly VisualElement _chartContainer; private void Rebuild() { var data = Array.Empty(); try { data = JsonConvert.DeserializeObject(Json); } catch (Exception e) { if (AllowWarning) Debug.LogException(e); return; } if(float.IsNaN(layout.width) || float.IsNaN(layout.height)) return; if (data is null or { Length: 0 }) return; _dataContainer.Clear(); _chartContainer.Clear(); var max = data.Max(); var min = data.Min(); //假如min是x,max是y,将中间的差用data.Length划分 _dataContainer.style.flexDirection = FlexDirection.ColumnReverse; for (var i = 0; i < data.Length; i++) { var label = _dataContainer.Create