不同平台(mac、windows—wpf、web、ios、android)下实现页面的转场动画

最简单的转场动画就是在一个黑色的圆角矩形里面加载一个菊花轮,但如果项目要求高一些,就需要我们自己来实现一个自定义的转场动画了,不多说,先上效果图:


Mac上是通过一个NSTimer计时器然后不停地重绘来实现的,转场动画封装在一个NSView中,具体代码如下:

// 上海诸君信息科技有限公司版权所有
// 海学权
//
using System;
using AppKit;
using CoreGraphics;
using Foundation;

namespace LoadingViewTest
{
	public class LoadingView:NSView
	{
		//缩放比例,原图是按照256*256来画的
		float scale;

		//圆形里面的三种颜色
		CGColor color1;
		CGColor color2;
		CGColor color3;

		//第一条曲线的起始点
		public CGPoint curve1StartPoint;
		//第一条曲线的结束点
		public CGPoint curve1EndPoint;

		//第二条曲线的起始点
		public CGPoint curve2StartPoint;
		//第二条曲线的结束点
		public CGPoint curve2EndPoint;

		//圆里面第一条曲线的贝塞尔控制点
		public CGPoint cp1;
		public CGPoint cp2;
		public CGPoint cp3;
		public CGPoint cp4;
		public CGPoint cp5;
		public CGPoint cp6;
		public CGPoint cp7;
		public CGPoint cp8;

		//圆里面第二条曲线的贝塞尔控制点
		public CGPoint rcp1;
		public CGPoint rcp2;
		public CGPoint rcp3;
		public CGPoint rcp4;
		public CGPoint rcp5;
		public CGPoint rcp6;
		public CGPoint rcp7;
		public CGPoint rcp8;

		//闪电路径中的点
		public CGPoint lightningP1;
		public CGPoint lightningP2;
		public CGPoint lightningP3;
		public CGPoint lightningP4;
		public CGPoint lightningP5;
		public CGPoint lightningP6;

		//嘴的贝塞尔控制点
		public CGPoint MouthControlP1;
		public CGPoint MouthControlP2;

		//左胳膊的贝塞尔控制点
		public CGPoint LeftArmCP1;
		public CGPoint LeftArmCP2;

		//右胳膊贝塞尔控制点
		public CGPoint RightArmCP1;
		public CGPoint RightArmCP2;

		//眼睛的旋转角度
		public float EyeRotateAngle;

		float eyeWidth = 26;

		float eyeLineWidth = 5;

		//手的旋转角度
		public float HandRotateAngle;

		//是否要动化显示的标记
		bool animationFlag = false;

