silverlight:贝塞尔曲线

2018-01-24 10:33:42 浏览数 (1)

Silverlight并没有象flash那样直接提供画线、画圆、画曲线的方法,只能用Path来生成贝塞尔曲线。

下面是示例代码:

XAML部分:

代码语言:javascript复制
<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部分:

代码语言:javascript复制
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):贝塞尔曲线

运行截图:

0 人点赞