第01章:ScottPlot.NET 折线图

一、概述

本文介绍使用ScottPlot.WPF绘制折线图。

二、折线图

第一步:新建项目

1.新建项目:SPLineDemo

2.添加Nuget包:ScottPlot.WPF

第二步:在MainWindow中编写以下代码

<Window x:Class="SPLineDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="clr-namespace:SPLineDemo"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Title="折线图"
        Width="800"
        Height="450"
        mc:Ignorable="d">
    <Grid>
        <WpfPlot x:Name="plot" />
    </Grid>
</Window>

第三步:在MainWindow.xaml.cs中分别进行各功能的代码演示

1.基础折线图

功能演示
实现代码
using System.Windows;

namespace SPLineDemo
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            InitBasicLineChart();
        }

        // 折线图
        private void InitBasicLineChart()
        {
            // 1.定义数据
            double[] xs = { 1, 2, 3, 4, 5 };
            double[] ys = { 1, 4, 9, 16, 20 };

            // 2.添加折线
            plot.Plot.AddScatterLines(xs, ys);

            // 3.刷新界面
            plot.Refresh();
        }
    }
}

  • 首先用数组的形式定义了数据源,然后调用AddScatterLines将数据源传入,绘制折线,最后调用Refresh方法刷新界面

  • Refresh方法必须调用,否则界面会有警示消息

注:为方便阅读,下面仅展示核心代码,其调用方式与此例无异

2.曲线图

功能演示
实现代码
        // 曲线图
        private void InitSmoothLineChart()
        {
            // 1.定义数据
            double[] xs = { 1, 2, 3, 4, 5 };
            double[] ys = { 1, 4, 9, 16, 20 };

            // 2.添加折线
            var sp = plot.Plot.AddScatterLines(xs, ys);
            sp.Smooth = true; // 指定曲线为平滑曲线

            // 3.刷新界面
            plot.Refresh();
        }
  • 将折线的Smooth属性设置为true,使曲线便平滑

3.折线图-点样式

功能演示
实现代码
        // 折线图-点样式
        private void InitLineWithMarker()
        {
            double[] xs = { 1, 2, 3, 4, 5 };
            double[] ys = { 1, 4, 9, 16, 20 };

            // 添加折线
            plot.Plot.AddScatter(xs, ys);

            plot.Refresh();
        }
  • 之前用AddScatterLines添加无点折线,用AddScatter添加带点的折线

4.折线图-仅绘制点

功能演示
实现代码
        // 折线图-仅绘制点
        private void InitOnlyMarker()
        {
            double[] xs = { 1, 2, 3, 4, 5 };
            double[] ys = { 1, 4, 9, 16, 20 };

            // 仅绘制点
            plot.Plot.AddScatterPoints(xs, ys, Color.Navy, 10, MarkerShape.filledCircle);

            plot.Refresh();
        }
  • 使用AddScatterPoints来绘制点,这其实是散点图了。

5.多折线图

功能演示
实现代码
        // 多折线图
        private void InitMultiLines()
        {
            double[] xs = { 1, 2, 3, 4, 5 };
            double[] ys1 = { 1, 4, 9, 16, 20 };
            double[] ys2 = { 2, 8, 18, 32, 40 };

            // 添加折线1
            plot.Plot.AddScatter(xs, ys1);
            // 添加折线2
            plot.Plot.AddScatter(xs, ys2);

            plot.Refresh();
        }
  • 多次调用AddScatter方法可以添加更多折线

6.自定义点样式

功能演示
实现代码
        // 自定义点样式
        private void InitCustomMarkers()
        {
            double[] xs = { 1, 2, 3, 4, 5 };
            double[] ys1 = { 1, 4, 9, 16, 20 };
            double[] ys2 = { 2, 8, 18, 32, 40 };

            var sp1 = plot.Plot.AddScatter(xs, ys1, markerSize: 8); // markerSize定义marker大小
            sp1.MarkerShape = MarkerShape.openCircle; // 空心圆

            var sp2 = plot.Plot.AddScatter(xs, ys2, markerSize: 6);
            sp2.MarkerShape = MarkerShape.filledSquare; // 实体方

            plot.Refresh();
        }
  • 通过改变MarkerSize属性改变marker的大小

  • 通过改变MarkerShape属性改变marker的样式

  • MarkerShape是个枚举类型,支持样式如下:

7.添加折线图图例

功能演示
实现代码
        // 添加折线图图例
        private void InitLineLegends()
        {
            double[] xs = { 1, 2, 3, 4, 5 };
            double[] ys1 = { 1, 4, 9, 16, 20 };
            double[] ys2 = { 2, 8, 18, 32, 40 };

            var sp1 = plot.Plot.AddScatter(xs, ys1);
            sp1.Label = "折线1"; // 折线1标签
            var sp2 = plot.Plot.AddScatter(xs, ys2);
            sp2.Label = "折线2"; // 折线2标签

            // 添加图例,并设置位置为右下
            var legend = plot.Plot.Legend(location: Alignment.LowerRight);
            legend.FontSize = 10; // 图例字体大小

            plot.Refresh();
        }
  • 首先为折线设置标签名称

  • 然后添加图例,并设置图例的位置

  • 最后设置了图例字体大小

8.折线图样式

功能演示
实现代码
        // 折线图样式
        private void InitLineStyles()
        {
            double[] xs = { 1, 2, 3, 4, 5 };
            double[] ys1 = { 1, 4, 9, 16, 20 };
            double[] ys2 = { 2, 8, 18, 32, 40 };

            // color:颜色,lineWidth:线宽,lineStyle:线样式
            plot.Plot.AddScatter(xs, ys1, color: Color.Blue, lineWidth: 1);
            plot.Plot.AddScatter(xs, ys2, color: Color.Orange, lineWidth: 2, lineStyle: LineStyle.Dash);

            plot.Refresh();
        }
  • 通过设置Color,设置折线颜色

  • 通过设置LineWidth,设置折线宽度

  • 通过设置LineStyle,设置折线样式。LineStyle为枚举,支持样式如下:

9.阶梯折线图

功能演示
实现代码
        // 阶梯折线图
        private void InitStepLines()
        {
            double[] xs = { 1, 2, 3, 4, 5 };
            double[] ys = { 1, 4, 9, 16, 20 };

            // 添加阶梯折线图
            plot.Plot.AddScatterStep(xs, ys);

            plot.Refresh();
        }
  • 通过AddScatterStep方法,添加阶梯折线图

10.可拖动折线图

功能演示
实现代码
        // 可拖动折线图
        private void InitDragLine()
        {
            double[] xs = { 1, 2, 3, 4, 5 };
            double[] ys = { 1, 4, 9, 16, 20 };

            // 添加可拖动折线
            var scatter = new ScottPlot.Plottable.ScatterPlotListDraggable();
            scatter.AddRange(xs, ys);
            plot.Plot.Add(scatter);

            plot.Refresh();
        }

11.折线图动态数据展示

功能演示
实现代码
        // 折线图动态数据展示
        private void InitDynamicDataDisplay()
        {
            var random = new Random();

            var xs = new List<double>();
            var ys = new List<double>();

            plot.Render();

            Task.Factory.StartNew(async () =>
            {
                var index = 5;
                while (true)
                {
                    xs.Add(index++);
                    ys.Add(random.Next(1, 100));

                    plot.Plot.Clear();
                    plot.Plot.AddScatter(xs.ToArray(), ys.ToArray());

                    Dispatcher.Invoke(() => plot.Render());

                    await Task.Delay(300);
                }
            });
        }
  • 核心逻辑便是重绘:清理掉之前的绘制,然后重新绘制折线,达到动态显示的效果。

  • 需要注意的便是Refresh方法必须在UI线程中调用。

12.折线图泛型数据源

功能演示
实现代码
        // 折线图泛型数据源
        private void InitGenric()
        {
            float[] xs = { 1, 2, 3, 4, 5 };
            float[] ys = { 1, 4, 9, 16, 20 };

            // 使用泛型数据
            var scatterList = plot.Plot.AddScatterList<float>();
            scatterList.AddRange(xs, ys);

            plot.Refresh();
        }

三、环境

开发工具:Visual Studio

开发语言:C#

目标框架:.Net 6.0

Nuget包:DynamicDataDisplayReloaded

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容