		nfloat LightningAlpha = 0;
		bool showLighting = true;
		//实例化方法
		public LoadingView(CGRect frame) : base(frame)
		{
			scale =(float)(frame.Width / 256);

			curve1StartPoint = new CGPoint(58, 167).MagnifyPoint(scale);
			curve1EndPoint = new CGPoint(174, 62.5f).MagnifyPoint(scale);
			curve2StartPoint = new CGPoint(120, 207.75f).MagnifyPoint(scale);
			curve2EndPoint = new CGPoint(206.5f, 112.5f).MagnifyPoint(scale);
			//为属性设置初始值
			color1 = new CGColor(0, 159 / 255f, 239 / 255f);
			color2 = new CGColor(85 / 255f, 198 / 255f, 237 / 255f);
			color3 = new CGColor(153 / 255f, 223 / 255f, 246 / 255f);

			cp1 = new CGPoint(97, 162).MagnifyPoint(scale);
			cp2 = new CGPoint(112, 143).MagnifyPoint(scale);
			cp3 = new CGPoint(87, 81).MagnifyPoint(scale);
			cp4 = new CGPoint(116, 56).MagnifyPoint(scale);
			cp5 = new CGPoint(147, 74).MagnifyPoint(scale);
			cp6 = new CGPoint(156, 77).MagnifyPoint(scale);
			cp7 = new CGPoint(101, 14.5f).MagnifyPoint(scale);
			cp8 = new CGPoint(19.75f, 91.5f).MagnifyPoint(scale);

			rcp1 = new CGPoint(122, 197).MagnifyPoint(scale);
			rcp2 = new CGPoint(165, 193).MagnifyPoint(scale);
			rcp3 = new CGPoint(134, 133).MagnifyPoint(scale);
			rcp4 = new CGPoint(153, 105).MagnifyPoint(scale);
			rcp5 = new CGPoint(194, 117).MagnifyPoint(scale);
			rcp6 = new CGPoint(195, 120).MagnifyPoint(scale);
			rcp7 = new CGPoint(215.75f, 156.5f).MagnifyPoint(scale);
			rcp8 = new CGPoint(183.5f, 213.25).MagnifyPoint(scale);

			lightningP1 = new CGPoint(-11, 4).MagnifyPoint(scale);
			lightningP2 = new CGPoint(-1, 1).MagnifyPoint(scale);
			lightningP3 = new CGPoint(-1, 5).MagnifyPoint(scale);
			lightningP4 = new CGPoint(11, -4).MagnifyPoint(scale);
			lightningP5 = new CGPoint(1, -1).MagnifyPoint(scale);
			lightningP6 = new CGPoint(1, -5).MagnifyPoint(scale);

			//CGPoint mouseControlStartP1 = new CGPoint(148.5f,180);
			//CGPoint mouseControlStartP2 = new CGPoint(156,172.5f);

			CGPoint mouseControlStartP1 = new CGPoint(120, 162.5f);
			CGPoint mouseControlStartP2 = new CGPoint(151, 163.5f);


			CGPoint mouseControlEndP1 = new CGPoint(149.5f, 140.5f);
			CGPoint mouseControlEndP2 = new CGPoint(174.5f, 145);

			MouthControlP1 = mouseControlStartP1.MagnifyPoint(scale);
			MouthControlP2 = mouseControlStartP2.MagnifyPoint(scale);


			LeftArmCP1 = new CGPoint(-6,59).MagnifyPoint(scale);
			LeftArmCP2 = new CGPoint(70,69).MagnifyPoint(scale);
			RightArmCP1 = new CGPoint(253,208).MagnifyPoint(scale);
			RightArmCP2 = new CGPoint(222,156).MagnifyPoint(scale);

			EyeRotateAngle = 70;

			HandRotateAngle = 30;

			//用一个timer不停地重绘来实现颜色交替变化的动画
			int i = 0;
			NSTimer.CreateRepeatingScheduledTimer(0.3, delegate (NSTimer timer)
			{
				if (animationFlag)
				{
					i = (i + 1) % 3;
					CGColor tmpcolor = color1;
					color1 = color3;
					color3 = color2;
					color2 = tmpcolor;
					SetNeedsDisplayInRect(this.Bounds);
				}
			});

			//嘴巴的贝塞尔控制点的变化范围
			float diffX1 = ((float)(mouseControlEndP1.X) - (float)(mouseControlStartP1.X))*scale;
			float diffX2 = ((float)(mouseControlEndP2.X) - (float)(mouseControlStartP2.X)) * scale;
			float diffY1 = ((float)(mouseControlEndP1.Y) - (float)(mouseControlStartP1.Y)) * scale;
			float diffY2 = ((float)(mouseControlEndP2.Y) - (float)(mouseControlStartP2.Y)) * scale;

			float handAngleDiff = -50;
			float eyeAngleDiff = -70;
			float eyeWidthDiff = 8;
			float eyeLineWidthDiff = 5;

			//控制动画方向的标识
			bool eyeAddFlag = true;
			//用一个timer不停地重绘来实现嘴巴、眼睛、手的动画
			int j = 0;
			//帧数
			float frameCount = 30;
			NSTimer.CreateRepeatingScheduledTimer(0.05, delegate (NSTimer timer)
			{
				if (animationFlag==false)
				{
					return;
				}
				if (eyeAddFlag)
				{
					j = j + 1;
					if (j > frameCount)
					{
						eyeAddFlag = false;
					}
					EyeRotateAngle += 1 / (float)frameCount * eyeAngleDiff;

					eyeWidth -= 1 / (float)frameCount * eyeWidthDiff;

					eyeLineWidth += 1 / (float)frameCount * eyeLineWidthDiff;

					HandRotateAngle += 1 / (float)frameCount * handAngleDiff;

					MouthControlP1 = new CGPoint(MouthControlP1.X + (diffX1 / frameCount), MouthControlP1.Y + (diffY1 / frameCount));
					MouthControlP2 = new CGPoint(MouthControlP2.X + (diffX2 / frameCount), MouthControlP2.Y + (diffY2 / frameCount));

				}
				else
				{
					j = j - 1;
					if (j < 0)
					{
						eyeAddFlag = true;
					}
					EyeRotateAngle -= 1 / (float)frameCount * eyeAngleDiff;
					eyeWidth += 1 / (float)frameCount * eyeWidthDiff;
					eyeLineWidth -= 1 / (float)frameCount * eyeLineWidthDiff;

					HandRotateAngle -= 1 / (float)frameCount * handAngleDiff;

					MouthControlP1 = new CGPoint(MouthControlP1.X - (diffX1 / frameCount), MouthControlP1.Y - (diffY1 / frameCount));
					MouthControlP2 = new CGPoint(MouthControlP2.X - (diffX2 / frameCount), MouthControlP2.Y - (diffY2 / frameCount));
				}
				LightningAlpha = j / frameCount;
				if (j % 10 == 0)
				{
					showLighting = true;
				}
				else
				{
					showLighting = false;
				}
				SetNeedsDisplayInRect(this.Bounds);
			});

		}

		//开始动画
		public void StartAnimation() {
			animationFlag = true;
		}

		//结束动画
		public void StopAnimation() {
			animationFlag = false;
		}

