WPF數據可視化-瀑布圖

實現方式一:微信

       將數據(Point[])根據索引沿X軸使用虛擬畫布進行繪製,每一個數據繪製大小爲1px * 1px;最終繪製出的寬度等於數據的總長度。標記並存儲當前繪製的圖爲PreviousBitmap; 繼續置頂繪製第二組數據,第二組數據繪製完後,將標記的PreviousBitmap做爲Image在Y軸距離頂部距離爲1px的地方用DrawingContext.DrawImage()方式繪製,以此類推。核心代碼以下:app

private void DoAddDataArray(Point[] arrPoints)
{
    this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
    {
        double dPixelWidth = Pixel;
        double dContainerWidth = this.VbxContainer.ActualWidth;
        double dContainerHeight = this.VbxContainer.ActualHeight;
        double dPixelHeight = Pixel/2d;
        double dCellHeight = 1;
        double dCellWidth = 1;

        DrawingVisual drawingVisual = new DrawingVisual();
        DrawingContext drawingContext = drawingVisual.RenderOpen();
        drawingContext.DrawRectangle(new SolidColorBrush(Colors.Blue),
                new Pen(), new Rect(0, 0, dPixelWidth, dCellHeight));

        // 繪製新數據
                  
        for (int i = 0; i < arrPoints.Length; i++)
        {
            double dCellX = Math.Round(((arrPoints[i].X - MinAxisX) / (MaxAxisX - MinAxisX)) * Pixel);
            double dY = arrPoints[i].Y;
            Color oColor = this.GetColor(dY);
            //drawingContext.DrawRectangle(new SolidColorBrush(oColor),
            //    new Pen(), new Rect(dCellX, 0, dCellWidth, dCellHeight));
            LinearGradientBrush lineBrush = new LinearGradientBrush();
            lineBrush.GradientStops.Add(new GradientStop(Colors.Transparent, 0));
            lineBrush.GradientStops.Add(new GradientStop(oColor, 0.25));
            lineBrush.GradientStops.Add(new GradientStop(oColor, 0.5));
            lineBrush.GradientStops.Add(new GradientStop(oColor, 0.75));
            lineBrush.GradientStops.Add(new GradientStop(Colors.Transparent, 1));
            drawingContext.DrawRectangle(lineBrush, new Pen(), new Rect(dCellX-1, 0, dCellWidth + 2, dCellHeight));
        }    

        // 繪製歷史數據
        if (this.PreviousBitmap != null)
            drawingContext.DrawImage(this.PreviousBitmap, new Rect(0, dCellHeight, dPixelWidth, dPixelHeight));
        drawingContext.Close();

        // 生成圖像處理
        RenderTargetBitmap rtbCurrent = new RenderTargetBitmap((int)dPixelWidth,
            (int)dPixelHeight, 96, 96, PixelFormats.Pbgra32);
        rtbCurrent.Render(drawingVisual);

        this.PreviousBitmap = rtbCurrent; // 當前繪製的存爲歷史,下次繪製時直接調用
        this.ImgMain.Source = rtbCurrent; // 顯示繪製的圖像
    }));
}

運行效果工具

 

實現方式二:性能

        將數據(Point[])根據索引沿X軸使用虛擬畫布進行繪製,每一個數據繪製大小爲1px * 1px;最終繪製出的寬度等於數據的總長度。建立一個Rectangle,將繪製的圖賦值給Rectangle.Fill屬性,將繪製過程當中不斷建立的Rectangle插入控件Stackpanel的首位。核心代碼以下:測試

private void DoAddDataArray(Point[] arrPoints)
{
    this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => 
    {
        double dPixelWidth = Pixel;
        double dContainerWidth = this.VbxContainer.ActualWidth;
        double dContainerHeight = this.VbxContainer.ActualHeight;
        double dPixelHeight = Pixel / 2d;

        DrawingVisual drawingVisual = new DrawingVisual();
        DrawingContext drawingContext = drawingVisual.RenderOpen();
        drawingContext.DrawRectangle(new SolidColorBrush(Colors.Blue),
                new Pen(), new Rect(0, 0, dPixelWidth, 1));

        // 繪製新數據
        double dCellHeight = 1;
        double dCellWidth = 1;
        for (int i = 0; i < arrPoints.Length; i++)
        {
            double dCellX = Math.Round(((arrPoints[i].X - MinAxisX) / (MaxAxisX - MinAxisX)) * Pixel);
            double dY = arrPoints[i].Y;
            Color oColor = this.GetColor(dY);
            //drawingContext.DrawRectangle(new SolidColorBrush(oColor),
            //    new Pen(), new Rect(dCellX, 0, dCellWidth, dCellHeight));
            LinearGradientBrush lineBrush = new LinearGradientBrush();
            lineBrush.GradientStops.Add(new GradientStop(Colors.Transparent, 0));
            lineBrush.GradientStops.Add(new GradientStop(oColor, 0.25));
            lineBrush.GradientStops.Add(new GradientStop(oColor, 0.5));
            lineBrush.GradientStops.Add(new GradientStop(oColor, 0.75));
            lineBrush.GradientStops.Add(new GradientStop(Colors.Transparent, 1));
            drawingContext.DrawRectangle(lineBrush, new Pen(), new Rect(dCellX - 0.5, 0, dCellWidth + 1, dCellHeight));
        }
        drawingContext.Close();

        // 生成圖像處理
        RenderTargetBitmap rtbCurrent = new RenderTargetBitmap((int)dPixelWidth, (int)1, 96, 96, PixelFormats.Pbgra32);
        rtbCurrent.Render(drawingVisual);

        Rectangle rect = new Rectangle();
        rect.Width = Pixel;
        rect.Height = 1;
        rect.Fill = new ImageBrush(rtbCurrent);
        // SpContainers  ---- Stackpanel
        this.SpContainers.Children.Insert(0, rect);
        if (this.SpContainers.Children.Count > 500)
            this.SpContainers.Children.RemoveAt(500);
    }));
}

 運行效果:this

相對而言,方式二因爲不斷插入新的Rectangle。下移效果爲控件位置變化所呈現,不像方式一是一張完整圖,故畫質欠缺。 spa

性能和測試: 插件

       採用Timer生成隨機數據進行測試。10毫秒1組,每組1000個數據點。 至關於每秒繪製10萬個點。3d

測試時在Release模式下,開啓多個子模塊,性能勉強能接受。 code

環境:

 語言: C#

 工程:WPF

 工具:Visual Studio 2017

 系統:Windows

 第三方插件:無

            微信掃碼下載源代碼:

相關文章
相關標籤/搜索