Start! WPF Custom Control (1) -- turntable menu, wpf Turntable
I have been registering my garden account for six months. I have always wanted to write something, but I don't know where to write it. I have worked as an intern in a company in Wuxi in the last month. I mainly engaged in development related to WPF. Although I have never touched on WPF before, I have learned C # and it is easy to understand it.
Recently, I made a Menu Control for a custom circular turntable. The effect is as follows:
Implementation process:
Key code:
1. Split the circumference evenly among the child nodes. Traverse all child nodes first, then subtract the middle icon, get the number of icons to divide the circumference, then get the split angle, and finally set each icon'sTopPropertyAndLeftPropertyAttribute
1 // the center and surrounding icons are displayed in the same circumference. 2 private void DivideCircleOnShowMenu () 3 {4 // obtain the child node 5 UIElementCollection children = this. children; 6 FrameworkElement f; 7 8 // Cylindrical Radius 9 double outCircleRadius = this. width/2-IconWidthAndHeight/2; 10 11 // level of equality 12 double divide1_lyangle = 360/(children. count-1); 13 14 for (int I = 0; I <children. count; I ++) 15 {16 f = children [I] as FrameworkElement; 17 // The First Intermediate icon 18 if (I = 0) 19 {20 if (ShowMenu) 21 {22 f. setValue (Canvas. topProperty, outCircleRadius); 23 f. setValue (Canvas. leftProperty, outCircleRadius); 24 if (OperateType = OperateEnum. mouseOperate) 25 {26 f. mouseDown + = F_MouseDown; 27} 28 else29 {30 f. touchUp + = F_TouchUp; 31} 32} 33 34 else35 {36 f. setValue (Canvas. topProperty, outCircleRadius-f. width/2); 37 f. setValue (Canvas. leftProperty, outCircleRadius-f. width/2); 38 f. visibility = Visibility. hidden; 39} 40} 41 42 else43 {44 // angular angle conversion to radian 45 double innerAngle = divide1_lyangle * (I-1) * Math. PI/180; 46 47 // TOP distance 48 double topHeight = outCircleRadius-Math. cos (innerAngle) * outCircleRadius; 49 50 // Left distance from 51 double leftWidth = Math. sin (innerAngle) * outCircleRadius; 52 53 if (innerAngle <= 180) 54 {55 f. setValue (Canvas. topProperty, topHeight); 56 f. setValue (Canvas. leftProperty, outCircleRadius + leftWidth); 57} 58 if (innerAngle> 180) 59 {60 f. setValue (Canvas. topProperty, topHeight); 61 f. setValue (Canvas. leftProperty, outCircleRadius-leftWidth); 62} 63} 64} 65}
2. Click the middle icon to rotate the animation for one week. The RotateTransform animation is used here. The animation is very simple, that is, rotating around a point. However, you have to setRenderTransformOriginThis attribute is a relative Point. It takes the upper left corner of each icon as the coordinate origin, and the downward and right are positive. For example, if it is set to (0.5, 0.5), it indicates that each icon rotates around its center, () indicates to rotate around the bottom right corner of itself. Here, I chose to rotate the entire canvas around its center point, and then let each icon turn around itself, so that the icon direction remains unchanged. Finally, here, rotateNumber is a custom dependency attribute, which can be set when this control is applied in the foreground XAML.
1 // canvans rotate 2 private void RotateAnimation (UIElement uIelement, double rotateNumber) 3 {4 RotateTransform rtf = new RotateTransform (); 5 uIelement. renderTransform = rtf; 6 uIelement. renderTransformOrigin = new Point (0.5, 0.5); 7 8 // define the animation path and event 9 DoubleAnimation dbAnimation = new DoubleAnimation (0, rotateNumber, 10 new Duration (TimeSpan. fromSeconds (RotateSpeed); 11 12 // start animation 13 rtf. beginAnimation (RotateTransform. angleProperty, dbAnimation );
3. Implement a rotation animation with the mouse dragging and following. Here, the events include MouseDown, MouseMove, and MouseUp. MainlyMouseMoveTo get the degree of each moving and rotating, and determine the direction of rotation (clockwise or counterclockwise ). I used high school mathematics to find the degree of each drag and rotation,Cosine formula of the angle between two vectors(That's right, it's it. This is also the method I can think of now = ). After calculating the degree of rotation based on this formula, the rotation direction is determined based on the quadrant of each click point and the end point.
// Drag the icon to rotate the event private void Rotate_MouseMove (object sender, MouseEventArgs e) {Point mAfter = e. getPosition (this); // obtain the coordinate Point n1 = new Point (centerP. x-mBefore. x, centerP. y-mBefore. y); Point n2 = new Point (centerP. x-mAfter. x, centerP. y-mAfter. y); // n1 * n2 double n1n2 = n1.X * n2.X + n1.Y * n2.Y; // n1 modulo double n1mo = Math. sqrt (Math. pow (n1.X, 2) + Math. pow (n1.Y, 2); // n2 modulo double n2mo = Math. sqrt (Math. pow (n2.X, 2) + Math. pow (n2.Y, 2); // double rotateNum = Math. acos (n1n2/(n1mo * n2mo); // Point potM = new Point (); potM. X = mAfter. x-centerP. x; potM. Y = centerP. y-mAfter. y; Point potD = new Point (); potD. X = mBefore. x-centerP. x; potD. Y = centerP. y-mBefore. y; // if (mAfter. X <0 | mAfter. x> this. width | mAfter. Y <0 | mAfter. y> this. height) {this. mouseMove-= Rotate_MouseMove;} else {if (GetcLockwise (potD, potM) {rotateAng + = rotateNum;} else {rotateAng-= rotateNum ;}} // execute the rotation animation IconRotateAnimation (-rotateAng); CanvansRotateAnimation (rotateAng );} /// <summary> /// obtain the clockwise or counterclockwise // </summary> /// <param name = "potD"> press the coordinates </param> /// <param name = "potM"> moving coordinates </param> /// <returns> True: shun, False: inverse </returns> private bool GetcLockwise (Point potD, Point potM) {if (potM. y> = 0 & potD. y> = 0) // one or two quadrants {return potM. x> = potD. x;} if (potM. Y <0 & potD. Y <0) // three quadrant {return potM. X <= potD. x;} if (potM. x> = 0 & potD. x> = 0) // a four quadrant {return potM. Y <= potD. y;} if (potM. X <0 & potD. X <0) // limit {return potM. y> = potD. Y ;}else {return true ;}}
Finally, the Touch slide function is added. In fact, it is okay to replace the corresponding Mouse event with the Touch event, but the effect may need to be slightly changed. It was a pity that it would have to be an effect of rotation with inertia, and there were few online resources. Now I think it is quite interesting to develop WPF controls. It is very helpful to train people's logical thinking ability. The opening article ends here. Let's continue!
Attached Demo source code: rotating Menu Control