【C #】 WPF wave line effect

 using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Navigation;

using System.Windows.Shapes;

using WaveLineTextDemo;


namespace waveLine

{

    /// <summary>

    /// Interaction logic for MainWindow.xaml

    /// </summary>

    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

        }

        private Point? _startPoint = null;

        private void ContainerCanvas_OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)

        {

            var position = e.GetPosition(ContainerCanvas);

            if (_startPoint == null)

            {

                _startPoint = position;

            }

            else

            {


                //Delete preview

                if (_previewLineElement != null)

                {

                    ContainerCanvas.Children.Remove(_previewLineElement);

                    _previewLineElement = null;

                    _lastMovedPoint = null;

                }


                //Determine the end point and draw a wavy line

                var myLineElement = new MyLineElement();

                myLineElement.DrawLine((Point)_startPoint, position);

                ContainerCanvas.Children.Add(myLineElement);

                _startPoint = null;

            }

        }


        private MyLineElement _previewLineElement = null;

        private Point? _lastMovedPoint = null;



        private void ContainerCanvas_OnMouseMove(object sender, MouseEventArgs e)

        {

            var position = e.GetPosition(ContainerCanvas);

            if (_startPoint != null && (_lastMovedPoint == null || _lastMovedPoint != null & (position - (Point)_lastMovedPoint).Length >= 2))

            {

                _lastMovedPoint = position;

                if (_previewLineElement != null)

                {

                    ContainerCanvas.Children.Remove(_previewLineElement);

                }

                var myLineElement = new MyLineElement();

                myLineElement.DrawLine((Point)_startPoint, position);

                ContainerCanvas.Children.Add(myLineElement);

                _previewLineElement = myLineElement;

            }

        }

    }

}

<Window x:Class="waveLine.MainWindow"
        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"
        xmlns:local="clr-namespace:waveLine"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Canvas x:Name="ContainerCanvas" PreviewMouseLeftButtonDown="ContainerCanvas_OnPreviewMouseLeftButtonDown"
               MouseMove="ContainerCanvas_OnMouseMove"
               Background="LightGray"></Canvas>
    </Grid>
</Window>

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace WaveLineTextDemo
{
    class MyLineElement : FrameworkElement
    {
        public MyLineElement()
        {
            _visualShape = new VisualCollection(this);
        }
        internal void DrawLine(Point startPoint, Point endPoint)
        {
            List<Point> points = ForgePoints(startPoint, endPoint);
            DrawLine(points);
        }
        private const int SeparatorPiexl = 4;
        private const int AbundancePiexl = 3;
        private List<Point> ForgePoints(Point startPoint, Point endPoint)
        {
            var points = new List<Point>();

            var lineVector = endPoint - startPoint;
            var lineDistance = lineVector.Length;
            var lineAngle = Math.Atan2(-(endPoint.Y - startPoint.Y), endPoint.X - startPoint.X);

            points.Add(startPoint);
            int index = 0;
            bool isAbundanceUpward = true;
            while (index * SeparatorPiexl < lineDistance)
            {
                index++;

                //Calculate the interval length (simulation point to starting point)
                var separatorDistance = index * SeparatorPiexl;
                var abundancePiexl = AbundancePiexl;
                var distanceToStartPoint = Math.Sqrt(Math.Pow(separatorDistance, 2) + Math.Pow(abundancePiexl, 2));
                //Calculate the simulation point, starting point, and the angle to the straight line
                var separatorAngle = Math.Atan2(AbundancePiexl, separatorDistance);
                separatorAngle = isAbundanceUpward ? separatorAngle : -separatorAngle;
                isAbundanceUpward = !isAbundanceUpward;

                //Get the horizontal angle of the simulated point
                var mockPointAngle = lineAngle + separatorAngle;

                //Calculate the simulation point coordinates
                var verticalDistance = distanceToStartPoint * Math.Sin(mockPointAngle);
                var horizontalDistance = distanceToStartPoint * Math.Cos(mockPointAngle);
                var mockPoint = new Point(startPoint.X + horizontalDistance, startPoint.Y - verticalDistance);
                points.Add(mockPoint);
            }
            points.Add(endPoint);
            return points;
        }

        private void DrawLine(List<Point> points)
        {
            _visualShape.Clear();

            var geometryTest = new StreamGeometry();
            using (var ctx = geometryTest.Open())
            {
                ctx.BeginFigure(points[0], true, false);
                if (points.Count % 2 == 0)
                {

                    //Draw the second-order Bessel function, need to ensure that it is an even point
                    ctx.PolyQuadraticBezierTo(points, true, true);
                }
                else
                {

                    //Draw the second-order Bessel function, need to ensure that it is an even point
                    points.Insert(0, points[0]);
                    ctx.PolyQuadraticBezierTo(points, true, true);
                }

                ctx.Close();
            }

            var visual = new DrawingVisual();
            using (var context = visual.RenderOpen())
            {
                context.DrawGeometry(FillBrush, StrokePen, geometryTest);
            }
            _visualShape.Add(visual);
        }

        #region InternalMethod

        [Obsolete]
        protected override void OnRender(DrawingContext drawingContext)
        {

            //Deprecated, changed to _visualShape filling implementation
            //drawingContext.DrawGeometry(FillBrush, StrokePen, BaseGeometry);
        }

        protected override int VisualChildrenCount => _visualShape.Count;

        protected override Visual GetVisualChild(int index)
        {
                if (index < 0 || index >= _visualShape.Count)
                {
                    throw new ArgumentOutOfRangeException();
                }

                return _visualShape[index];
            }

        #endregion
        #region CurveAttributes

        private readonly VisualCollection _visualShape;
            protected Brush FillBrush {  get; set; } = Brushes.Transparent;
        public Brush LineBrush {  get; set; } = Brushes.DarkSeaGreen;
        protected double BorderThickness {  get; set; } = 1.0;
        private Pen _defaultPen = null;
        protected Pen StrokePen
        {
            get
            {
                if (_defaultPen == null)
                {
                    _defaultPen = new Pen(LineBrush, BorderThickness);
                }
                return _defaultPen;
            }
            set => _defaultPen = value;
        }

        #endregion}
    }
}

No comments:

Pipe and Drape Backdrop Ideas for Weddings: Budget-Friendly Elegance

We get it. You've envisioned the perfect wedding venue, a space overflowing with love, joy, and elegance. But when it comes to backdrops...

Contact Form

Name

Email *

Message *