		//绘制方法
		public override void DrawRect(CGRect dirtyRect)
		{
			dirtyRect = this.Bounds;
			//获取当前画布
			CGContext context = NSGraphicsContext.CurrentContext.GraphicsPort;



			//圆形的四周边距
			nfloat margin = 44*scale;

			//圆形所在的矩形
			CGRect circleRect = new CGRect(margin,margin,dirtyRect.Width-(margin*2),dirtyRect.Height-(margin*2));

			//圆形的线宽
			nfloat lineWidth = 8 * scale;
			context.SetLineWidth(lineWidth);
			context.SetStrokeColor(NSColor.Black.CGColor);
			context.SetFillColor(color2);
			context.StrokeEllipseInRect(circleRect);
			margin = 48 * scale;
			context.FillEllipseInRect(new CGRect(margin, margin, dirtyRect.Width - (margin * 2), dirtyRect.Height - (margin * 2)));

			//第一条曲线的路径
			CGPath path1 = new CGPath();
			path1.MoveToPoint(curve1StartPoint);

			CGPoint endp = new CGPoint(100, 114).MagnifyPoint(scale);
			path1.AddCurveToPoint(cp1, cp2, endp);


			CGPoint endp2 = new CGPoint(140, 72).MagnifyPoint(scale);
			path1.AddCurveToPoint(cp3, cp4, endp2);



			path1.AddCurveToPoint(cp5, cp6, curve1EndPoint);

			path1.AddCurveToPoint(cp7, cp8, curve1StartPoint);

			context.SetFillColor(color1);
			context.AddPath(path1);
			context.FillPath();

			//第二条曲线
			CGPath path2 = new CGPath();

			path2.MoveToPoint(curve2StartPoint);

			CGPoint rendp = new CGPoint(144, 154).MagnifyPoint(scale);
			path2.AddCurveToPoint(rcp1, rcp2, rendp);


			CGPoint rendp2 = new CGPoint(180, 110).MagnifyPoint(scale);
			path2.AddCurveToPoint(rcp3, rcp4, rendp2);


			path2.AddCurveToPoint(rcp5, rcp6, curve2EndPoint);


			path2.AddCurveToPoint(rcp7, rcp8, curve2StartPoint);

			context.SetFillColor(color3);
			context.AddPath(path2);
			context.FillPath();

			//眼睛
			context.SetFillColor(NSColor.Black.CGColor);
			CGPoint leftEyeCenterPoint = new CGPoint(119,165).MagnifyPoint(scale);
			CGPoint rightEyeCenterPoint = new CGPoint(147,181).MagnifyPoint(scale);

			float angle = (float)(36f / 180 * Math.PI);
			float eyeAngle=(float)(EyeRotateAngle / 180 * Math.PI);
			context.TranslateCTM(leftEyeCenterPoint.X,leftEyeCenterPoint.Y);//移动光标到指定位置
			context.RotateCTM(angle);

			float cornerWidth = eyeLineWidth / 2 * scale;
			context.RotateCTM(eyeAngle);
			CGPath leftEyePath1 = new CGPath();
			leftEyePath1.AddRoundedRect(new CGRect(-cornerWidth, -cornerWidth, eyeLineWidth * scale, eyeWidth * scale), cornerWidth, cornerWidth);
			context.AddPath(leftEyePath1);
			context.FillPath();
			context.RotateCTM(-eyeAngle);

			context.RotateCTM((float)(Math.PI)-eyeAngle);
			CGPath leftEyePath2 = new CGPath();
			leftEyePath2.AddRoundedRect(new CGRect(-cornerWidth, -cornerWidth, eyeLineWidth * scale, eyeWidth * scale), cornerWidth, cornerWidth);
			context.AddPath(leftEyePath2);
			context.FillPath();
			context.RotateCTM(eyeAngle-(float)(Math.PI));

			context.RotateCTM(-angle);//转回去
			context.TranslateCTM(-leftEyeCenterPoint.X, -leftEyeCenterPoint.Y);


			context.TranslateCTM(rightEyeCenterPoint.X, rightEyeCenterPoint.Y);//移动光标到指定位置
			context.RotateCTM(angle);

			context.RotateCTM(eyeAngle+(float)(Math.PI));
			CGPath rightEyePath1 = new CGPath();
			rightEyePath1.AddRoundedRect(new CGRect(-cornerWidth, -cornerWidth, eyeLineWidth * scale, eyeWidth * scale), cornerWidth, cornerWidth);
			context.AddPath(rightEyePath1);
			context.FillPath();
			context.RotateCTM(-eyeAngle-(float)(Math.PI));

			context.RotateCTM(-eyeAngle);
			CGPath rightEyePath2 = new CGPath();
			rightEyePath2.AddRoundedRect(new CGRect(-cornerWidth, -cornerWidth, eyeLineWidth * scale, eyeWidth * scale), cornerWidth, cornerWidth);
			context.AddPath(rightEyePath2);
			context.FillPath();
			context.RotateCTM(eyeAngle);

			context.RotateCTM(-angle);//转回去
			context.TranslateCTM(-rightEyeCenterPoint.X, -rightEyeCenterPoint.Y);

			//嘴巴
			CGPath mousePaht = new CGPath();
			CGPoint mousePoint1 = new CGPoint(118,134).MagnifyPoint(scale);
			CGPoint mousePoint2 = new CGPoint(165,165).MagnifyPoint(scale);
			mousePaht.MoveToPoint(mousePoint1);
			mousePaht.AddCurveToPoint(MouthControlP1, MouthControlP2, mousePoint2);
			context.SetLineWidth(5*scale);
			context.AddPath(mousePaht);
			context.StrokePath();

			context.SetFillColor(NSColor.Black.CGColor);
			CGRect mouseRect1 = new CGRect(mousePoint1.X-(2.5f*scale),mousePoint1.Y - (2.5f * scale),5 * scale,5 * scale);
			CGRect mouseRect2 = new CGRect(mousePoint2.X - (2.5f * scale), mousePoint2.Y - (2.5f * scale), 5 * scale,5 * scale);
			context.FillEllipseInRect(mouseRect1);
			context.FillEllipseInRect(mouseRect2);

			//手臂
			CGPoint leftArmP1 = new CGPoint(48,106).MagnifyPoint(scale);
			CGPoint leftArmP2 = new CGPoint(129,95).MagnifyPoint(scale);

			CGPoint rightArmP1 = new CGPoint(188,189).MagnifyPoint(scale);
			CGPoint rightArmP2 = new CGPoint(163,115).MagnifyPoint(scale);

			CGPath armPath = new CGPath();
			armPath.MoveToPoint(leftArmP1);
			armPath.AddCurveToPoint(LeftArmCP1,LeftArmCP2,leftArmP2);

			armPath.MoveToPoint(rightArmP1);
			armPath.AddCurveToPoint(RightArmCP1,RightArmCP2,rightArmP2);

			context.AddPath(armPath);
			context.SetLineWidth(8*scale);
			context.StrokePath();

			CGPoint leftHandP = leftArmP2;
			CGPoint rightHandP = rightArmP2;
			CGPath leftHandPath = new CGPath();
			leftHandPath.AddRoundedRect(new CGRect(-5* scale, -4* scale, 10* scale, 28* scale), 5* scale, 5* scale);
			float handAngle = (float)(HandRotateAngle/180 * Math.PI);
			context.TranslateCTM(leftHandP.X, leftHandP.Y);//移动光标到指定位置
			context.RotateCTM(handAngle);
			context.AddPath(leftHandPath);
			context.FillPath();
			context.RotateCTM(-handAngle);//转回去
			context.TranslateCTM(-leftHandP.X, -leftHandP.Y);

			CGPath rightHandPath = new CGPath();
			rightHandPath.AddRoundedRect(new CGRect(-5* scale, -24* scale, 10* scale, 28* scale), 5* scale, 5* scale);
			context.TranslateCTM(rightHandP.X, rightHandP.Y);//移动光标到指定位置
			context.RotateCTM(handAngle);
			context.AddPath(rightHandPath);
			context.FillPath();
			context.RotateCTM(-handAngle);//转回去
			context.TranslateCTM(-rightHandP.X, -rightHandP.Y);

			if (showLighting)
			{
				CGPoint lightningCenterP = new CGPoint((leftArmP2.X + rightArmP2.X) / 2.0f, (leftArmP2.Y + rightArmP2.Y) / 2.0f);
				CGPath lightningPath = new CGPath();

				lightningPath.MoveToPoint(lightningP1);
				lightningPath.AddLineToPoint(lightningP2);
				lightningPath.AddLineToPoint(lightningP3);
				lightningPath.AddLineToPoint(lightningP4);
				lightningPath.AddLineToPoint(lightningP5);
				lightningPath.AddLineToPoint(lightningP6);
				lightningPath.AddLineToPoint(lightningP1);
				lightningPath.CloseSubpath();

				context.TranslateCTM(lightningCenterP.X, lightningCenterP.Y);//移动光标到指定位置
				context.RotateCTM(handAngle);
				context.AddPath(lightningPath);
				context.SetFillColor(new CGColor(1, 213 / 255f, LightningAlpha));
				context.FillPath();
				context.RotateCTM(-handAngle);//转回去
				context.TranslateCTM(-lightningCenterP.X, -lightningCenterP.Y);
			}

		}

	}
}

