0%

.NET开源、功能强大、跨平台的图表库 - LiveCharts2 - 追逐时光者 - 博客园

Excerpt

前言 今天大姚给大家分享一个.NET开源(MIT License)、功能强大、简单、灵活、跨平台的图表、地图和仪表库:LiveCharts2。 项目介绍 LiveCharts2是一个.NET开源、简单、灵活、交互式且功能强大的.NET图表、地图和仪表,现在几乎可以在任何地方运行如:Maui、Uno


思维导航

前言

今天大姚给大家分享一个.NET开源(MIT License)、功能强大、简单、灵活、跨平台的图表、地图和仪表库:LiveCharts2。

 

项目介绍

LiveCharts2是一个.NET开源、简单、灵活、交互式且功能强大的.NET图表、地图和仪表,现在几乎可以在任何地方运行如:Maui、Uno Platform、Blazor-wasm、WPF、WinForms、Xamarin、Avalonia、WinUI、UWP。

项目源代码

Blazor Wasm中快速使用

创建Blazor WebAssembly项目

安装NuGet

1
<span data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/9M0PhLTmTIfnJACqtiacDthGHw41mFQWicrBGYYWQ04Qt99XiauHyhwtaxyFHrKXcYpn6Uficdtz8D1GDjW1CKp7dtIMhGgBnPOQ/640?wx_fmt=svg&amp;from=appmsg" data-fail="0" highlighted="true"><code>NuGet包管理器中搜索:LiveChartsCore.SkiaSharpView.Blazor 点击安装。</code></span>

 注意:该包目前仍处于预发行阶段,尚未有正式版,很多同学反馈说找不到,是因为没有勾选:包括预发行版

Basic Bars

View Model

1
<span data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/9M0PhLTmTIfnJACqtiacDthGHw41mFQWicrBGYYWQ04Qt99XiauHyhwtaxyFHrKXcYpn6Uficdtz8D1GDjW1CKp7dtIMhGgBnPOQ/640?wx_fmt=svg&amp;from=appmsg" data-fail="0" highlighted="true"><code>using&nbsp;CommunityToolkit.Mvvm.ComponentModel;<br>using&nbsp;LiveChartsCore;<br>using&nbsp;LiveChartsCore.SkiaSharpView;<br>using&nbsp;LiveChartsCore.SkiaSharpView.Painting;<br>using&nbsp;SkiaSharp;<br><br>namespace&nbsp;ViewModelsSamples.Bars.Basic;<br><br>public&nbsp;partial&nbsp;class&nbsp;ViewModel&nbsp;:&nbsp;ObservableObject<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ISeries[]&nbsp;Series&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}&nbsp;=<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;ColumnSeries&lt;double&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;=&nbsp;"Mary",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Values&nbsp;=&nbsp;new&nbsp;double[]&nbsp;{&nbsp;2,&nbsp;5,&nbsp;4&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;ColumnSeries&lt;double&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;=&nbsp;"Ana",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Values&nbsp;=&nbsp;new&nbsp;double[]&nbsp;{&nbsp;3,&nbsp;1,&nbsp;6&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;};<br><br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Axis[]&nbsp;XAxes&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}&nbsp;=<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;Axis<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Labels&nbsp;=&nbsp;new&nbsp;string[]&nbsp;{&nbsp;"Category&nbsp;1",&nbsp;"Category&nbsp;2",&nbsp;"Category&nbsp;3"&nbsp;},<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LabelsRotation&nbsp;=&nbsp;0,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SeparatorsPaint&nbsp;=&nbsp;new&nbsp;SolidColorPaint(new&nbsp;SKColor(200,&nbsp;200,&nbsp;200)),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SeparatorsAtCenter&nbsp;=&nbsp;false,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TicksPaint&nbsp;=&nbsp;new&nbsp;SolidColorPaint(new&nbsp;SKColor(35,&nbsp;35,&nbsp;35)),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TicksAtCenter&nbsp;=&nbsp;true,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;By&nbsp;default&nbsp;the&nbsp;axis&nbsp;tries&nbsp;to&nbsp;optimize&nbsp;the&nbsp;number&nbsp;of&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;labels&nbsp;to&nbsp;fit&nbsp;the&nbsp;available&nbsp;space,&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;when&nbsp;you&nbsp;need&nbsp;to&nbsp;force&nbsp;the&nbsp;axis&nbsp;to&nbsp;show&nbsp;all&nbsp;the&nbsp;labels&nbsp;then&nbsp;you&nbsp;must:&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ForceStepToMin&nbsp;=&nbsp;true,&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MinStep&nbsp;=&nbsp;1&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;};<br>}<br></code></span>

