[英]Wpf ArcSegment with 3 color gradient
我尝试在我的 WPF 控件中绘制一个 ArcSegment,该控件用作循环进度条并具有三色渐变。 它应该从 0% 的红色开始,50% 的黄色和 100% 的绿色。 所以对于 75%,它应该是这样的:
我用 LinearGradientBrush 试试这个
<Path StrokeThickness="25">
<Path.Data>
<PathGeometry>
<PathFigure StartPoint="50, 12.5">
<ArcSegment RotationAngle="0" SweepDirection="Clockwise"
IsLargeArc="true"
Point="12.5, 75"
Size="62.5, 62.5">
</ArcSegment>
</PathFigure>
</PathGeometry>
</Path.Data>
<Path.Stroke>
<LinearGradientBrush StartPoint="0, 0.5" EndPoint="1, 0.5">
<GradientStop Offset="0" Color="Green" />
<GradientStop Offset="0.5" Color="Red" />
<GradientStop Offset="1.0" Color="Yellow"/>
</LinearGradientBrush>
</Path.Stroke>
</Path>
或者在其他方向:
<Path.Stroke>
<LinearGradientBrush StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Offset="0" Color="Green" />
<GradientStop Offset="0.5" Color="Red" />
<GradientStop Offset="1.0" Color="Yellow"/>
</LinearGradientBrush>
</Path.Stroke>
但问题是渐变用于整个表面,所以我用红色画了两个而不是一次,并且在循环开始时不正确:
我尝试使用带有我想要的渐变的图片的图片画笔。
<Path.Stroke>
<ImageBrush ImageSource="../brush.png" />
</Path.Stroke>
这适用于大于 75% 的值,但对于较低的值,绿色部分也会绘制不应该是什么。
任何想法我能做些什么来使这项工作?
我让它与 ImageBrush 一起工作。 ting 是仅使用需要通过裁剪来绘制的图像部分。
为此,我使用了一个 Converter,它返回一个 ImageBrush 或当前百分比值。
public class ValueToImageBrush : IValueConverter
{
private const string _filePath = "pack://application:,,,/XXX;component/brush.png";
private BitmapImage _baseImage;
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var doubleValue = value as double?;
if (doubleValue == null) return new SolidColorBrush(Colors.LightSlateGray);
var baseImg = LoadImage();
var img = CutImage(baseImg, doubleValue.Value);
return InitImageBrush(img);
}
private BitmapImage LoadImage()
{
if (_baseImage == null)
{
_baseImage = new BitmapImage();
_baseImage.BeginInit();
_baseImage.UriSource = new Uri(_filePath);
_baseImage.EndInit();
}
return _baseImage;
}
private static ImageSource CutImage(BitmapImage baseImg, double doubleValue)
{
var img = baseImg as ImageSource;
if (doubleValue < 50)
{
var usedHight = Math.Max(25.0, baseImg.PixelHeight * (doubleValue * 2 / 100));
img = new CroppedBitmap(baseImg,
new Int32Rect(baseImg.PixelWidth / 2, 0, baseImg.PixelWidth / 2, (int)usedHight));
}
else if (doubleValue < 75)
{
var usedWidth = baseImg.PixelWidth * (doubleValue / 100);
img = new CroppedBitmap(baseImg, new Int32Rect(200 - (int)usedWidth, 0, (int)usedWidth, baseImg.PixelHeight));
}
return img;
}
private static object InitImageBrush(ImageSource img)
{
ImageBrush imgBrush = new ImageBrush();
imgBrush.ImageSource = img;
imgBrush.Stretch = Stretch.None;
return imgBrush;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
我不确定这是否是最聪明的解决方案,但它执行速度很快,而且实施起来并不复杂。 可能其他人有更好的解决方案。
我认为使用线性渐变画笔不可能实现这种显示。
我的解决方案是将控件分成许多小的楔形元素,每个元素都有单一的纯色。 每个元素的颜色是根据它的角度和控件的开始/结束角度计算的(如果你要努力创建这样一个控件,你最好让它更通用一点)和所需的颜色停止。
您不能只使用红色/绿色/蓝色颜色空间并为单个元素插入颜色 - 您必须使用色相/饱和度/亮度之类的东西。
我意识到,这有点棘手,但如果起点位于顶部、底部、左侧或右侧,则最多将 ArcSegment 分成四部分会有所帮助。 我明天可以解释更多,但棘手的部分是找到从每个 ArcSegment 的起点到终点的对角线上的梯度步骤。 如果起点在任何地方,投影线将更难找到,因为它可能具有非矩形角度。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.