Demo可以从下面的地址下载:

Xamarin.Mac版本转场动画Demo

ios上的实现原理和Mac上的相识,只不多ios中的y坐标系和mac上是相反的,所以需要进行上下翻转,代码相识,这里就不写了。


网页版本是通过svg实现的,具体代码如下:





    svg网页版地球动画




    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
        
        
        
    


SVG动画相关的知识可以从参考下面的网址:

svg动画相关

Windows版本(WPF)是通过Storyboard的动画来实现的,具体代码如下:


    
        
            
                
                
                
            
            
                
                
                
            
            
                
                
                
            
            
                
                
                
            
            
                
                
                
            
            
                
                
                
            
            
                
                
                
            
            
                
                
                
            
            
                
                
                
            
            
                
                
                
            
            
                
                
                
            
            
                
                
                
            
            
                
                
                
                
                
                
                
            
            
                
                
                
                
                
                
                
            
            
                
                
                
                
                
                
                
            
            
                
                
                
            
            
                
                
                
            
            
                
                
                
            
            
                
                
                
            
            
                
                
                
            
        
    
    
        
            
        
    
    
        
            
            
            
            
            
            
            
                
                    
                        
                        
                        
                        
                    
                
                
                    
                        
                            
                        
                    
                
            
            
                
                    
                        
                        
                        
                        
                    
                
                
                    
                        
                            
                        
                    
                
            
            
                
                    
                        
                            
                            
                        
                    
                
            
            
                
                    
                        
                            
                            
                        
                    
                
                
                    
                        
                        
                        
                        
                    
                
            
            
                
                    
                        
                            
                        
                    
                
            
            
                
                    
                        
                        
                        
                        
                    
                
            
        
    