HTML

1
<span data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/9M0PhLTmTIfnJACqtiacDthGHw41mFQWicrBGYYWQ04Qt99XiauHyhwtaxyFHrKXcYpn6Uficdtz8D1GDjW1CKp7dtIMhGgBnPOQ/640?wx_fmt=svg&amp;from=appmsg" data-fail="0" highlighted="true"><code>@page&nbsp;"/Bars/Basic"<br>@using&nbsp;LiveChartsCore.SkiaSharpView.Blazor<br>@using&nbsp;ViewModelsSamples.Bars.Basic<br><br>&lt;CartesianChart<br>&nbsp;Series="ViewModel.Series"<br>&nbsp;XAxes="ViewModel.XAxes"<br>&nbsp;LegendPosition="LiveChartsCore.Measure.LegendPosition.Right"&gt;<br>&lt;/CartesianChart&gt;<br><br>@code&nbsp;{<br>&nbsp;public&nbsp;ViewModel&nbsp;ViewModel&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}&nbsp;=&nbsp;new();<br>}<br></code></span>

Delayed Animations

View model

1
<span data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/9M0PhLTmTIfnJACqtiacDthGHw41mFQWicrBGYYWQ04Qt99XiauHyhwtaxyFHrKXcYpn6Uficdtz8D1GDjW1CKp7dtIMhGgBnPOQ/640?wx_fmt=svg&amp;from=appmsg" data-fail="0" highlighted="true"><code>using&nbsp;System;<br>using&nbsp;System.Collections.Generic;<br>using&nbsp;CommunityToolkit.Mvvm.ComponentModel;<br>using&nbsp;LiveChartsCore;<br>using&nbsp;LiveChartsCore.Drawing;<br>using&nbsp;LiveChartsCore.Kernel;<br>using&nbsp;LiveChartsCore.SkiaSharpView;<br>using&nbsp;LiveChartsCore.SkiaSharpView.Drawing.Geometries;<br><br>namespace&nbsp;ViewModelsSamples.Bars.DelayedAnimation;<br><br>public&nbsp;partial&nbsp;class&nbsp;ViewModel&nbsp;:&nbsp;ObservableObject<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ViewModel()<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;values1&nbsp;=&nbsp;new&nbsp;List&lt;float&gt;();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;values2&nbsp;=&nbsp;new&nbsp;List&lt;float&gt;();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;fx&nbsp;=&nbsp;EasingFunctions.BounceInOut;&nbsp;//&nbsp;this&nbsp;is&nbsp;the&nbsp;function&nbsp;we&nbsp;are&nbsp;going&nbsp;to&nbsp;plot<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;x&nbsp;=&nbsp;0f;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(x&nbsp;&lt;=&nbsp;1)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;values1.Add(fx(x));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;values2.Add(fx(x&nbsp;-&nbsp;0.15f));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;+=&nbsp;0.025f;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;columnSeries1&nbsp;=&nbsp;new&nbsp;ColumnSeries&lt;float&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Values&nbsp;=&nbsp;values1,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Stroke&nbsp;=&nbsp;null,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Padding&nbsp;=&nbsp;2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;columnSeries2&nbsp;=&nbsp;new&nbsp;ColumnSeries&lt;float&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Values&nbsp;=&nbsp;values2,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Stroke&nbsp;=&nbsp;null,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Padding&nbsp;=&nbsp;2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columnSeries1.PointMeasured&nbsp;+=&nbsp;OnPointMeasured;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columnSeries2.PointMeasured&nbsp;+=&nbsp;OnPointMeasured;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Series&nbsp;=&nbsp;new&nbsp;List&lt;ISeries&gt;&nbsp;{&nbsp;columnSeries1,&nbsp;columnSeries2&nbsp;};<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;void&nbsp;OnPointMeasured(ChartPoint&lt;float,&nbsp;RoundedRectangleGeometry,&nbsp;LabelGeometry&gt;&nbsp;point)<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;perPointDelay&nbsp;=&nbsp;100;&nbsp;//&nbsp;milliseconds<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;delay&nbsp;=&nbsp;point.Context.Entity.MetaData!.EntityIndex&nbsp;*&nbsp;perPointDelay;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;speed&nbsp;=&nbsp;(float)point.Context.Chart.AnimationsSpeed.TotalMilliseconds&nbsp;+&nbsp;delay;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;point.Visual?.SetTransition(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;Animation(progress&nbsp;=&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;d&nbsp;=&nbsp;delay&nbsp;/&nbsp;speed;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;progress&nbsp;&lt;=&nbsp;d<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?&nbsp;0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;EasingFunctions.BuildCustomElasticOut(1.5f,&nbsp;0.60f)((progress&nbsp;-&nbsp;d)&nbsp;/&nbsp;(1&nbsp;-&nbsp;d));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TimeSpan.FromMilliseconds(speed)));<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;List&lt;ISeries&gt;&nbsp;Series&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}<br>}<br></code></span>

