自定义滑块 Windows 8.1
Custom Slider Windows 8.1
我需要创建一个自定义滑块,目前我的滑块看起来正是我想要的,它看起来像这样(来自 VisualStudio 的图像):
xaml 代码是这样的:
<Grid x:Name="mainGrid">
<Grid Height="240" Width="300" Canvas.ZIndex="2">
<Grid.RenderTransform>
<RotateTransform x:Name="rotateTransform"
Angle="-125"
CenterX="150"
CenterY="150" />
</Grid.RenderTransform>
<Ellipse Height="54" Width="54"
x:Name="knob"
Fill="Red"
PointerMoved="Image_PointerMoved"
VerticalAlignment="Top"
Margin="0,-7,0,0"/>
</Grid>
<Path x:Name="path"
Data="M269.01,233.229 C303.532,181.303 304.261,118.855 269.097,67.0139 C207.933,-15.2077 92.8603,-16.8742 31.2108,66.0937 C-3.68835,121.514 -3.36331,179.271 30.8461,232.917 C51.2571,253.282 74.8965,230.573 61.3585,209.167 C38.2919,172.761 36.0008,129.688 62.1396,90.2093 C106.398,28.022 194.916,29.4803 237.509,90.1399 C262.554,127.345 263.613,170.209 237.647,209.792 C227.355,233.49 250.474,250.782 269.01,233.229 z"
Stretch="Fill"
Fill="Gray" />
</Grid>
C# 代码是这样的:
private void Image_PointerMoved(object sender, PointerRoutedEventArgs e)
{
//Canculate the current rotation angle and set the value.
var newPos = e.GetCurrentPoint(path);
double angle = GetAngleR(newPos.Position);
rotateTransform.Angle = angle;
}
public double GetAngleR(Point pos)
{
var xDiff = 150 - pos.X;
var yDiff = 150 - pos.Y;
var r = Math.Sqrt((xDiff * xDiff) + (yDiff * yDiff));
var radians = Math.Acos((yDiff) / r);
var angle = radians * (180 / Math.PI);
if(angle > 125)
{
angle = 125;
}
if(pos.X < 150)
{
angle = -angle;
}
return angle;
}
我的问题是如何在移动椭圆时用不同的颜色填充路径?
我需要实现这样的目标:
有什么建议吗?
好的,我已经想出了如何做这个滑块,这不是一个完美的解决方案,但它有效,对我来说就足够了。
我创建了一个 GeometryGroup
,其中包含一些用于绘制拱形路径的 BezierSegment
,然后我将 a 添加到组 a RectangleGeometry
,这是元素的大小.
在本例中GeometryGroup
,两个形状的相交区域未填充。
之后我将正确的颜色放在主路径后面。
这是代码:
XAML
<Grid x:Name="mainGrid">
<Grid Height="240" Width="300" Canvas.ZIndex="2">
<Grid.RenderTransform>
<RotateTransform x:Name="rotateTransform"
Angle="-125"
CenterX="150"
CenterY="150" />
</Grid.RenderTransform>
<Image Height="54" Width="54" x:Name="knob"
Source="ms-appx:///Assets/ic_slider_credito.png"
PointerMoved="Image_PointerMoved"
VerticalAlignment="Top"
Margin="0,-5,0,0" />
</Grid>
<Rectangle VerticalAlignment="Top"
HorizontalAlignment="Left"
Fill="Gray"
Width="300"
Height="240" />
<Path x:Name="fillPath"
Height="240"
Width="300"
UseLayoutRounding="False"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Fill="Orange" />
<Path x:Name="path"
Height="240"
Width="300"
UseLayoutRounding="False"
Stretch="Fill"
Fill="White" />
</Grid>
C#
public SliderInvioCredito()
{
this.InitializeComponent();
DrawPath();
}
private void Image_PointerMoved(object sender, PointerRoutedEventArgs e)
{
var newPos = e.GetCurrentPoint(path);
double angle = GetAngleR(newPos.Position);
rotateTransform.Angle = angle;
}
public double GetAngleR(Point pos)
{
var xDiff = 150 - pos.X;
var yDiff = 150 - pos.Y;
var r = Math.Sqrt((xDiff * xDiff) + (yDiff * yDiff));
var radians = Math.Acos((yDiff) / r);
var angle = radians * (180 / Math.PI);
if (angle > 125)
{
angle = 125;
}
if (pos.X < 150)
{
angle = -angle;
}
DrawFillPath(pos.X, pos.Y, angle);
return angle;
}
private void DrawFillPath(double x, double y, double angle)
{
var start = new Point(150, 120);
var pth = new PathFigure();
pth.StartPoint = start;
var ls1 = new LineSegment();
ls1.Point = start;
pth.Segments.Add(ls1);
var ls8 = new LineSegment();
ls8.Point = new Point(150, 240);
pth.Segments.Add(ls8);
var ls2 = new LineSegment();
ls2.Point = new Point(0, 240);
pth.Segments.Add(ls2);
if (angle > -45)
{
var ls5 = new LineSegment();
ls5.Point = new Point(0, 0);
pth.Segments.Add(ls5);
if (angle > -30)
{
var ls6 = new LineSegment();
ls6.Point = new Point(x, 0);
pth.Segments.Add(ls6);
}
}
else
{
var ls3 = new LineSegment();
ls3.Point = new Point(0, y);
pth.Segments.Add(ls3);
}
if (angle > 45)
{
var ls7 = new LineSegment();
ls7.Point = new Point(300, 0);
pth.Segments.Add(ls7);
var ls9 = new LineSegment();
ls9.Point = new Point(300, y);
pth.Segments.Add(ls9);
}
var ls4 = new LineSegment();
ls4.Point = new Point(x, y);
pth.Segments.Add(ls4);
var pthCollection = new PathFigureCollection();
pthCollection.Add(pth);
var pthGeometry = new PathGeometry();
pthGeometry.Figures = pthCollection;
fillPath.Data = pthGeometry;
}
private void DrawPath()
{
var cc1 = new BezierSegment();
cc1.Point1 = new Point(303.532, 181.303);
cc1.Point2 = new Point(304.261, 118.855);
cc1.Point3 = new Point(269.097, 67.0139);
var cc2 = new BezierSegment();
cc2.Point1 = new Point(207.933, -15.2077);
cc2.Point2 = new Point(92.8603, -16.8742);
cc2.Point3 = new Point(31.2108, 66.0937);
var cc3 = new BezierSegment();
cc3.Point1 = new Point(-3.68835, 121.514);
cc3.Point2 = new Point(-3.36331, 179.271);
cc3.Point3 = new Point(30.8461, 232.917);
var cc4 = new BezierSegment();
cc4.Point1 = new Point(51.2571, 253.282);
cc4.Point2 = new Point(74.8965, 230.573);
cc4.Point3 = new Point(61.3585, 209.167);
var cc5 = new BezierSegment();
cc5.Point1 = new Point(38.2919, 172.761);
cc5.Point2 = new Point(36.0008, 129.688);
cc5.Point3 = new Point(62.1396, 90.2093);
var cc6 = new BezierSegment();
cc6.Point1 = new Point(106.398, 28.022);
cc6.Point2 = new Point(194.916, 29.4803);
cc6.Point3 = new Point(237.509, 90.1399);
var cc7 = new BezierSegment();
cc7.Point1 = new Point(262.554, 127.345);
cc7.Point2 = new Point(263.613, 170.209);
cc7.Point3 = new Point(237.647, 209.792);
var cc8 = new BezierSegment();
cc8.Point1 = new Point(227.355, 233.49);
cc8.Point2 = new Point(250.474, 250.782);
cc8.Point3 = new Point(269.01, 233.229);
var pthFigure = new PathFigure();
pthFigure.StartPoint = new Point(269.01, 233.229);
var psc = new PathSegmentCollection();
psc.Add(cc1);
psc.Add(cc2);
psc.Add(cc3);
psc.Add(cc4);
psc.Add(cc5);
psc.Add(cc6);
psc.Add(cc7);
psc.Add(cc8);
pthFigure.Segments = psc;
var pthFigureCollection = new PathFigureCollection();
pthFigureCollection.Add(pthFigure);
var pthGeometry = new PathGeometry();
pthGeometry.Figures = pthFigureCollection;
var rect = new RectangleGeometry();
rect.Rect = new Rect(0, 0, 300, 240);
var gg = new GeometryGroup();
gg.Children.Add(pthGeometry);
gg.Children.Add(rect);
path.Data = gg;
}
我需要创建一个自定义滑块,目前我的滑块看起来正是我想要的,它看起来像这样(来自 VisualStudio 的图像):
<Grid x:Name="mainGrid">
<Grid Height="240" Width="300" Canvas.ZIndex="2">
<Grid.RenderTransform>
<RotateTransform x:Name="rotateTransform"
Angle="-125"
CenterX="150"
CenterY="150" />
</Grid.RenderTransform>
<Ellipse Height="54" Width="54"
x:Name="knob"
Fill="Red"
PointerMoved="Image_PointerMoved"
VerticalAlignment="Top"
Margin="0,-7,0,0"/>
</Grid>
<Path x:Name="path"
Data="M269.01,233.229 C303.532,181.303 304.261,118.855 269.097,67.0139 C207.933,-15.2077 92.8603,-16.8742 31.2108,66.0937 C-3.68835,121.514 -3.36331,179.271 30.8461,232.917 C51.2571,253.282 74.8965,230.573 61.3585,209.167 C38.2919,172.761 36.0008,129.688 62.1396,90.2093 C106.398,28.022 194.916,29.4803 237.509,90.1399 C262.554,127.345 263.613,170.209 237.647,209.792 C227.355,233.49 250.474,250.782 269.01,233.229 z"
Stretch="Fill"
Fill="Gray" />
</Grid>
C# 代码是这样的:
private void Image_PointerMoved(object sender, PointerRoutedEventArgs e)
{
//Canculate the current rotation angle and set the value.
var newPos = e.GetCurrentPoint(path);
double angle = GetAngleR(newPos.Position);
rotateTransform.Angle = angle;
}
public double GetAngleR(Point pos)
{
var xDiff = 150 - pos.X;
var yDiff = 150 - pos.Y;
var r = Math.Sqrt((xDiff * xDiff) + (yDiff * yDiff));
var radians = Math.Acos((yDiff) / r);
var angle = radians * (180 / Math.PI);
if(angle > 125)
{
angle = 125;
}
if(pos.X < 150)
{
angle = -angle;
}
return angle;
}
我的问题是如何在移动椭圆时用不同的颜色填充路径?
我需要实现这样的目标:
有什么建议吗?
好的,我已经想出了如何做这个滑块,这不是一个完美的解决方案,但它有效,对我来说就足够了。
我创建了一个 GeometryGroup
,其中包含一些用于绘制拱形路径的 BezierSegment
,然后我将 a 添加到组 a RectangleGeometry
,这是元素的大小.
在本例中GeometryGroup
,两个形状的相交区域未填充。
之后我将正确的颜色放在主路径后面。
这是代码:
XAML
<Grid x:Name="mainGrid">
<Grid Height="240" Width="300" Canvas.ZIndex="2">
<Grid.RenderTransform>
<RotateTransform x:Name="rotateTransform"
Angle="-125"
CenterX="150"
CenterY="150" />
</Grid.RenderTransform>
<Image Height="54" Width="54" x:Name="knob"
Source="ms-appx:///Assets/ic_slider_credito.png"
PointerMoved="Image_PointerMoved"
VerticalAlignment="Top"
Margin="0,-5,0,0" />
</Grid>
<Rectangle VerticalAlignment="Top"
HorizontalAlignment="Left"
Fill="Gray"
Width="300"
Height="240" />
<Path x:Name="fillPath"
Height="240"
Width="300"
UseLayoutRounding="False"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Fill="Orange" />
<Path x:Name="path"
Height="240"
Width="300"
UseLayoutRounding="False"
Stretch="Fill"
Fill="White" />
</Grid>
C#
public SliderInvioCredito()
{
this.InitializeComponent();
DrawPath();
}
private void Image_PointerMoved(object sender, PointerRoutedEventArgs e)
{
var newPos = e.GetCurrentPoint(path);
double angle = GetAngleR(newPos.Position);
rotateTransform.Angle = angle;
}
public double GetAngleR(Point pos)
{
var xDiff = 150 - pos.X;
var yDiff = 150 - pos.Y;
var r = Math.Sqrt((xDiff * xDiff) + (yDiff * yDiff));
var radians = Math.Acos((yDiff) / r);
var angle = radians * (180 / Math.PI);
if (angle > 125)
{
angle = 125;
}
if (pos.X < 150)
{
angle = -angle;
}
DrawFillPath(pos.X, pos.Y, angle);
return angle;
}
private void DrawFillPath(double x, double y, double angle)
{
var start = new Point(150, 120);
var pth = new PathFigure();
pth.StartPoint = start;
var ls1 = new LineSegment();
ls1.Point = start;
pth.Segments.Add(ls1);
var ls8 = new LineSegment();
ls8.Point = new Point(150, 240);
pth.Segments.Add(ls8);
var ls2 = new LineSegment();
ls2.Point = new Point(0, 240);
pth.Segments.Add(ls2);
if (angle > -45)
{
var ls5 = new LineSegment();
ls5.Point = new Point(0, 0);
pth.Segments.Add(ls5);
if (angle > -30)
{
var ls6 = new LineSegment();
ls6.Point = new Point(x, 0);
pth.Segments.Add(ls6);
}
}
else
{
var ls3 = new LineSegment();
ls3.Point = new Point(0, y);
pth.Segments.Add(ls3);
}
if (angle > 45)
{
var ls7 = new LineSegment();
ls7.Point = new Point(300, 0);
pth.Segments.Add(ls7);
var ls9 = new LineSegment();
ls9.Point = new Point(300, y);
pth.Segments.Add(ls9);
}
var ls4 = new LineSegment();
ls4.Point = new Point(x, y);
pth.Segments.Add(ls4);
var pthCollection = new PathFigureCollection();
pthCollection.Add(pth);
var pthGeometry = new PathGeometry();
pthGeometry.Figures = pthCollection;
fillPath.Data = pthGeometry;
}
private void DrawPath()
{
var cc1 = new BezierSegment();
cc1.Point1 = new Point(303.532, 181.303);
cc1.Point2 = new Point(304.261, 118.855);
cc1.Point3 = new Point(269.097, 67.0139);
var cc2 = new BezierSegment();
cc2.Point1 = new Point(207.933, -15.2077);
cc2.Point2 = new Point(92.8603, -16.8742);
cc2.Point3 = new Point(31.2108, 66.0937);
var cc3 = new BezierSegment();
cc3.Point1 = new Point(-3.68835, 121.514);
cc3.Point2 = new Point(-3.36331, 179.271);
cc3.Point3 = new Point(30.8461, 232.917);
var cc4 = new BezierSegment();
cc4.Point1 = new Point(51.2571, 253.282);
cc4.Point2 = new Point(74.8965, 230.573);
cc4.Point3 = new Point(61.3585, 209.167);
var cc5 = new BezierSegment();
cc5.Point1 = new Point(38.2919, 172.761);
cc5.Point2 = new Point(36.0008, 129.688);
cc5.Point3 = new Point(62.1396, 90.2093);
var cc6 = new BezierSegment();
cc6.Point1 = new Point(106.398, 28.022);
cc6.Point2 = new Point(194.916, 29.4803);
cc6.Point3 = new Point(237.509, 90.1399);
var cc7 = new BezierSegment();
cc7.Point1 = new Point(262.554, 127.345);
cc7.Point2 = new Point(263.613, 170.209);
cc7.Point3 = new Point(237.647, 209.792);
var cc8 = new BezierSegment();
cc8.Point1 = new Point(227.355, 233.49);
cc8.Point2 = new Point(250.474, 250.782);
cc8.Point3 = new Point(269.01, 233.229);
var pthFigure = new PathFigure();
pthFigure.StartPoint = new Point(269.01, 233.229);
var psc = new PathSegmentCollection();
psc.Add(cc1);
psc.Add(cc2);
psc.Add(cc3);
psc.Add(cc4);
psc.Add(cc5);
psc.Add(cc6);
psc.Add(cc7);
psc.Add(cc8);
pthFigure.Segments = psc;
var pthFigureCollection = new PathFigureCollection();
pthFigureCollection.Add(pthFigure);
var pthGeometry = new PathGeometry();
pthGeometry.Figures = pthFigureCollection;
var rect = new RectangleGeometry();
rect.Rect = new Rect(0, 0, 300, 240);
var gg = new GeometryGroup();
gg.Children.Add(pthGeometry);
gg.Children.Add(rect);
path.Data = gg;
}