How to rotate the Ellipse and border based on dragging border?

1.4k views Asked by At

Please find the attached Image for my requirement.when drag the arc(Border) the arc and wheel rotate through mouse position.can you please help me? if rotate the arc and wheel in button click it working.But i want rotate this in Draging the border(arc).i was stuck with calculation.

XAML:
<Grid HorizontalAlignment="Center">
    <StackPanel Orientation="Horizontal" x:Name="mainStackPanel" RenderTransformOrigin="0.5,0.5">
        <Grid>
            <Border BorderThickness="10" BorderBrush="Blue" MouseMove="Border_MouseMove" MouseLeftButtonDown="Border_MouseLeftButtonDown"
                    MouseLeftButtonUp="Border_MouseLeftButtonUp" Width="10" Height="90" />
        </Grid>
        <Grid x:Name="rotateGrid" Margin="20 0 0 0" RenderTransformOrigin="0.5,0.5">
            <Ellipse Height="250" Width="250" Stroke="Red" StrokeThickness="20"/>
            <Border BorderThickness="10" BorderBrush="Red" Height="15" Width="250"
            HorizontalAlignment="Stretch" VerticalAlignment="Center"/>

            <Border BorderThickness="10" BorderBrush="Red" Width="15"  Height="250"
            HorizontalAlignment="Center" VerticalAlignment="Stretch"/>

            <Border BorderThickness="10" BorderBrush="Red" Width="15"  Height="246" RenderTransformOrigin="0.5,0.5"
            HorizontalAlignment="Center" VerticalAlignment="Stretch">
                <Border.RenderTransform>
                    <RotateTransform Angle="45"/>
                </Border.RenderTransform>
            </Border>
            <Border BorderThickness="10" BorderBrush="Red" Width="15"  Height="246" RenderTransformOrigin="0.5,0.5"
            HorizontalAlignment="Center" VerticalAlignment="Stretch">
                <Border.RenderTransform>
                    <RotateTransform Angle="135"/>
                </Border.RenderTransform>
            </Border>

        </Grid>
        <Grid Margin="20 0 0 0">
            <Border BorderThickness="10" BorderBrush="Blue" Width="10" Height="90" />
        </Grid>

    </StackPanel>

Code Behind:
RotateTransform trans = new RotateTransform();
    double angle = 30;
    Point oldPoint;
    Point newPoint;
    bool dragStarted = false;

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        trans.Angle = angle;
        mainStackPanel.RenderTransform = trans;
        if (angle >= 360)
            angle = 0;
        angle += 30;
    }

    private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        dragStarted = true;
        oldPoint = e.GetPosition(this);
        Mouse.Capture(sender as IInputElement);
    }

    private void Border_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        Mouse.Capture(null);
        oldPoint = new Point(0, 0);
        newPoint = new Point(0, 0);
        dragStarted = false;
    }
    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
    {
        Mouse.Capture(null);
        oldPoint = new Point(0, 0);
        newPoint = new Point(0, 0);
        dragStarted = false;
        base.OnMouseLeftButtonUp(e);
    }

    private void Border_MouseMove(object sender, MouseEventArgs e)
    {
        if (dragStarted)
        {
            newPoint = e.GetPosition(this);
            if (oldPoint.Y != newPoint.Y)
            {
                if (oldPoint.Y > newPoint.Y)
                    trans.Angle = (oldPoint.Y - newPoint.Y);
                else
                    trans.Angle += (newPoint.Y - oldPoint.Y);

                mainStackPanel.RenderTransform = trans;
            }
        }
    }

enter image description here

1

There are 1 answers

0
Sheridan On

First, I would change these lines:

if (angle >= 360)
        angle = 0;
    angle += 30;

To this line:

angle = angle >= 330 ? 0 : angle + 30;

Although I doubt that it would cause too much problem as it is. In your code, if angle equalled 350 for instance, then it would end up as 380, but WPF should wrap that angle round to an effective angle of 20 anyway.

Ahhhhhhh... I've just worked out your exact requirement... you want the user to move the mouse and you want the shape to rotate just as far as the user has moved the mouse so that it virtually looks like they are actually physically moving it.

Right, here goes... I can explain what you have to do, but not do it for you. I hope that your trigonometry is good because I haven't used it for decades! Basically, if I remember correctly, we want to create some imaginary triangles to get our figures for the calculations. The points of the triangle will come from the centre of the circle and various points around its circumference. So the first thing is to make note of the exact Point that the centre of the circle resides in... I'll leave that to you.

Next, we want to find the other figures to use. One will always be either directly above, below, left, or right of the centre, so that our triangle will always have a right angle... we need this if we want our calls to Math.Sin and Math.Cos to return valid results. If you don't know about trigonometry, you can find out more by looking at the Sine, Cosine and Tangent page on the Maths Is Fun website.

The third and last point of each triangle will be the position of the mouse, or more accurately, the position on the circumference in the direction of the mouse cursor. This is achieved by creating a bigger imaginary circle that includes the mouse cursor position, the circle centre and the position either directly above, below, left, or right of the centre, so that our bigger triangle also has a right angle.

Having formed these imaginary triangles (you may benefit from drawing these on paper to help visualise the situation), you can then use the Math class' Sin and Cos methods to calculate the required angles to rotate your shape to. Although I believe that the RotateTransform.Angle property is in degrees (MSDN not available at the moment), you may need to adjust your resulting angle values to fit in with WPF's weird 0 degrees position (by adding or subtracting a divisor of 90).

The last thing is for me to wish you good luck.