WP7 Application Development Note (4) circular sliding control implementation

Source: Internet
Author: User
Control Function Analysis

The circular control can recognize the clockwise and counterclockwise sliding gestures and recognize the sliding speed.

 

Related events provided by the system
Onmanipulationstarted Slide start Hand Press
Onmanipulationdelta Moving Hold and move
Onmanipulationcompleted Slide complete Release

These three events are necessary events to achieve slide, because eventargs provides the mobile XY coordinates that have been moved at a speed,

However, it is a pity that you need to implement clockwise recognition.

 

Recognize clockwise sliding

It recognizes clockwise and vice versa, but how can it recognize clockwise sliding,

In fact, this problem has plagued me a lot of time. First, let's look at the default axis structure:

The red brush shows a gesture. It seems that there is no breakthrough. There is no reference for the change of X and Y.

 

You have to change your mind and move the coordinate axis to the center of the circle without changing the direction (Y is slightly different from mathematics)

Similarly, the red brush is used to represent the gesture. The changes of light from X and Y seem to have no reference, but there are some rules in different ranges.

Let's take a look at the variation of X and Y sliding clockwise.

Interval 1 X increase Y decrease
Interval 2 X increase Y increase
Interval 3 X decrease Y decrease
Interval 4 X decrease Y increase

Well, we can basically identify the direction, but it is a bit difficult to write. Is there a better way.

At this time, I lost the geometric structure for N years and suddenly recovered it. I have been entangled in X and Y. Isn't there a concept of angle,

Math, which has been on the bench for a long time, has an atan function in it to find the inverse trigonometric function.

The angle formula is as follows: var angle = math. atan (x/y) * 180.0/Math. Pi;

Next, we can determine the direction of the angle through the interval. These problems are solved. Suddenly I felt the importance of mathematics.

Of course, you can refer to the code implementation for some details.

 

Control Code Implementation

XAML:

View code

<UserControl
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:VirtualKeyboard.Controls"
mc:Ignorable="d"
x:Class="VirtualKeyboard.Controls.LoopControl"
d:DesignWidth="340" d:DesignHeight="340">

<Canvas>
<Ellipse x:Name="bigEllipse" Height="340" Width="340" Canvas.Left="0" Canvas.Top="0" StrokeThickness="4" Stroke="White" Fill="#FF7A7A7A" />
<local:RoundButton x:Name="centerButton" Height="150" Width="150" Canvas.Left="95" Canvas.Top="95" ImageSource="/VirtualKeyboard.Controls;component/Icons/word.ok.png" Background="#FF1D1D1D"/>
</Canvas>
</UserControl>

To facilitate the addition of a circular OK button in the middle, the implementation of this button will be implemented in the following sections. If you are interested in the exercises, you can directly remove the local: roundbutton

C #

View code

Public partial class loopcontrol
{
# Region const
Constdouble bigradius = 200.0;
Const double smailradius = 70.0;
Private readonly timespan deltaspan = new timespan (0, 0, 0, 0,200 );
# Endregion

# Region private
Private datetime starttime;
Private angle startangle;
# Endregion

Public event routedeventhandler centerclick
{
Add {centerbutton. Click + = value ;}
Remove {centerbutton. Click-= value ;}
}

Public event eventhandler <loopglideeventarg> loopglide;

Public void onloopglide (loopglideeventarg E)
{
Eventhandler <loopglideeventarg> handler = loopglide;
If (handler! = NULL) handler (this, e );
}

Public loopcontrol ()
{
// Required for variable Initialization
Initializecomponent ();
}


Protected override void onmanipulationstarted (manipulationstartedeventargs E)
{
Starttime = datetime. now;
Startangle = toangle (E. manipulationorigin );
Base. onmanipulationstarted (E );
}

Protected override void onmanipulationdelta (manipulationdeltaeventargs E)
{
If (isincenter (E. manipulationorigin) return;

VaR now = datetime. now;
If (now-starttime> deltaspan)
{
Getdirection (E. manipulationorigin );
Starttime = now;
Startangle = toangle (E. manipulationorigin );
}
Base. onmanipulationdelta (E );
}

Private void getdirection (point)
{
VaR angle = toangle (point );
VaR angledistance = startangle-angle;
Onloopglide (New loopglideeventarg (angledistance. Distance ));
}

/// <Summary>
/// Angle
/// </Summary>
/// <Param name = "point"> </param>
/// <Returns> </returns>
Private angle toangle (point)
{
VaR xpoint = toxpoint (point );
VaR x = xpoint. X;
Var y = xpoint. Y;
VaR angle = math. atan (x/y) * 180.0/Math. Pi;
If (! (Y <0.0 ))
{
Angle + = 180.0;
}
Else if (X-> 0.0)
{
Angle + = 360.0;
}
Return new angle (angle );
}

/// <Summary>
/// Changed coordinates
/// </Summary>
/// <Param name = "point"> </param>
/// <Returns> </returns>
Private point toxpoint (point)
{
VaR x = point. X-bigradius;
Var y = point. Y-bigradius;
Return new point (x, y );
}

Private bool isincenter (point)
{
VaR xpoint = toxpoint (point );
VaR radius = math. SQRT (xpoint. x * xpoint. x + xpoint. y * xpoint. y );
Return radius <smailradius;
}

# Region private struct

/// <Summary>
/// Angle
/// </Summary>
Private struct angle: iequatable <angle>
{
Private readonly double value;
Private const double Epsilon = 0.1;

Public double value
{
Get {return value ;}
}

Public angle (double value)
{
If (value> 360.0 | value <0)
{
Throw new argumentoutofrangeexception ("value", "value must between 0 and 360 ");
}
This. value = value;
}

Public override string tostring ()
{
Return string. Format ("{0: N2}", value );
}

Public static angledistance operator-(angle angle1, angle angle2)
{
Double angledistance = angle1.value-angle2.value;
If (angledistance> 180.0)
{
Angledistance-= 360;
}
Else if (angledistance <-180.0)
{
Angledistance ++ = 360;
}
Return new angledistance (angledistance );
}

Public override bool equals (Object OBJ)
{
If (obj is angle)
{
Return equals (angle) OBJ );
}
Return false;
}

Public override int gethashcode ()
{
Return 360 ^ value. gethashcode ();
}

Public bool equals (angle other)
{
Return math. Abs (value-other. Value) <Epsilon;
}
}

/// <Summary>
/// Angle
/// </Summary>
Private struct angledistance
{
Private readonly double angledistance;

Public angledistance (double angledistance)
{
This. angledistance = angledistance;
}

Public double distance
{
Get {return angledistance ;}
}

Public override string tostring ()
{
Return string. Format ("{0: N2}", angledistance );
}

/// <Summary>
/// Clockwise
/// </Summary>
Public bool clockwise
{
Get {return angledistance> 0 ;}
}
}
# Endregion


}

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.