WPF版本的Demo可以从这里下载:


WPF版本转场动画


Android版本的转场动画和ios的原理相似,只不过是方法名称有些细微差别,具体代码如下:

// 上海诸君信息科技有限公司版权所有
// 海学权
//
using System;
using Android.Content;
using Android.Graphics;
using Android.Views;
using Java.Util;

namespace LoadingViewForAndroid
{
	public class LoadingView:View
	{
		protected Context _context;
		public float Scale { get; set; }

		//圆形里面的三种颜色
		public Color color1;
		public Color color2;
		public Color color3;

		//第一条曲线的起始点
		public PointF curve1StartPoint;
		//第一条曲线的结束点
		public PointF curve1EndPoint;

		//第二条曲线的起始点
		public PointF curve2StartPoint;
		//第二条曲线的结束点
		public PointF curve2EndPoint;

		//圆里面第一条曲线的贝塞尔控制点
		public PointF cp1;
		public PointF cp2;
		public PointF cp3;
		public PointF cp4;
		public PointF cp5;
		public PointF cp6;
		public PointF cp7;
		public PointF cp8;

		//圆里面第二条曲线的贝塞尔控制点
		public PointF rcp1;
		public PointF rcp2;
		public PointF rcp3;
		public PointF rcp4;
		public PointF rcp5;
		public PointF rcp6;
		public PointF rcp7;
		public PointF rcp8;

		//闪电路径中的点
		public PointF lightningP1;
		public PointF lightningP2;
		public PointF lightningP3;
		public PointF lightningP4;
		public PointF lightningP5;
		public PointF lightningP6;

		//嘴的贝塞尔控制点
		public PointF MouthControlP1;
		public PointF MouthControlP2;

		//左胳膊的贝塞尔控制点
		public PointF LeftArmCP1;
		public PointF LeftArmCP2;

		//右胳膊贝塞尔控制点
		public PointF RightArmCP1;
		public PointF RightArmCP2;

		//眼睛的旋转角度
		public float EyeRotateAngle;

		float eyeWidth = 26;

		float eyeLineWidth = 4;

		//手的旋转角度
		public float HandRotateAngle;

		//是否要动化显示的标记
		bool animationFlag = true;

		float LightningAlpha = 0;
		bool showLighting = true;