HTML

1
<span data-lazy-bgimg="https://mmbiz.qpic.cn/mmbiz_svg/9M0PhLTmTIfnJACqtiacDthGHw41mFQWicrBGYYWQ04Qt99XiauHyhwtaxyFHrKXcYpn6Uficdtz8D1GDjW1CKp7dtIMhGgBnPOQ/640?wx_fmt=svg&amp;from=appmsg" data-fail="0" highlighted="true"><code>@page&nbsp;"/Bars/DelayedAnimation"<br>@using&nbsp;LiveChartsCore.SkiaSharpView.Blazor<br>@using&nbsp;ViewModelsSamples.Bars.DelayedAnimation<br><br>&lt;CartesianChart<br>&nbsp;Series="ViewModel.Series"&gt;<br>&lt;/CartesianChart&gt;<br><br>@code&nbsp;{<br>&nbsp;public&nbsp;ViewModel&nbsp;ViewModel&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}&nbsp;=&nbsp;new();<br>}<br></code></span>

项目更多图表截图

项目源码地址

更多项目实用功能和特性欢迎前往项目开源地址查看👀,别忘了给项目一个Star支持💖。

优秀项目和框架精选

该项目已收录到C#/.NET/.NET Core优秀项目和框架精选中,关注优秀项目和框架精选能让你及时了解C#、.NET和.NET Core领域的最新动态和最佳实践,提高开发工作效率和质量。坑已挖,欢迎大家踊跃提交PR推荐或自荐(让优秀的项目和框架不被埋没🤞)。

DotNetGuide技术社区交流群

  • DotNetGuide技术社区是一个面向.NET开发者的开源技术社区,旨在为开发者们提供全面的C#/.NET/.NET Core相关学习资料、技术分享和咨询、项目框架推荐、求职和招聘资讯、以及解决问题的平台。
  • 在DotNetGuide技术社区中,开发者们可以分享自己的技术文章、项目经验、学习心得、遇到的疑难技术问题以及解决方案,并且还有机会结识志同道合的开发者。
  • 我们致力于构建一个积极向上、和谐友善的.NET技术交流平台。无论您是初学者还是有丰富经验的开发者,我们都希望能为您提供更多的价值和成长机会。

欢迎加入DotNetGuide技术社区微信交流群👪