WPF 云图
/// <summary> /// 颜色温度对应表 /// </summary> public class ColorTable { public int Value { get; set; } public int R { get; set; } public int G { get; set; } public int B { get; set; } public double Alpha { get; set; } public ColorTable() { Value = R = G = B = 0; Alpha = 255; } public ColorTable(int value, int r, int g, int b, double alpha = 255) { Value = value; R = r; G = g; B = b; Alpha = alpha; } }
/// <summary> /// 温湿度结构 /// </summary> public class HumiTemp { public HumiTemp() { X = 0; Y = 0; MgrObjId = ""; Id = ""; Value = 0; } public HumiTemp(double x, double y, string mgrobjid, string id, double value = 0) { X = x; Y = y; MgrObjId = mgrobjid; Id = id; Value = value; } public double X { get; set; } public double Y { get; set; } /// <summary> /// 管理对象ID /// </summary> public string MgrObjId { get; set; } /// <summary> /// 属性ID /// </summary> public string Id { get; set; } /// <summary> /// 外部传入值 /// </summary> public double Value { get; set; } }
/// <summary> /// CloudChart.xaml 的交互逻辑 /// </summary> public partial class CloudChart : UserControl { private static readonly DependencyProperty ColorListProperty = DependencyProperty.Register("ColorList", typeof(List<ColorTable>), typeof(CloudChart), new PropertyMetadata(new List<ColorTable>())); private static readonly DependencyProperty HTListProperty = DependencyProperty.Register("HTList", typeof(List<HumiTemp>), typeof(CloudChart), new PropertyMetadata(new List<HumiTemp>())); private static readonly DependencyProperty CabWidthProperty = DependencyProperty.Register("CabWidth", typeof(double), typeof(CloudChart), new PropertyMetadata(double.NaN)); private static readonly DependencyProperty CabHeightProperty = DependencyProperty.Register("CabHeight", typeof(double), typeof(CloudChart), new PropertyMetadata(double.NaN)); public CloudChart() { InitializeComponent(); //SetValue(HTListProperty, new List<HumiTemp>()); //SetValue(ColorListProperty, new List<ColorTable>()); HTList = new List<HumiTemp>(); ColorList = new List<ColorTable>(); } private bool isRealTimeValue; /// <summary> /// 是否是实时值 /// </summary> public bool IsRealTimeValue { get { return isRealTimeValue; } set { isRealTimeValue = value; } } /// <summary> /// 配置信息 /// </summary> public List<HumiTemp> HTList { set { SetValue(HTListProperty, value); } get { return (List<HumiTemp>)GetValue(HTListProperty); } } /// <summary> /// 颜色表 /// </summary> public List<ColorTable> ColorList { set { SetValue(ColorListProperty, value); } get { return (List<ColorTable>)GetValue(ColorListProperty); } } /// <summary> /// 机柜宽度 /// </summary> public double CabWidth { set { SetValue(CabWidthProperty, value); } get { return (double)GetValue(CabWidthProperty); } } /// <summary> /// 机柜高度 /// </summary> public double CabHeight { set { SetValue(CabHeightProperty, value); } get { return (double)GetValue(CabHeightProperty); } } /// <summary> /// 计算每个点的实时值 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="list"></param> /// <returns></returns> private double GetPointRealTimeValue(double x, double y, List<HumiTemp> list) { double R = 0, S = 0; foreach (var ht in list) { double temp = GetRealTimeValue(ht); if (x == ht.X && y == ht.Y) return temp; //计算系数 double ratio = 1 / ((x - ht.X) * (x - ht.X) + (y - ht.Y) * (y - ht.Y)); S += ratio * temp; R += ratio; } return S / R; } /// <summary> /// 读取实时值 /// </summary> /// <param name="ht"></param> /// <returns></returns> private double GetRealTimeValue(HumiTemp ht) { double value; if (double.TryParse(WcfClient.Instance.GetData(ht.MgrObjId, ht.Id), out value)) return value; return double.NaN; } /// <summary> /// 根据外部传入值计算每个点的值 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="list"></param> /// <returns></returns> private double GetPointOutsideValue(double x, double y, List<HumiTemp> list) { double R = 0, S = 0; foreach (var ht in list) { double temp = GetOutsideValue(ht); if (x == ht.X && y == ht.Y) return temp; //计算系数 double ratio = 1 / ((x - ht.X) * (x - ht.X) + (y - ht.Y) * (y - ht.Y)); S += ratio * temp; R += ratio; } return S / R; } /// <summary> /// 读取外部传入值 /// </summary> /// <param name="ht"></param> /// <returns></returns> private double GetOutsideValue(HumiTemp ht) { return ht.Value; } /// <summary> /// 温度(值)转换成颜色值 /// </summary> /// <param name="temperature"></param> /// <returns></returns> private Color ValueToColor(double temperature, List<ColorTable> colorList) { int Tlength = colorList.Count; if (Tlength == 0) return Colors.Red; int i; for (i = 0; i < Tlength; i++) { if (colorList[i].Value > temperature) break; } if (i == 0) return Color.FromRgb((byte)(colorList[0].R), (byte)(colorList[0].G), (byte)(colorList[0].B)); else if (i == Tlength) return Color.FromRgb((byte)(colorList[i - 1].R), (byte)(colorList[i - 1].G), (byte)(colorList[i - 1].B)); double ratio = (temperature - colorList[i - 1].Value) / (colorList[i].Value - colorList[i - 1].Value); int rSpan = colorList[i].R - colorList[i - 1].R; int gSpan = colorList[i].G - colorList[i - 1].G; int bSpan = colorList[i].B - colorList[i - 1].B; double r = (colorList[i - 1].R + rSpan * ratio); double g = (colorList[i - 1].G + gSpan * ratio); double b = (colorList[i - 1].B + bSpan * ratio); return Color.FromRgb((byte)r, (byte)g, (byte)b); } /// <summary> /// 更新界面 /// </summary> public void Update() { Show(); } /// <summary> /// 获取坐标点的值 /// </summary> private double GetData(double x, double y, List<HumiTemp> list) { double ret = 0; if (IsRealTimeValue == true) { ret = GetPointRealTimeValue(x, y, list); } else { ret = GetPointOutsideValue(x, y, list); } return ret; } /// <summary> /// 控件初始化 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void UserControl_Loaded(object sender, RoutedEventArgs e) { if (CabHeight > 0 && CabWidth > 0) { double d1 = Height / CabHeight; double d2 = Width / CabWidth; //取得控件和真实机柜的比例尺 double scale = d1 > d2 ? d2 : d1; img.Height = scale * CabHeight; img.Width = scale * CabWidth; } InitColorTable(); } /// <summary> /// 初始化颜色表 /// </summary> public void InitColorTable() { colorStack.Children.Clear(); ValueStack.Children.Clear(); foreach (ColorTable item in ColorList) { Rectangle rect = new Rectangle(); rect.Width = 25; rect.Height = 25; rect.Fill = new SolidColorBrush(Color.FromRgb((byte)item.R, (byte)item.G, (byte)item.B)); colorStack.Children.Add(rect); Label lb = new Label(); lb.Width = 25; lb.Height = 25; lb.Content = item.Value; ValueStack.Children.Add(lb); } } /// <summary> /// 显示云图 /// </summary> private void Show() { if (double.IsNaN(img.Width) || img.Width == 0 || double.IsNaN(img.Height) || img.Height == 0) { UserControl_Loaded(this, new RoutedEventArgs()); } //防止用户并未初始化 if (!double.IsNaN(img.Width) && !double.IsNaN(img.Height)) { // Create the bitmap, with the dimensions of the image placeholder. WriteableBitmap wb = new WriteableBitmap((int)img.Width, (int)img.Height, 96, 96, PixelFormats.Bgra32, null); // Define the update square (which is as big as the entire image). Int32Rect rect = new Int32Rect(0, 0, (int)img.Width, (int)img.Height); byte[] pixels = new byte[(int)img.Width * (int)img.Height * wb.Format.BitsPerPixel / 8]; for (int y = 0; y < wb.PixelHeight; y++) { for (int x = 0; x < wb.PixelWidth; x++) { int alpha = 255; int red = 0; int green = 0; int blue = 0; double value = GetData(x, y, HTList); Color c = ValueToColor(value,ColorList); red = c.R; green = c.G; blue = c.B; int pixelOffset = (x + (wb.PixelHeight - y - 1) * wb.PixelWidth) * wb.Format.BitsPerPixel / 8; pixels[pixelOffset] = (byte)blue; pixels[pixelOffset + 1] = (byte)green; pixels[pixelOffset + 2] = (byte)red; pixels[pixelOffset + 3] = (byte)alpha; } int stride = (wb.PixelWidth * wb.Format.BitsPerPixel) / 8; wb.WritePixels(rect, pixels, stride, 0); } // Show the bitmap in an Image element. img.Source = wb; } } }
<UserControl x:Class="MobileHT.CloudChart" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" Loaded="UserControl_Loaded" d:DesignHeight="600" d:DesignWidth="400" Width="400" Height="600"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="26"></RowDefinition> <RowDefinition Height="26"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <Image Grid.Row="3" Name="img" IsHitTestVisible="False" Margin="2" ></Image> <StackPanel Name="colorStack" Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="0" Margin="2"> </StackPanel> <StackPanel Name="ValueStack" Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="1" Margin="2"> </StackPanel> </Grid> </UserControl>
获取数据有使用外部DLL,可参考以上代码,做任何值的云图。(上述为温度云图或者湿度云图)
效果图:
效果图配置代码:
<my:CloudChart x:Name="cloud2" Height="300" Width="200" CabHeight="300" CabWidth="200" IsRealTimeValue="False" Margin="365,85,53,294"> <my:CloudChart.HTList> <my:HumiTemp Id="0" MgrObjId="0" /> <my:HumiTemp Id="1" MgrObjId="1" X="20" Y="30" Value="19"/> <my:HumiTemp Id="2" MgrObjId="2" X="30" Y="60" Value="20"/> <my:HumiTemp Id="3" MgrObjId="3" X="40" Y="90" Value="21"/> <my:HumiTemp Id="4" MgrObjId="4" X="50" Y="100" Value="22"/> <my:HumiTemp Id="5" MgrObjId="5" X="60" Y="110" Value="27"/> <my:HumiTemp Id="6" MgrObjId="6" X="80" Y="120" Value="24"/> <my:HumiTemp Id="7" MgrObjId="7" X="100" Y="130" Value="25"/> <my:HumiTemp Id="8" MgrObjId="8" X="120" Y="150" Value="26"/> <my:HumiTemp Id="9" MgrObjId="9" X="140" Y="160" Value="28"/> <my:HumiTemp Id="9" MgrObjId="9" X="160" Y="200" Value="30"/> <my:HumiTemp Id="9" MgrObjId="9" X="180" Y="230" Value="33"/> <my:HumiTemp Id="9" MgrObjId="9" X="270" Y="200" Value="35"/> </my:CloudChart.HTList> <my:CloudChart.ColorList> <my:ColorTable Value="19" R="0" G="0" B="255" Alpha="255"></my:ColorTable> <my:ColorTable Value="22" R="100" G="149" B="237" Alpha="255"></my:ColorTable> <my:ColorTable Value="25" R="100" G="100" B="220" Alpha="255"></my:ColorTable> <my:ColorTable Value="28" R="127" G="0" B="212" Alpha="255"></my:ColorTable> <my:ColorTable Value="30" R="173" G="255" B="47" Alpha="255"></my:ColorTable> <my:ColorTable Value="32" R="255" G="165" B="0" Alpha="255"></my:ColorTable> <my:ColorTable Value="35" R="255" G="69" B="0" Alpha="255"></my:ColorTable> </my:CloudChart.ColorList> </my:CloudChart>