		public LoadingView(Context context,float scale):base(context)
		{
			this._context = context;
			this.Scale = scale;

			curve1StartPoint = new PointF(58, 167).MagnifyPoint(scale);
			curve1EndPoint = new PointF(174, 62.5f).MagnifyPoint(scale);
			curve2StartPoint = new PointF(120, 207.75f).MagnifyPoint(scale);
			curve2EndPoint = new PointF(206.5f, 112.5f).MagnifyPoint(scale);
			//为属性设置初始值
			color1 = new Color(0, 159, 239);
			color2 = new Color(85, 198, 237);
			color3 = new Color(153, 223, 246);

			cp1 = new PointF(97, 162).MagnifyPoint(scale);
			cp2 = new PointF(112, 143).MagnifyPoint(scale);
			cp3 = new PointF(87, 81).MagnifyPoint(scale);
			cp4 = new PointF(116, 56).MagnifyPoint(scale);
			cp5 = new PointF(147, 74).MagnifyPoint(scale);
			cp6 = new PointF(156, 77).MagnifyPoint(scale);
			cp7 = new PointF(101, 14.5f).MagnifyPoint(scale);
			cp8 = new PointF(19.75f, 91.5f).MagnifyPoint(scale);

			rcp1 = new PointF(122, 197).MagnifyPoint(scale);
			rcp2 = new PointF(165, 193).MagnifyPoint(scale);
			rcp3 = new PointF(134, 133).MagnifyPoint(scale);
			rcp4 = new PointF(153, 105).MagnifyPoint(scale);
			rcp5 = new PointF(194, 117).MagnifyPoint(scale);
			rcp6 = new PointF(195, 120).MagnifyPoint(scale);
			rcp7 = new PointF(215.75f, 156.5f).MagnifyPoint(scale);
			rcp8 = new PointF(183.5f, 213.25f).MagnifyPoint(scale);

			lightningP1 = new PointF(-11, 4).MagnifyPoint(scale);
			lightningP2 = new PointF(-1, 1).MagnifyPoint(scale);
			lightningP3 = new PointF(-1, 5).MagnifyPoint(scale);
			lightningP4 = new PointF(11, -4).MagnifyPoint(scale);
			lightningP5 = new PointF(1, -1).MagnifyPoint(scale);
			lightningP6 = new PointF(1, -5).MagnifyPoint(scale);

			//CGPoint mouseControlStartP1 = new CGPoint(148.5f,180);
			//CGPoint mouseControlStartP2 = new CGPoint(156,172.5f);

			PointF mouseControlStartP1 = new PointF(120, 162.5f);
			PointF mouseControlStartP2 = new PointF(151, 163.5f);


			PointF mouseControlEndP1 = new PointF(149.5f, 140.5f);
			PointF mouseControlEndP2 = new PointF(174.5f, 145);

			MouthControlP1 = mouseControlStartP1.MagnifyPoint(scale);
			MouthControlP2 = mouseControlStartP2.MagnifyPoint(scale);


			LeftArmCP1 = new PointF(-6, 59).MagnifyPoint(scale);
			LeftArmCP2 = new PointF(70, 69).MagnifyPoint(scale);
			RightArmCP1 = new PointF(253, 208).MagnifyPoint(scale);
			RightArmCP2 = new PointF(222, 156).MagnifyPoint(scale);

			EyeRotateAngle = 70;

			HandRotateAngle = 30;

			#region timer动画先注释掉

			//用一个timer不停地重绘来实现颜色交替变化的动画
			int i = 0;
			System.Timers.Timer t = new System.Timers.Timer(300);
			t.Elapsed += delegate (object sender, System.Timers.ElapsedEventArgs e)
			{

				if (animationFlag)
				{
					i = (i + 1) % 3;
					Color tmpcolor = color1;
					color1 = color3;
					color3 = color2;
					color2 = tmpcolor;
					PostInvalidate();
				}
			};
			t.Enabled = true;
			t.Start();


			//嘴巴的贝塞尔控制点的变化范围
			float diffX1 = ((float)(mouseControlEndP1.X) - (float)(mouseControlStartP1.X)) * scale;
			float diffX2 = ((float)(mouseControlEndP2.X) - (float)(mouseControlStartP2.X)) * scale;
			float diffY1 = ((float)(mouseControlEndP1.Y) - (float)(mouseControlStartP1.Y)) * scale;
			float diffY2 = ((float)(mouseControlEndP2.Y) - (float)(mouseControlStartP2.Y)) * scale;

			float handAngleDiff = -50;
			float eyeAngleDiff = -70;
			float eyeWidthDiff = 8;
			float eyeLineWidthDiff = 4;

			//控制动画方向的标识
			bool eyeAddFlag = true;
			//用一个timer不停地重绘来实现嘴巴、眼睛、手的动画
			int j = 0;
			//帧数
			float frameCount = 30;

			System.Timers.Timer t2 = new System.Timers.Timer(50);
			t2.Elapsed += delegate (object sender, System.Timers.ElapsedEventArgs e)
			{

				if (animationFlag == false)
				{
					return;
				}
				if (eyeAddFlag)
				{
					j = j + 1;
					if (j > frameCount)
					{
						eyeAddFlag = false;
					}
					EyeRotateAngle += 1 / (float)frameCount * eyeAngleDiff;

					eyeWidth -= 1 / (float)frameCount * eyeWidthDiff;

					eyeLineWidth += 1 / (float)frameCount * eyeLineWidthDiff;

					HandRotateAngle += 1 / (float)frameCount * handAngleDiff;

					MouthControlP1 = new PointF(MouthControlP1.X + (diffX1 / frameCount), MouthControlP1.Y + (diffY1 / frameCount));
					MouthControlP2 = new PointF(MouthControlP2.X + (diffX2 / frameCount), MouthControlP2.Y + (diffY2 / frameCount));

				}
				else
				{
					j = j - 1;
					if (j < 0)
					{
						eyeAddFlag = true;
					}
					EyeRotateAngle -= 1 / (float)frameCount * eyeAngleDiff;
					eyeWidth += 1 / (float)frameCount * eyeWidthDiff;
					eyeLineWidth -= 1 / (float)frameCount * eyeLineWidthDiff;

					HandRotateAngle -= 1 / (float)frameCount * handAngleDiff;

					MouthControlP1 = new PointF(MouthControlP1.X - (diffX1 / frameCount), MouthControlP1.Y - (diffY1 / frameCount));
					MouthControlP2 = new PointF(MouthControlP2.X - (diffX2 / frameCount), MouthControlP2.Y - (diffY2 / frameCount));
				}
				LightningAlpha = j / frameCount;
				if (j % 10 == 0)
				{
					showLighting = true;
				}
				else
				{
					showLighting = false;
				}
				PostInvalidate();
			};
			t2.Enabled = true;
			t2.Start();

			#endregion

			this.RotationX = 180;

		}



