Silverlight并没有象flash那样直接提供画线、画圆、画曲线的方法,只能用Path来生成贝塞尔曲线。
下面是示例代码:
XAML部分:
<UserControl x:Class="SLCurveSample.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="400" d:DesignWidth="400"> <Canvas x:Name="LayoutRoot" Background="White"> <Ellipse Width="10" Height="10" StrokeThickness="1" Stroke="Red" x:Name="point1"></Ellipse> <TextBlock Text="Left Point" Name="tbLeftPoint" Visibility="Collapsed"></TextBlock> <Ellipse Width="10" Height="10" StrokeThickness="1" Stroke="Red" x:Name="point2"></Ellipse> <TextBlock Text="Right Point" Name="tbRightPoint" Visibility="Collapsed"></TextBlock> <Path Stroke="Red" StrokeThickness="1" x:Name="p" > <Path.Data> <PathGeometry> <PathGeometry.Figures> <PathFigure> <PathFigure.Segments> <BezierSegment /> </PathFigure.Segments> </PathFigure> </PathGeometry.Figures> </PathGeometry> </Path.Data> </Path> </Canvas> </UserControl>
Xaml.cs部分:
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; namespace SLCurveSample { public partial class MainPage : UserControl { Point _leftPoint = new Point(); Point _rightPoint = new Point(); BezierSegment seg = null; public MainPage() { InitializeComponent(); this.Loaded += PageLoaded; } void PageLoaded(object sender, RoutedEventArgs e) { this.SizeChanged += PageSizeChanged; this.MouseMove += PageMouseMove; this.Loaded -= PageLoaded; } void PageMouseMove(object sender, MouseEventArgs e) { Point mousePos = e.GetPosition(this); //根据鼠标的位置对线条粗细、左右圈圈大小做一些交互 double scale = Math.Abs(_leftPoint.Y - mousePos.Y) / _leftPoint.Y; point1.Width = point1.Height = 10 + 40 * scale; point2.Width = point2.Height = point1.Width; p.StrokeThickness = 3 - 2 * scale; //重绘 Draw(); //计算二个控制点的位置 Point ctlPoint1 = new Point() { X = (mousePos.X + _leftPoint.X) * 0.5, Y = (mousePos.Y + _leftPoint.Y) * 0.5 }; Point ctlPoint2 = new Point() { X = (mousePos.X + _rightPoint.X) * 0.5, Y = (mousePos.Y + _rightPoint.Y) * 0.5 }; if (seg != null) { seg.Point1 = ctlPoint1;//贝兹曲线的第一个控制点 seg.Point2 = ctlPoint2;//贝兹曲线的第二个控制点 } } void PageSizeChanged(object sender, SizeChangedEventArgs e) { Draw(); } void Draw() { double _stageWidth = this.ActualWidth; double _stageHeight = this.ActualHeight; double _margin = 80; //将二个小圈定位于左右二侧 point1.SetValue(Canvas.TopProperty, _stageHeight * 0.5); point1.SetValue(Canvas.LeftProperty, _margin); point2.SetValue(Canvas.TopProperty, _stageHeight * 0.5); point2.SetValue(Canvas.LeftProperty, _stageWidth - _margin); //计算左侧小圈的中心 _leftPoint.X = (double)point1.GetValue(Canvas.LeftProperty) + point1.Width * 0.5; _leftPoint.Y = (double)point1.GetValue(Canvas.TopProperty) + point1.Height * 0.5; tbLeftPoint.SetValue(Canvas.LeftProperty, _leftPoint.X - 20); tbLeftPoint.SetValue(Canvas.TopProperty, _leftPoint.Y + 10); //计算右侧小圈的中心 _rightPoint.X = (double)point2.GetValue(Canvas.LeftProperty) + point2.Width * 0.5; _rightPoint.Y = (double)point2.GetValue(Canvas.TopProperty) + point2.Height * 0.5; tbRightPoint.SetValue(Canvas.LeftProperty, _rightPoint.X - 20); tbRightPoint.SetValue(Canvas.TopProperty, _rightPoint.Y + 10); PathFigure figure = (p.Data as PathGeometry).Figures[0]; figure.StartPoint = _leftPoint;//设置(贝兹曲线的)起点 seg = figure.Segments[0] as BezierSegment; seg.Point3 = _rightPoint;//贝兹曲线的终点 } } }
以上的代码,先在Canvas中放置了一段Path,然后在后台去动态修改贝塞尔曲线的控制点,并加入了与鼠标的一些简单交互。更详细的原理也可参见我之前记录的Flash/Flex学习笔记(20):贝塞尔曲线
运行截图: