最近用到一个使用五角星做评级的小控件,用Path创建了一个五角星的控件,贴出代码及效果:
效果:
图片比较小,凑合看吧,贴出来现在使用的两个控件的代码。
第一个是单个的五角星控件,支持设置五角星大小、FillColor,Stroke等。
下面的代码是在Win8的程序下写的,如果在其他平台下,可以找到关键代码拷贝过去。
UcOneStarView.xaml
<UserControl
x:Class="App1.Common.UserControls.UcOneStarView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1.Common.UserControls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid Name="grdRoot"></Grid>
</UserControl>
UcOneStarView.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Shapes;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace App1.Common.UserControls
{
public sealed partial class UcOneStarView : UserControl
{
public int StarSize
{
get { return (int)GetValue(StarHeightProperty); }
set { SetValue(StarHeightProperty, value); }
}
// Using a DependencyProperty as the backing store for StarHeight. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarHeightProperty =
DependencyProperty.Register("StarSize", typeof(int), typeof(UcOneStarView), new PropertyMetadata(100));
public bool IsFill
{
get { return (bool)GetValue(IsFillProperty); }
set { SetValue(IsFillProperty, value); }
}
// Using a DependencyProperty as the backing store for IsFill. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsFillProperty =
DependencyProperty.Register("IsFill", typeof(bool), typeof(UcOneStarView), new PropertyMetadata(true));
public Color StarFillColor
{
get { return (Color)GetValue(StarFillColorProperty); }
set { SetValue(StarFillColorProperty, value); }
}
// Using a DependencyProperty as the backing store for StarFillColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarFillColorProperty =
DependencyProperty.Register("StarFillColor", typeof(Color), typeof(UcOneStarView), new PropertyMetadata(Colors.Red));
public Color StarStroke
{
get { return (Color)GetValue(StarStrokeProperty); }
set { SetValue(StarStrokeProperty, value); }
}
// Using a DependencyProperty as the backing store for StarStroke. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarStrokeProperty =
DependencyProperty.Register("StarStroke", typeof(Color), typeof(UcOneStarView), new PropertyMetadata(Colors.White));
public UcOneStarView()
{
this.InitializeComponent();
this.Loaded += UcOneStarView_Loaded;
}
void UcOneStarView_Loaded(object sender, RoutedEventArgs e)
{
Path pathRoot = CreateAStar(StarSize, IsFill ? 100 : 0, StarFillColor, StarStroke);
grdRoot.Children.Add(pathRoot);
}
/// <summary>
/// 创建一个五角星的Path
/// </summary>
/// <param name="sizeBase"></param>
/// <param name="percent">smaller than 100 && larger than 0</param>
/// <param name="colorFill"></param>
/// <param name="colorStroke"></param>
private Path CreateAStar(double sizeBase, double percent, Color colorFill, Color colorStroke)
{
//定义Path
Path pathRoot = new Path();
pathRoot.Fill = new SolidColorBrush(colorFill);
pathRoot.Stroke = new SolidColorBrush(colorStroke);
PathGeometry pathData = new PathGeometry();
PathFigureCollection pathFigureCollection = new PathFigureCollection();
PathFigure pathFigure1 = new PathFigure();
pathFigure1.StartPoint = new Point(sizeBase, 0);
PathSegmentCollection pathSegments = new PathSegmentCollection();
Point p1 = new Point(sizeBase, 0);
//各定点连线中间部分长度的1/2
double length1 = sizeBase / (Math.Tan(GetRadianByAngle(72d)) + Math.Tan(GetRadianByAngle(54d)));
//圆中心到五角星各顶点连线的距离
double length2 = sizeBase * Math.Sin(GetRadianByAngle(18d));
Point p2 = new Point(sizeBase + length1, sizeBase - length2);
Point p3 = new Point(sizeBase + length2 * Math.Tan(GetRadianByAngle(72d)), sizeBase - length2);
Point p4 = new Point(p2.X + length1 * 2 * Math.Sin(GetRadianByAngle(18d)), p2.Y + length1 * 2 * Math.Cos(GetRadianByAngle(18d)));
Point p5 = new Point(sizeBase + sizeBase * Math.Sin(GetRadianByAngle(36d)), sizeBase + sizeBase * Math.Cos(GetRadianByAngle(36d)));
Point p6 = new Point(sizeBase, sizeBase + length2 / Math.Cos(GetRadianByAngle(36d)));
Point p7 = new Point(sizeBase - sizeBase * Math.Sin(GetRadianByAngle(36d)), p5.Y);
Point p8 = new Point(sizeBase - length2 / Math.Cos(GetRadianByAngle(36d)), p4.Y);
Point p9 = new Point(sizeBase - sizeBase * Math.Sin(GetRadianByAngle(72d)), p3.Y);
Point p10 = new Point(sizeBase - length1, sizeBase - length2);
pathSegments.Add(new LineSegment() { Point = p2 });
pathSegments.Add(new LineSegment() { Point = p3 });
pathSegments.Add(new LineSegment() { Point = p4 });
pathSegments.Add(new LineSegment() { Point = p5 });
pathSegments.Add(new LineSegment() { Point = p6 });
pathSegments.Add(new LineSegment() { Point = p7 });
pathSegments.Add(new LineSegment() { Point = p8 });
pathSegments.Add(new LineSegment() { Point = p9 });
pathSegments.Add(new LineSegment() { Point = p10 });
pathFigure1.Segments = pathSegments;
pathFigure1.IsClosed = true;
pathFigureCollection.Add(pathFigure1);
pathData.Figures = pathFigureCollection;
pathRoot.Data = pathData;
if (percent > 0)
{
double boundWith = Math.Abs(p3.X - p9.X);
double boundHeight = boundWith;
//根据Star要显示的百分比来进行显示颜色
Size rectSize = new Size(boundWith * percent / 100d, boundHeight);
Rect rect = new Rect(new Point(p9.X, p1.Y), rectSize);
pathRoot.Clip = new RectangleGeometry() { Rect = rect };
}
return pathRoot;
}
/// <summary>
/// 把角度值转换成弧度
/// </summary>
/// <param name="angle">角度值</param>
/// <returns>弧度值</returns>
private double GetRadianByAngle(double angle)
{
return angle * Math.PI / 180d;
}
}
}
第二个是将每个五角星组合起来的控件
UcStarsView.xaml
<UserControl
x:Class="App1.Common.UserControls.UcStarsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1.Common.UserControls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<StackPanel Name="spRoot" Orientation="{Binding StarOrientation}">
</StackPanel>
</UserControl>
UcStarsView.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Shapes;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace App1.Common.UserControls
{
public sealed partial class UcStarsView : UserControl
{
public int StarSize
{
get { return (int)GetValue(StarSizeProperty); }
set { SetValue(StarSizeProperty, value); }
}
// Using a DependencyProperty as the backing store for StarSize. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarSizeProperty =
DependencyProperty.Register("StarSize", typeof(int), typeof(UcStarsView), new PropertyMetadata(100));
public Color StarFillColor
{
get { return (Color)GetValue(StarFillColorProperty); }
set { SetValue(StarFillColorProperty, value); }
}
// Using a DependencyProperty as the backing store for StarFillColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarFillColorProperty =
DependencyProperty.Register("StarFillColor", typeof(Color), typeof(UcStarsView), new PropertyMetadata(Colors.Red));
public Color StarStroke
{
get { return (Color)GetValue(StarStrokeProperty); }
set { SetValue(StarStrokeProperty, value); }
}
// Using a DependencyProperty as the backing store for StarStroke. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarStrokeProperty =
DependencyProperty.Register("StarStroke", typeof(Color), typeof(UcStarsView), new PropertyMetadata(Colors.White));
/// <summary>
/// 大于0小于等于StarMaxNumber的整数
/// </summary>
public int Rating
{
get { return (int)GetValue(RatingProperty); }
set
{
if (Rating < 0)
{
throw new ArithmeticException("Rating should be larger than Zero.");
}
else
{
if (Rating <= StarMaxNumber)
{
SetValue(RatingProperty, value);
}
else
{
throw new ArithmeticException("The number is larger than StarMaxNumber.");
}
}
}
}
// Using a DependencyProperty as the backing store for Rating. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RatingProperty =
DependencyProperty.Register("Rating", typeof(int), typeof(UcStarsView), new PropertyMetadata(5));
public Orientation StarOrientation
{
get { return (Orientation)GetValue(StarOrientationProperty); }
set { SetValue(StarOrientationProperty, value); }
}
// Using a DependencyProperty as the backing store for StarOrientation. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarOrientationProperty =
DependencyProperty.Register("StarOrientation", typeof(Orientation), typeof(UcStarsView), new PropertyMetadata(Orientation.Horizontal));
public int StarMaxNumber
{
get { return (int)GetValue(StarMaxNumberProperty); }
set { SetValue(StarMaxNumberProperty, value); }
}
// Using a DependencyProperty as the backing store for StarMaxNumber. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarMaxNumberProperty =
DependencyProperty.Register("StarMaxNumber", typeof(int), typeof(UcStarsView), new PropertyMetadata(5));
/// <summary>
/// 五角星之间的距离
/// </summary>
public double StarMargin
{
get { return (double)GetValue(StarMarginProperty); }
set { SetValue(StarMarginProperty, value); }
}
// Using a DependencyProperty as the backing store for StarMargin. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarMarginProperty =
DependencyProperty.Register("StarMargin", typeof(double), typeof(UcStarsView), new PropertyMetadata(5));
public UcStarsView()
{
this.InitializeComponent();
this.DataContext = this;
this.Loaded += UcStarsView_Loaded;
}
void UcStarsView_Loaded(object sender, RoutedEventArgs e)
{
for (int i = 0; i < Rating; i++)
{
UcOneStarView star = CreateStar(true);
star.StarFillColor = StarFillColor;
star.Margin = new Thickness(0, 0, StarMargin, 0);
spRoot.Children.Add(star);
}
for (int i = 0; i < StarMaxNumber - Rating; i++)
{
UcOneStarView star = CreateStar(false);
star.StarFillColor = Colors.Transparent;
star.Margin = new Thickness(0, 0, StarMargin, 0);
spRoot.Children.Add(star);
}
}
private UcOneStarView CreateStar(bool isFill)
{
UcOneStarView star = new UcOneStarView();
star.StarSize = StarSize;
star.StarStroke = StarStroke;
star.IsFill = isFill;
return star;
}
}
}
http://go.microsoft.com/fwlink/?LinkId=234236
namespace App1.Common.UserControls
{
public sealed partial class UcStarsView : UserControl
{
public int StarSize
{
get { return (int)GetValue(StarSizeProperty); }
set { SetValue(StarSizeProperty, value); }
}
// Using a DependencyProperty as the backing store for StarSize. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarSizeProperty =
DependencyProperty.Register("StarSize", typeof(int), typeof(UcStarsView), new PropertyMetadata(100));
public Color StarFillColor
{
get { return (Color)GetValue(StarFillColorProperty); }
set { SetValue(StarFillColorProperty, value); }
}
// Using a DependencyProperty as the backing store for StarFillColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarFillColorProperty =
DependencyProperty.Register("StarFillColor", typeof(Color), typeof(UcStarsView), new PropertyMetadata(Colors.Red));
public Color StarStroke
{
get { return (Color)GetValue(StarStrokeProperty); }
set { SetValue(StarStrokeProperty, value); }
}
// Using a DependencyProperty as the backing store for StarStroke. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarStrokeProperty =
DependencyProperty.Register("StarStroke", typeof(Color), typeof(UcStarsView), new PropertyMetadata(Colors.White));
/// <summary>
/// 大于0小于等于StarMaxNumber的整数
/// </summary>
public int Rating
{
get { return (int)GetValue(RatingProperty); }
set
{
if (Rating < 0)
{
throw new ArithmeticException("Rating should be larger than Zero.");
}
else
{
if (Rating <= StarMaxNumber)
{
SetValue(RatingProperty, value);
}
else
{
throw new ArithmeticException("The number is larger than StarMaxNumber.");
}
}
}
}
// Using a DependencyProperty as the backing store for Rating. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RatingProperty =
DependencyProperty.Register("Rating", typeof(int), typeof(UcStarsView), new PropertyMetadata(5));
public Orientation StarOrientation
{
get { return (Orientation)GetValue(StarOrientationProperty); }
set { SetValue(StarOrientationProperty, value); }
}
// Using a DependencyProperty as the backing store for StarOrientation. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarOrientationProperty =
DependencyProperty.Register("StarOrientation", typeof(Orientation), typeof(UcStarsView), new PropertyMetadata(Orientation.Horizontal));
public int StarMaxNumber
{
get { return (int)GetValue(StarMaxNumberProperty); }
set { SetValue(StarMaxNumberProperty, value); }
}
// Using a DependencyProperty as the backing store for StarMaxNumber. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarMaxNumberProperty =
DependencyProperty.Register("StarMaxNumber", typeof(int), typeof(UcStarsView), new PropertyMetadata(5));
/// <summary>
/// 五角星之间的距离
/// </summary>
public double StarMargin
{
get { return (double)GetValue(StarMarginProperty); }
set { SetValue(StarMarginProperty, value); }
}
// Using a DependencyProperty as the backing store for StarMargin. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StarMarginProperty =
DependencyProperty.Register("StarMargin", typeof(double), typeof(UcStarsView), new PropertyMetadata(5));
public UcStarsView()
{
this.InitializeComponent();
this.DataContext = this;
this.Loaded += UcStarsView_Loaded;
}
void UcStarsView_Loaded(object sender, RoutedEventArgs e)
{
for (int i = 0; i < Rating; i++)
{
UcOneStarView star = CreateStar(true);
star.StarFillColor = StarFillColor;
star.Margin = new Thickness(0, 0, StarMargin, 0);
spRoot.Children.Add(star);
}
for (int i = 0; i < StarMaxNumber - Rating; i++)
{
UcOneStarView star = CreateStar(false);
star.StarFillColor = Colors.Transparent;
star.Margin = new Thickness(0, 0, StarMargin, 0);
spRoot.Children.Add(star);
}
}
private UcOneStarView CreateStar(bool isFill)
{
UcOneStarView star = new UcOneStarView();
star.StarSize = StarSize;
star.StarStroke = StarStroke;
star.IsFill = isFill;
return star;
}
}
}