		protected override void OnDraw(Android.Graphics.Canvas canvas)
		{
			RectF dirtyRect = new RectF(0,0,256*Scale,256*Scale);

			canvas.DrawRoundRect(dirtyRect, 25, 25, new Paint(){AntiAlias=true,Color=new Color(255,255,255,128)});

			//圆形的四周边距
			float margin = 44 * Scale;

			//圆形的线宽
			float lineWidth = 8 * Scale;
			float circleR = 84 * Scale;
			canvas.DrawCircle(dirtyRect.Width()/2, dirtyRect.Height() / 2, circleR, new Paint() { AntiAlias=true,Color=color2});
			Paint p = new Paint();
			p.AntiAlias = true;
			p.StrokeWidth = lineWidth;
			p.Color = new Color(0,0,0);
			p.SetStyle(Paint.Style.Stroke);

			canvas.DrawCircle(dirtyRect.Width() / 2, dirtyRect.Height() / 2,  circleR,p);

			第一条曲线的路径
			Path path1 = new Path();
			path1.MoveTo(curve1StartPoint.X,curve1StartPoint.Y);

			PointF endp = new PointF(100, 114).MagnifyPoint(Scale);
			path1.CubicTo(cp1.X,cp1.Y, cp2.X,cp2.Y, endp.X,endp.Y);


			PointF endp2 = new PointF(140, 72).MagnifyPoint(Scale);
			path1.CubicTo(cp3.X,cp3.Y, cp4.X,cp4.Y, endp2.X,endp2.Y);



			path1.CubicTo(cp5.X,cp5.Y, cp6.X,cp6.Y, curve1EndPoint.X,curve1EndPoint.Y);

			path1.CubicTo(cp7.X,cp7.Y, cp8.X,cp8.Y, curve1StartPoint.X,curve1StartPoint.Y);

			p.Color = color1;
			p.SetStyle(Paint.Style.Fill);
			canvas.DrawPath(path1,p);
			//第二条曲线
			Path path2 = new Path();

			path2.MoveTo(curve2StartPoint.X,curve2StartPoint.Y);

			PointF rendp = new PointF(144, 154).MagnifyPoint(Scale);
			path2.CubicTo(rcp1.X,rcp1.Y, rcp2.X,rcp2.Y, rendp.X,rendp.Y);


			PointF rendp2 = new PointF(180, 110).MagnifyPoint(Scale);
			path2.CubicTo(rcp3.X,rcp3.Y, rcp4.X,rcp4.Y, rendp2.X,rendp2.Y);


			path2.CubicTo(rcp5.X,rcp5.Y, rcp6.X,rcp6.Y, curve2EndPoint.X,curve2EndPoint.Y);


			path2.CubicTo(rcp7.X,rcp7.Y, rcp8.X,rcp8.Y, curve2StartPoint.X,curve2StartPoint.Y);

			p.Color = color3;
			canvas.DrawPath(path2,p);

			//眼睛
			p.Color = new Color(0,0,0);
			PointF leftEyeCenterPoint = new PointF(119, 165).MagnifyPoint(Scale);
			PointF rightEyeCenterPoint = new PointF(147, 181).MagnifyPoint(Scale);

			float angle = 36;
			float eyeAngle = EyeRotateAngle;
			canvas.Translate(leftEyeCenterPoint.X, leftEyeCenterPoint.Y);//移动光标到指定位置
			canvas.Rotate(angle);

			float cornerWidth = eyeLineWidth * Scale;
			canvas.Rotate(eyeAngle);
			Path leftEyePath1 = new Path();
			leftEyePath1.AddRoundRect(new RectF(-cornerWidth, -cornerWidth, eyeLineWidth * Scale, eyeWidth * Scale), cornerWidth, cornerWidth,Path.Direction.Cw);

			p.Color = new Color(0,0,0);
			canvas.DrawPath(leftEyePath1,p);

			canvas.Rotate(-eyeAngle);

			canvas.Rotate(180- eyeAngle);
			Path leftEyePath2 = new Path();
			leftEyePath2.AddRoundRect(new RectF(-cornerWidth, -cornerWidth, eyeLineWidth * Scale, eyeWidth * Scale), cornerWidth, cornerWidth,Path.Direction.Cw);
			canvas.DrawPath(leftEyePath2,p);
			canvas.Rotate(eyeAngle - 180);

			canvas.Rotate(-angle);//转回去
			canvas.Translate(-leftEyeCenterPoint.X, -leftEyeCenterPoint.Y);

			canvas.Translate(rightEyeCenterPoint.X, rightEyeCenterPoint.Y);//移动光标到指定位置
			canvas.Rotate(angle);

			canvas.Rotate(eyeAngle + 180);
			Path rightEyePath1 = new Path();
			rightEyePath1.AddRoundRect(new RectF(-cornerWidth, -cornerWidth, eyeLineWidth * Scale,eyeWidth * Scale), cornerWidth, cornerWidth,Path.Direction.Cw);
			canvas.DrawPath(rightEyePath1,p);
			canvas.Rotate(-eyeAngle - 180);

			canvas.Rotate(-eyeAngle);
			Path rightEyePath2 = new Path();
			rightEyePath2.AddRoundRect(new RectF(-cornerWidth, -cornerWidth, eyeLineWidth * Scale, eyeWidth * Scale), cornerWidth, cornerWidth,Path.Direction.Cw);
			canvas.DrawPath(rightEyePath2,p);
			canvas.Rotate(eyeAngle);

			canvas.Rotate(-angle);//转回去
			canvas.Translate(-rightEyeCenterPoint.X, -rightEyeCenterPoint.Y);

			//嘴巴
			Path mousePaht = new Path();
			PointF mousePoint1 = new PointF(118, 134).MagnifyPoint(Scale);
			PointF mousePoint2 = new PointF(165, 165).MagnifyPoint(Scale);
			mousePaht.MoveTo(mousePoint1.X,mousePoint1.Y);
			mousePaht.CubicTo(MouthControlP1.X,MouthControlP1.Y, MouthControlP2.X,MouthControlP2.Y, mousePoint2.X,mousePoint2.Y);
			p.StrokeWidth = 5 * Scale;
			p.SetStyle(Paint.Style.Stroke);
			canvas.DrawPath(mousePaht,p);

			p.SetStyle(Paint.Style.Fill);
			canvas.DrawCircle(mousePoint1.X,mousePoint1.Y,2.5f*Scale,p);
			canvas.DrawCircle(mousePoint2.X, mousePoint2.Y, 2.5f * Scale, p);

			//手臂
			PointF leftArmP1 = new PointF(48, 106).MagnifyPoint(Scale);
			PointF leftArmP2 = new PointF(129, 95).MagnifyPoint(Scale);

			PointF rightArmP1 = new PointF(188, 189).MagnifyPoint(Scale);
			PointF rightArmP2 = new PointF(163, 115).MagnifyPoint(Scale);

			Path armPath = new Path();
			armPath.MoveTo(leftArmP1.X,leftArmP1.Y);
			armPath.CubicTo(LeftArmCP1.X,LeftArmCP1.Y, LeftArmCP2.X,LeftArmCP2.Y, leftArmP2.X,leftArmP2.Y);

			armPath.MoveTo(rightArmP1.X,rightArmP1.Y);
			armPath.CubicTo(RightArmCP1.X,RightArmCP1.Y, RightArmCP2.X,RightArmCP2.Y, rightArmP2.X,rightArmP2.Y);

			p.SetStyle(Paint.Style.Stroke);
			p.StrokeWidth = 8 * Scale;
			canvas.DrawPath(armPath,p);

			PointF leftHandP = leftArmP2;
			PointF rightHandP = rightArmP2;
			Path leftHandPath = new Path();
			RectF leftHandRect = new RectF(-4 * Scale, -4 * Scale, 8 * Scale, 28 * Scale);
			leftHandPath.AddRoundRect(leftHandRect, 5 * Scale, 5 * Scale,Path.Direction.Cw);
			float handAngle = HandRotateAngle;
			canvas.Translate(leftHandP.X, leftHandP.Y);//移动光标到指定位置
			canvas.Rotate(handAngle);
			p.SetStyle(Paint.Style.Fill);
			canvas.DrawRoundRect(leftHandRect, 8 * Scale, 8 * Scale, p);

			canvas.Rotate(-handAngle);//转回去
			canvas.Translate(-leftHandP.X, -leftHandP.Y);

			canvas.Translate(rightHandP.X, rightHandP.Y);//移动光标到指定位置
			canvas.Rotate(handAngle+180);
			canvas.DrawRoundRect(leftHandRect, 8 * Scale, 8 * Scale,p);
			canvas.Rotate(-handAngle-180);//转回去
			canvas.Translate(-rightHandP.X, -rightHandP.Y);

			if (showLighting)
			{
				PointF lightningCenterP = new PointF((leftArmP2.X + rightArmP2.X) / 2.0f, (leftArmP2.Y + rightArmP2.Y) / 2.0f);
				Path lightningPath = new Path();

				lightningPath.MoveTo(lightningP1.X,lightningP1.Y);
				lightningPath.LineTo(lightningP2.X,lightningP2.Y);
				lightningPath.LineTo(lightningP3.X,lightningP3.Y);
				lightningPath.LineTo(lightningP4.X,lightningP4.Y);
				lightningPath.LineTo(lightningP5.X,lightningP5.Y);
				lightningPath.LineTo(lightningP6.X,lightningP6.Y);
				lightningPath.LineTo(lightningP1.X,lightningP1.Y);
				lightningPath.Close();

				canvas.Translate(lightningCenterP.X, lightningCenterP.Y);//移动光标到指定位置
				p.Color = new Color(255, 221,0);
				p.SetStyle(Paint.Style.Fill);
				canvas.Rotate(handAngle);
				canvas.DrawPath(lightningPath,p);
				canvas.Rotate(-handAngle);//转回去
				canvas.Translate(-lightningCenterP.X, -lightningCenterP.Y);
			}
		}
	}
}


Android版本的完整DEMO可以从这里下载:

Android版本Demo


你可能感兴趣的:(Xamarin,Mac,开发,WPF)