- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
。
源码地址: https://gitee.com/LiuShuiRuoBing/code_blog 。
public IEnumerable< double > LayersPercentList { get { return (IEnumerable< double > )GetValue(LayersPercentListProperty); } set { SetValue(LayersPercentListProperty, value); } } // Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc... public static readonly DependencyProperty LayersPercentListProperty = DependencyProperty.Register( " LayersPercentList " , typeof (IEnumerable< double >), typeof (RadarMapUserControl), new FrameworkPropertyMetadata( null , new PropertyChangedCallback(OnChangedToRefreshRadarMap)));
。
<UserControl x:Class= " MT.CustomUserControl.Views.UserControls.RadarMapUserControl " 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 " xmlns:local = " clr-namespace:MT.CustomUserControl.Views.UserControls " mc:Ignorable = " d " d:Background = " White " SizeChanged = " RadarMapUserControl_SizeChanged " > <!--雷达图--> <Grid x:Name= " Grid_RadarMap " HorizontalAlignment= " Center " VerticalAlignment= " Center " MinWidth= " 300 " MinHeight= " 300 " Margin= " 200 " SizeChanged= " RadarMapUserControl_SizeChanged " /> </UserControl>
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Shapes; namespace MT.CustomUserControl.Views.UserControls { /// <summary> /// QSCC_RadarMapUserControl.xaml 的交互逻辑 /// </summary> public partial class RadarMapUserControl : UserControl { #region 私有属性,用于绘图 /// <summary> /// 每个扇区的角度 /// </summary> private double Angle { set ; get ; } /// <summary> /// 用于绘制雷达图的层数的多边形 /// </summary> private List<Polygon> RadarMapLayersPolygon = new List<Polygon> (); /// <summary> /// 用于绘制雷达图的射线 /// </summary> private List<Polyline> RadarMapRadialsPolyline = new List<Polyline> (); /// <summary> /// 用于绘制雷达图射线上实际值的圆点,使用多边形绘制,以实际值为圆心扩展多变形 /// </summary> private List<Polygon> RadarMapRadialsValuesPolygons = new List<Polygon> (); /// <summary> /// 所有的雷达图的多变形 /// </summary> private Polygon RadarMapRadialsValuesPolygon = new Polygon(); #endregion #region 雷达图图层 /// <summary> /// 雷达图的层数 /// </summary> public int Layers { get { return ( int )GetValue(LayersProperty); } set { if (value < 1 ) value = 1 ; SetValue(LayersProperty, value); } } // Using a DependencyProperty as the backing store for Layers. This enables animation, styling, binding, etc... public static readonly DependencyProperty LayersProperty = DependencyProperty.Register( " Layers " , typeof ( int ), typeof (RadarMapUserControl), new PropertyMetadata( 4 , new PropertyChangedCallback(OnCurrentLayersChanged))); private static void OnCurrentLayersChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { RadarMapUserControl userControl = (RadarMapUserControl)d; bool needRefresh = false ; if (userControl.RadarMapLayersPolygon.Count > userControl.Layers) { int nCnt = userControl.RadarMapLayersPolygon.Count - userControl.Layers; userControl.RadarMapLayersPolygon.RemoveRange(userControl.RadarMapLayersPolygon.Count - 1 - nCnt, nCnt); needRefresh = true ; } else if (userControl.RadarMapLayersPolygon.Count < userControl.Layers) { int nCnt = userControl.Layers - userControl.RadarMapLayersPolygon.Count; for ( int i = 0 ; i < nCnt; i++ ) { userControl.RadarMapLayersPolygon.Add( new Polygon() { Stroke = userControl.LayerStroke, StrokeThickness = 1 }); } needRefresh = true ; } if (needRefresh) { userControl.RefreshRadarMap(); } } /// <summary> /// 雷达图分层的规则,这里使用0-1之间的数据标识,主要是用比例来表示 /// 在使用者未指定的情况下,则根据Layers的层数来均分 /// 设置举例:雷达图分4层,均分每层面积,则LayersPercentList设置为: /// LayersPercentList[0] = 0.25; /// LayersPercentList[1] = 0.5; /// LayersPercentList[2] = 0.75; /// LayersPercentList[3] = 1; /// </summary> public IEnumerable< double > LayersPercentList { get { return (IEnumerable< double > )GetValue(LayersPercentListProperty); } set { SetValue(LayersPercentListProperty, value); } } // Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc... public static readonly DependencyProperty LayersPercentListProperty = DependencyProperty.Register( " LayersPercentList " , typeof (IEnumerable< double >), typeof (RadarMapUserControl), new FrameworkPropertyMetadata( null , new PropertyChangedCallback(OnChangedToRefreshRadarMap))); /// <summary> /// 每层边框的粗细 /// </summary> public double LayerStrokeThickness { get { return ( double )GetValue(LayerStrokeThicknessProperty); } set { SetValue(LayerStrokeThicknessProperty, value); } } // Using a DependencyProperty as the backing store for LayerStrokeThickness. This enables animation, styling, binding, etc... public static readonly DependencyProperty LayerStrokeThicknessProperty = DependencyProperty.Register( " LayerStrokeThickness " , typeof ( double ), typeof (RadarMapUserControl), new PropertyMetadata( 1.0 , new PropertyChangedCallback(OnCurrentLayersFillBrushAndStockThicknessChanged))); /// <summary> /// 每层的边框颜色 /// </summary> public SolidColorBrush LayerStroke { get { return (SolidColorBrush)GetValue(LayerStrokeProperty); } set { SetValue(LayerStrokeProperty, value); } } // Using a DependencyProperty as the backing store for LayerStroke. This enables animation, styling, binding, etc... public static readonly DependencyProperty LayerStrokeProperty = DependencyProperty.Register( " LayerStroke " , typeof (SolidColorBrush), typeof (RadarMapUserControl), new PropertyMetadata(Brushes.White, new PropertyChangedCallback(OnCurrentLayersFillBrushAndStockThicknessChanged))); /// <summary> /// 雷达图从内到外渐变色,内部颜色 /// </summary> public Color InnerColor { get { return (Color)GetValue(InnerColorProperty); } set { SetValue(InnerColorProperty, value); } } // Using a DependencyProperty as the backing store for InnerColor. This enables animation, styling, binding, etc... public static readonly DependencyProperty InnerColorProperty = DependencyProperty.Register( " InnerColor " , typeof (Color), typeof (RadarMapUserControl), new PropertyMetadata(Colors.White, new PropertyChangedCallback(OnCurrentLayersFillBrushAndStockThicknessChanged))); /// <summary> /// 雷达图从内到外渐变色,外部颜色 /// </summary> public Color OutColor { get { return (Color)GetValue(OutColorProperty); } set { SetValue(OutColorProperty, value); } } // Using a DependencyProperty as the backing store for OutColor. This enables animation, styling, binding, etc... public static readonly DependencyProperty OutColorProperty = DependencyProperty.Register( " OutColor " , typeof (Color), typeof (RadarMapUserControl), new PropertyMetadata(Colors.Purple, new PropertyChangedCallback(OnCurrentLayersFillBrushAndStockThicknessChanged))); private static void OnCurrentLayersFillBrushAndStockThicknessChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { RadarMapUserControl userControl = (RadarMapUserControl)d; userControl.RefreshLayersFillBrushAndThickness(); } #endregion #region 雷达图射线 /// <summary> /// 雷达图的射线数 /// </summary> public int Radials { get { return ( int )GetValue(RadialsProperty); } set { SetValue(RadialsProperty, value); } } // Using a DependencyProperty as the backing store for Radials. This enables animation, styling, binding, etc... public static readonly DependencyProperty RadialsProperty = DependencyProperty.Register( " Radials " , typeof ( int ), typeof (RadarMapUserControl), new PropertyMetadata( 9 , new PropertyChangedCallback(OnCurrentRadialsChanged))); private static void OnCurrentRadialsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { RadarMapUserControl userControl = (RadarMapUserControl)d; bool needRefresh = false ; if (userControl.RadarMapRadialsPolyline.Count > userControl.Radials) { int nCnt = userControl.RadarMapRadialsPolyline.Count - userControl.Radials; userControl.RadarMapRadialsPolyline.RemoveRange(userControl.RadarMapRadialsPolyline.Count - 1 - nCnt, nCnt); needRefresh = true ; } else if (userControl.RadarMapRadialsPolyline.Count < userControl.Radials) { int nCnt = userControl.Radials - userControl.RadarMapRadialsPolyline.Count; for ( int i = 0 ; i < nCnt; i++ ) { userControl.RadarMapRadialsPolyline.Add( new Polyline() { Stroke = userControl.RadialBrush, StrokeThickness = 2 }); } needRefresh = true ; } if (userControl.RadarMapRadialsValuesPolygons.Count > userControl.Radials) { int nCnt = userControl.RadarMapRadialsValuesPolygons.Count - userControl.Radials; userControl.RadarMapRadialsValuesPolygons.RemoveRange(userControl.RadarMapRadialsValuesPolygons.Count - 1 - nCnt, nCnt); needRefresh = true ; } else if (userControl.RadarMapRadialsValuesPolygons.Count < userControl.Radials) { int nCnt = userControl.Radials - userControl.RadarMapRadialsValuesPolygons.Count; for ( int i = 0 ; i < nCnt; i++ ) { userControl.RadarMapRadialsValuesPolygons.Add( new Polygon() { Stroke = userControl.LayerStroke, StrokeThickness = 1 }); } needRefresh = true ; } if (needRefresh) userControl.RefreshRadarMap(); } /// <summary> /// 雷达图半径,决定雷达图的半径 /// </summary> public double Radius { get { return ( double )GetValue(RadiusProperty); } set { SetValue(RadiusProperty, value); } } // Using a DependencyProperty as the backing store for Radius. This enables animation, styling, binding, etc... public static readonly DependencyProperty RadiusProperty = DependencyProperty.Register( " Radius " , typeof ( double ), typeof (RadarMapUserControl), new PropertyMetadata( 100.0 , new PropertyChangedCallback(OnChangedToRefreshRadarMap))); /// <summary> /// 射线颜色 /// </summary> public SolidColorBrush RadialBrush { get { return (SolidColorBrush)GetValue(RadialBrushProperty); } set { SetValue(RadialBrushProperty, value); } } // Using a DependencyProperty as the backing store for RadialBrush. This enables animation, styling, binding, etc... public static readonly DependencyProperty RadialBrushProperty = DependencyProperty.Register( " RadialBrush " , typeof (SolidColorBrush), typeof (RadarMapUserControl), new PropertyMetadata(Brushes.White, new PropertyChangedCallback(OnCurrentRadialBrushAndThicknessChanged))); /// <summary> /// 射线粗细 /// </summary> public double RadialThickness { get { return ( double )GetValue(RadialThicknessProperty); } set { SetValue(RadialThicknessProperty, value); } } // Using a DependencyProperty as the backing store for RadialThickness. This enables animation, styling, binding, etc... public static readonly DependencyProperty RadialThicknessProperty = DependencyProperty.Register( " RadialThickness " , typeof ( double ), typeof (RadarMapUserControl), new PropertyMetadata( 1.5 , new PropertyChangedCallback(OnCurrentRadialBrushAndThicknessChanged))); private static void OnCurrentRadialBrushAndThicknessChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { RadarMapUserControl userControl = (RadarMapUserControl)d; userControl.RefreshRadialBrushAndThinkness(); } #endregion #region 雷达图上点 /// <summary> /// 射线上的所有值点 /// 1. 注意在使用绑定时,要先将Binding对象设置为null,然后将数据整合好的ObservableCollection再赋值给绑定对象,否则不更新 /// </summary> public IEnumerable< double > Values { get { return (IEnumerable< double > )GetValue(ValuesProperty); } set { SetValue(ValuesProperty, value); } } // Using a DependencyProperty as the backing store for Values. This enables animation, styling, binding, etc... public static readonly DependencyProperty ValuesProperty = DependencyProperty.Register( " Values " , typeof (IEnumerable< double >), typeof (RadarMapUserControl), new FrameworkPropertyMetadata( null , new PropertyChangedCallback(OnChangedToRefreshValues))); private static void OnChangedToRefreshValues(DependencyObject d, DependencyPropertyChangedEventArgs e) { RadarMapUserControl userControl = (RadarMapUserControl)d; userControl.DrawRadarMapRadialsValues(); } /// <summary> /// 普通值点的绘制半径 /// </summary> public double ValueRadius { get { return ( double )GetValue(ValueRadiusProperty); } set { SetValue(ValueRadiusProperty, value); } } // Using a DependencyProperty as the backing store for ValueRadius. This enables animation, styling, binding, etc... public static readonly DependencyProperty ValueRadiusProperty = DependencyProperty.Register( " ValueRadius " , typeof ( double ), typeof (RadarMapUserControl), new PropertyMetadata( 4.0 , new PropertyChangedCallback(OnChangedToRefreshValueRadiusAndBrush))); /// <summary> /// 普通值点的颜色 /// </summary> public SolidColorBrush ValueBrush { get { return (SolidColorBrush)GetValue(ValueBrushProperty); } set { SetValue(ValueBrushProperty, value); } } // Using a DependencyProperty as the backing store for ValueBrush. This enables animation, styling, binding, etc... public static readonly DependencyProperty ValueBrushProperty = DependencyProperty.Register( " ValueBrush " , typeof (SolidColorBrush), typeof (RadarMapUserControl), new PropertyMetadata(Brushes.Red, new PropertyChangedCallback(OnChangedToRefreshValueRadiusAndBrush))); /// <summary> /// 需要高亮点的索引 /// 1. 注意在使用绑定时,要先将Binding对象设置为null,然后将数据整合好的ObservableCollection再赋值给绑定对象,否则不更新 /// </summary> public IEnumerable< double > HeightLightValues { get { return (IEnumerable< double > )GetValue(HeightLightValuesProperty); } set { SetValue(HeightLightValuesProperty, value); } } // Using a DependencyProperty as the backing store for HeightLightPoints. This enables animation, styling, binding, etc... public static readonly DependencyProperty HeightLightValuesProperty = DependencyProperty.Register( " HeightLightValues " , typeof (IEnumerable< double >), typeof (RadarMapUserControl), new FrameworkPropertyMetadata( null , new PropertyChangedCallback(OnChangedToRefreshValues))); /// <summary> /// 光亮点的半径 /// </summary> public double HeighLightRadius { get { return ( double )GetValue(HeighLightRadiusProperty); } set { SetValue(HeighLightRadiusProperty, value); } } // Using a DependencyProperty as the backing store for HeighLightValueRadius. This enables animation, styling, binding, etc... public static readonly DependencyProperty HeighLightRadiusProperty = DependencyProperty.Register( " HeighLightRadius " , typeof ( double ), typeof (RadarMapUserControl), new PropertyMetadata( 6.0 , new PropertyChangedCallback(OnChangedToRefreshValueRadiusAndBrush))); /// <summary> /// 高亮点的颜色 /// </summary> public SolidColorBrush HeighLightBrush { get { return (SolidColorBrush)GetValue(HeighLightBrushProperty); } set { SetValue(HeighLightBrushProperty, value); } } // Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc... public static readonly DependencyProperty HeighLightBrushProperty = DependencyProperty.Register( " HeighLightBrush " , typeof (SolidColorBrush), typeof (RadarMapUserControl), new PropertyMetadata(Brushes.Yellow, new PropertyChangedCallback(OnChangedToRefreshValueRadiusAndBrush))); private static void OnChangedToRefreshValueRadiusAndBrush(DependencyObject d, DependencyPropertyChangedEventArgs e) { RadarMapUserControl userControl = (RadarMapUserControl)d; userControl.RefreshValuesRadiusAndBrush(); } #endregion #region 雷达图值区域 /// <summary> /// 雷达图值区域填充色 /// </summary> public SolidColorBrush ValuesAreaFill { get { return (SolidColorBrush)GetValue(ValuesAreaFillProperty); } set { SetValue(ValuesAreaFillProperty, value); } } // Using a DependencyProperty as the backing store for ValuesAreaFill. This enables animation, styling, binding, etc... public static readonly DependencyProperty ValuesAreaFillProperty = DependencyProperty.Register( " ValuesAreaFill " , typeof (SolidColorBrush), typeof (RadarMapUserControl), new PropertyMetadata(Brushes.Red, new PropertyChangedCallback(OnChangedToRefreshValuesAreaFillAndStrokeBrush))); /// <summary> /// 雷达图值区域边框色 /// </summary> public SolidColorBrush ValuesAreaStroke { get { return (SolidColorBrush)GetValue(ValuesAreaStrokeProperty); } set { SetValue(ValuesAreaStrokeProperty, value); } } // Using a DependencyProperty as the backing store for ValuesAreaStroke. This enables animation, styling, binding, etc... public static readonly DependencyProperty ValuesAreaStrokeProperty = DependencyProperty.Register( " ValuesAreaStroke " , typeof (SolidColorBrush), typeof (RadarMapUserControl), new PropertyMetadata(Brushes.Gray, new PropertyChangedCallback(OnChangedToRefreshValuesAreaFillAndStrokeBrush))); private static void OnChangedToRefreshValuesAreaFillAndStrokeBrush(DependencyObject d, DependencyPropertyChangedEventArgs e) { RadarMapUserControl userControl = (RadarMapUserControl)d; userControl.RefreshValuesAreaBrushAndStroke(); } #endregion #region 雷达图的射线标题文字 /// <summary> /// 是否显示Title /// </summary> public bool ShowTitle { get { return ( bool )GetValue(ShowTitleProperty); } set { SetValue(ShowTitleProperty, value); } } // Using a DependencyProperty as the backing store for ShowTitle. This enables animation, styling, binding, etc... public static readonly DependencyProperty ShowTitleProperty = DependencyProperty.Register( " ShowTitle " , typeof ( bool ), typeof (RadarMapUserControl), new PropertyMetadata( false , new PropertyChangedCallback(OnChangedToRefreshTitles))); /// <summary> /// 文字的前景色 /// </summary> public SolidColorBrush TitleForground { get { return (SolidColorBrush)GetValue(TitleForgroundProperty); } set { SetValue(TitleForgroundProperty, value); } } // Using a DependencyProperty as the backing store for TitleForground. This enables animation, styling, binding, etc... public static readonly DependencyProperty TitleForgroundProperty = DependencyProperty.Register( " TitleForground " , typeof (SolidColorBrush), typeof (RadarMapUserControl), new PropertyMetadata(Brushes.Black, new PropertyChangedCallback(OnChangedToRefreshTitles))); /// <summary> /// 文字的字号 /// </summary> public int TitleFontSize { get { return ( int )GetValue(TitleFontSizeProperty); } set { SetValue(TitleFontSizeProperty, value); } } // Using a DependencyProperty as the backing store for TitleFontSize. This enables animation, styling, binding, etc... public static readonly DependencyProperty TitleFontSizeProperty = DependencyProperty.Register( " TitleFontSize " , typeof ( int ), typeof (RadarMapUserControl), new PropertyMetadata( 14 , new PropertyChangedCallback(OnChangedToRefreshTitles))); /// <summary> /// FontWeight /// </summary> public FontWeight TitleFontWeight { get { return (FontWeight)GetValue(TitleFontWeightProperty); } set { SetValue(TitleFontWeightProperty, value); } } // Using a DependencyProperty as the backing store for TitleFontWeights. This enables animation, styling, binding, etc... public static readonly DependencyProperty TitleFontWeightProperty = DependencyProperty.Register( " TitleFontWeights " , typeof (FontWeight), typeof (RadarMapUserControl), new PropertyMetadata(FontWeights.Normal, new PropertyChangedCallback(OnChangedToRefreshTitles))); /// <summary> /// Title要显示的文字 /// </summary> public IEnumerable< string > Titles { get { return (IEnumerable< string > )GetValue(TitlesProperty); } set { SetValue(TitlesProperty, value); } } // Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc... public static readonly DependencyProperty TitlesProperty = DependencyProperty.Register( " Titles " , typeof (IEnumerable< string >), typeof (RadarMapUserControl), new FrameworkPropertyMetadata( null , new PropertyChangedCallback(OnChangedToRefreshTitles))); private static void OnChangedToRefreshTitles(DependencyObject d, DependencyPropertyChangedEventArgs e) { RadarMapUserControl userControl = (RadarMapUserControl)d; userControl.RefreshRadarMap(); } #endregion private static void OnChangedToRefreshRadarMap(DependencyObject d, DependencyPropertyChangedEventArgs e) { RadarMapUserControl userControl = (RadarMapUserControl)d; userControl.RefreshRadarMap(); } public RadarMapUserControl() { SolidColorBrush polygonFill = new SolidColorBrush((Color)ColorConverter.ConvertFromString( " #7653a7 " )); // 绘制图层 List<Color> colors = GetSingleColorList(OutColor, InnerColor, Layers); for ( int i = 0 ; i < Layers; i++ ) { RadarMapLayersPolygon.Add( new Polygon() {Fill= new SolidColorBrush(colors[i]), Stroke = LayerStroke, StrokeThickness = LayerStrokeThickness }); } // 绘制射线以及线上值 for ( int i = 0 ; i < Radials; i++ ) { RadarMapRadialsPolyline.Add( new Polyline() { Stroke = RadialBrush, StrokeThickness = RadialThickness }); RadarMapRadialsValuesPolygons.Add( new Polygon() { Fill = ValueBrush, StrokeThickness = 1 }); } // 雷达图值组成的区域 RadarMapRadialsValuesPolygon = new Polygon() { Fill = ValuesAreaFill, Stroke = ValuesAreaStroke, Opacity = 0.2 }; InitializeComponent(); } private void RadarMapUserControl_SizeChanged( object sender, SizeChangedEventArgs e) { RefreshRadarMap(); } /// <summary> /// 刷新雷达图的层的填充色和层线粗细 /// </summary> private void RefreshLayersFillBrushAndThickness() { // 绘制雷达图层的多边形 List<Color> colors = GetSingleColorList(OutColor, InnerColor, Layers); for ( int i = 0 ; i < Layers; i++ ) { RadarMapLayersPolygon[i].Fill = new SolidColorBrush(colors[i]); RadarMapLayersPolygon[i].Stroke = LayerStroke; RadarMapLayersPolygon[i].StrokeThickness = LayerStrokeThickness; } } /// <summary> /// 刷新射线的颜色和粗细 /// </summary> private void RefreshRadialBrushAndThinkness() { foreach ( var item in RadarMapRadialsPolyline) { item.Stroke = RadialBrush; item.StrokeThickness = RadialThickness; } } /// <summary> /// 刷新雷达图 /// </summary> private void RefreshRadarMap() { Grid_RadarMap.Children.Clear(); // 首先清除一下polygon里存储的数据 for ( int i = 0 ; i < Layers; i++ ) { RadarMapLayersPolygon[i] ?.Points? .Clear(); } for ( int i = 0 ; i < Radials; i++ ) { RadarMapRadialsPolyline[i] ?.Points? .Clear(); } // 如果设置了LayersPercentList,并且LayersPercentList的元素个数与层数相同则按照LayersPercentList画每层的占比,否则均分每层占比 List< double > layersPercents = new List< double > (); if (LayersPercentList != null && LayersPercentList.Count() == Layers && LayersPercentList.Max() < 1 ) { foreach ( var item in LayersPercentList) { layersPercents.Add(item); } } else { double gap = 1.0 / Layers; for ( int i = 0 ; i < Layers; i++ ) { layersPercents.Add(gap * i + gap); // 计算每层的默认占比 } } // 计算每个扇区的角度 Angle = 360 / Radials; // 计算并添加雷达图的区域线和射线上的点 for ( int i = 0 ; i < Radials; i++ ) { // 射线上每层的点,从外到内 List<Point> points = new List<Point> (); for ( int j = 0 ; j < Layers; j++ ) { Point p = new Point(Radius + (Radius * layersPercents[Layers - j - 1 ]) * Math.Cos((Angle * i - 90 ) * Math.PI / 180 ), Radius + (Radius * layersPercents[Layers - j - 1 ]) * Math.Sin((Angle * i - 90 ) * Math.PI / 180 )); points.Add(p); // 添加到区域线中 RadarMapLayersPolygon[j].Points.Add(p); } // 添加到射线中 foreach ( var item in points) { RadarMapRadialsPolyline[i].Points.Add(item); } // 计算原点并添加到射线中 Point p_origin = new Point(Radius + Radius * 0 * Math.Cos((Angle * i - 90 ) * Math.PI / 180 ), Radius + Radius * 0 * Math.Sin((Angle * i - 90 ) * Math.PI / 180 )); RadarMapRadialsPolyline[i].Points.Add(p_origin); } // 绘制区域层 foreach ( var polygon in RadarMapLayersPolygon) { if (! Grid_RadarMap.Children.Contains(polygon)) Grid_RadarMap.Children.Add(polygon); } // 绘制雷达图射线 foreach ( var polyline in RadarMapRadialsPolyline) { if (! Grid_RadarMap.Children.Contains(polyline)) Grid_RadarMap.Children.Add(polyline); } // 绘制雷达图上的文字 if (ShowTitle && Titles != null && Titles.Count() == Radials) { List < string > titleList = Titles.ToList(); for ( int i = 0 ; i < Radials; i++ ) { Point point = RadarMapLayersPolygon[ 0 ].Points[i]; string title = titleList[i]; TextBlock textBlock = RefreshRadiusTitles(point, title); if (! Grid_RadarMap.Children.Contains(textBlock)) Grid_RadarMap.Children.Add(textBlock); } } DrawRadarMapRadialsValues(); } /// <summary> /// 刷新雷达图上值的点的半径和填充色,以及高亮点的半径和填充色 /// </summary> private void RefreshValuesRadiusAndBrush() { if (Values == null ) return ; bool drawHeight = false ; if (HeightLightValues != null && HeightLightValues.Count() > 0 ) drawHeight = true ; List < double > values = Values.ToList(); for ( int i = 0 ; i < RadarMapRadialsValuesPolygon.Points.Count; i++ ) { RadarMapRadialsValuesPolygons[i].Points.Clear(); RadarMapRadialsValuesPolygons[i].Fill = ValueBrush; double radius = ValueRadius; if (drawHeight) { if (HeightLightValues.Contains(values[i])) { radius = HeighLightRadius; RadarMapRadialsValuesPolygons[i].Fill = HeighLightBrush; if (ShowTitle && Titles != null && Titles.Count() > i) { List < string > titleList = Titles.ToList(); string heightTitle = titleList[i]; foreach ( var item in Grid_RadarMap.Children) { if (item is TextBlock) { TextBlock textBlock = (TextBlock)item; if (textBlock.Text == heightTitle) { textBlock.Foreground = HeighLightBrush; } } } } } } Point valuePoint = RadarMapRadialsValuesPolygon.Points[i]; Point[] calc_points = GetEllipsePoints(valuePoint, radius); foreach ( var p in calc_points) { RadarMapRadialsValuesPolygons[i].Points.Add(p); } if (! Grid_RadarMap.Children.Contains(RadarMapRadialsValuesPolygons[i])) Grid_RadarMap.Children.Add(RadarMapRadialsValuesPolygons[i]); } } /// <summary> /// 刷新雷达图值区域的填充色和边框色 /// </summary> private void RefreshValuesAreaBrushAndStroke() { RadarMapRadialsValuesPolygon.Fill = ValuesAreaFill; RadarMapRadialsValuesPolygon.Stroke = ValuesAreaStroke; } /// <summary> /// 刷新射线上的文字标题 /// </summary> /// <param name="point"> 图层最外层的点 </param> /// <returns></returns> private TextBlock RefreshRadiusTitles(Point point, string title) { TextBlock textBlock = new TextBlock(); textBlock.FontSize = 20 ; textBlock.Text = title; textBlock.Foreground = TitleForground; textBlock.FontWeight = FontWeights.Normal; textBlock.FontSize = TitleFontSize; // 计算文字的实际像素值 Rect rect1 = new Rect(); textBlock.Arrange(rect1); double textLength = textBlock.ActualWidth; Thickness thickness = new Thickness(point.X + 10 , point.Y - 10 , 0 , 0 ); if (point.X == Radius && point.Y < Radius) { thickness = new Thickness(point.X - textLength / 2 , point.Y - 30 , 0 , 0 ); } else if (point.X == Radius && point.Y >= Radius) { thickness = new Thickness(point.X - textLength / 2 , point.Y + 10 , 0 , 0 ); } else if (point.X < Radius) { thickness = new Thickness(point.X - 20 - textLength, point.Y - 10 , 0 , 0 ); } else { thickness = new Thickness(point.X + 10 , point.Y - 10 , 0 , 0 ); } textBlock.Margin = thickness; return textBlock; } /// <summary> /// 绘制雷达图上的点 /// </summary> /// <param name="Values"></param> /// <param name="mainType"></param> /// <param name="secondType"></param> public void DrawRadarMapRadialsValues() { if (Values == null || Values.Count() != Radials) return ; int fullScore = 100 ; RadarMapRadialsValuesPolygon.Points.Clear(); for ( int i = 0 ; i < Radials; i++ ) { double temp = Values.ToList()[i]; if (temp <= 0 ) continue ; Point value = new Point(Radius + Radius * (temp * 1.0 / fullScore) * Math.Cos((Angle * i - 90 ) * Math.PI / 180 ), Radius + Radius * (temp * 1.0 / fullScore) * Math.Sin((Angle * i - 90 ) * Math.PI / 180 )); RadarMapRadialsValuesPolygon.Points.Add(value); } if (! Grid_RadarMap.Children.Contains(RadarMapRadialsValuesPolygon)) Grid_RadarMap.Children.Add(RadarMapRadialsValuesPolygon); RefreshValuesRadiusAndBrush(); } #region 工具类 /// <summary> /// 根据圆心,扩展绘制圆 /// </summary> /// <param name="origin"></param> /// <param name="radius"></param> /// <returns></returns> private Point[] GetEllipsePoints(Point origin, double radius) { int count = 10 ; Point[] points = new Point[count]; double angle = 360 / count; for ( int i = 0 ; i < count; i++ ) { Point p1 = new Point(origin.X + radius * Math.Cos((angle * i - 90 ) * Math.PI / 180 ), origin.Y + radius * Math.Sin((angle * i - 90 ) * Math.PI / 180 )); points[i] = p1; } return points; } /// <summary> /// 获得某一颜色区间的颜色集合 /// </summary> /// <param name="sourceColor"> 起始颜色 </param> /// <param name="destColor"> 终止颜色 </param> /// <param name="count"> 分度数 </param> /// <returns> 返回颜色集合 </returns> private List<Color> GetSingleColorList(Color srcColor, Color desColor, int count) { List <Color> colorFactorList = new List<Color> (); int redSpan = desColor.R - srcColor.R; int greenSpan = desColor.G - srcColor.G; int blueSpan = desColor.B - srcColor.B; for ( int i = 0 ; i < count; i++ ) { Color color = Color.FromRgb( ( byte )(srcColor.R + ( int )(( double )i / count * redSpan)), ( byte )(srcColor.G + ( int )(( double )i / count * greenSpan)), ( byte )(srcColor.B + ( int )(( double )i / count * blueSpan)) ); colorFactorList.Add(color); } return colorFactorList; } #endregion } }
。
。
。
。
最后此篇关于WPF-封装自定义雷达图控件的文章就讲到这里了,如果你想了解更多关于WPF-封装自定义雷达图控件的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我想实现自定义搜索,但遇到了一个麻烦。我需要将 UIButton、SearchBar 组合在一个控件中,以便我可以通过指针引用它。然后我将向该组合控件动态添加更多 UIbutton。最重要的是,我想将
它没有在我的方法中执行 if block 中的语句 母版页:- 页面加载事件:- Control c = new Control(); DoSomething(c); 我的方法:- protecte
ComboBox 控件有一个 setConverter 方法,请参阅 JavaFX ComboBox - Display text but return ID on selection举个例子。我正在
我没有找到任何包含用于标记化(标记)文本输入的控件的 wpf 库。也许我找不到库,因为我错误地调用了这个组件。怎么叫或者哪里有这样的库? 最佳答案 DevExpress WPF 库包含多个数据编辑控件
是否有 Silverlight 控件允许您输入文本并将其突出显示为代码? 例如: foreach (client in Clients){ client.Save();} would become
我有以下用户控件 a) Panel.ZIndex="99999999" 是否是将此控件设置为该控件中 TopMost 的正
是否可以在 Windows 窗体中使用 C# 在窗体加载时隐藏所有特定控件,例如标签或按钮,然后选择显示我不想显示的那些? 我有一个包含很多按钮和标签的程序,但我只想在加载时显示一两个,我觉得对每个标
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: Duplicating components at Run-Time 我有一个TMyControl ( Contro
我正在尝试在 Delphi 中编写一个 dll 库,其中包含一个创建 TFrame 后代实例并返回它的函数。但是当我在应用程序中导入这个函数时,每次调用它时,我都会得到一个异常,例如“'xxx'控件没
是否有 Win32 API 调用来确定哪些窗口和/或控件在特定坐标和/或鼠标下可见? 最佳答案 您可以使用GetWindowFromPoint 。它将返回窗口句柄,以便您可以使用 GetClassNa
我需要在编辑控件中输入以下公式: 公式是在 MS Word 中制作的。尝试将其复制/粘贴到编辑控件(单行或多行)后,我得到 M 0.33 Q10T9.1-9.7。 当我输入这个时,我正在研究 Rich
我只是想成功地将它添加到我的窗口中,但这却出奇地困难。 我已经尝试过 #include "windef.h" #include "winbase.h" #include "initguid.h" #i
我希望能够使用 google maps api v3 拥有自己的“街景”按钮。单击按钮时,我希望它根据我的标记经纬度加载街景。然后我希望按钮更改为“返回 map ”,然后再次加载默认 map View
我目前正在用 PHP 开发(另一个)开源 CMS,我想使用 javascript 控件,尤其是管理面板。问题是,是否有任何具有 PHP 接口(interface)的开源、可自由分发的控件(用于创建 j
我为其编写软件的产品之一是会计类应用程序。它用 C++ 编写,使用 C++ Builder 和 VCL 控件,连接到运行在 Linux 上的 PostgreSQL 数据库。 PostgreSQL 数据
我使用 Key Listener 来读取用户的输入,但我遇到了问题。首先,我读到 JTextField“请输入您的姓名”。如果用户输入一个名字,例如 John,它将更改为 John。但是,如果用户输入
我正在尝试对齐数据表列中的复选框(h=center,v=middle) ... 但复选框仍然显示在错误的位置(见附图)
我有一个包含统计信息的 JSON 数据树: { prefix: "a", count: 20, children: [ { prefix: "a:b", c
我在 Photoshop 中设计了一个模型,我打算将它应用到我的产品目录的 ListView 控件中,但它似乎没有正确显示(未对齐?),我希望这里的人可以像我一样指出我的错误试图弄清楚无济于事。 预期
您是使用 ASP.NET 控件还是仅使用带有 CSS 的 HTML? 我在 TextBox 和 DropDownList 的宽度方面遇到了一些问题。在不同的浏览器中,宽度会有所不同,控件的大小也不会相
我是一名优秀的程序员,十分优秀!