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

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


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

// <copyright company="上海诸君信息科技有限公司">上海诸君信息科技有限公司版权所有</copyright>
// <author>海学权</author>
//
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实现的,具体代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<meta charset="utf-8">
    <title>svg网页版地球动画</title>
</head>
<body>

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="256" height="256"  xml:space="preserve" id="canvas1">
    <circle id="canvas1-oval" stroke="rgb(0, 0, 0)" stroke-width="8" fill="rgb(85, 198, 237)" cx="128" cy="128" r="88" >
    <animate attributeName="fill" values="rgb(85, 198, 237);rgb(0, 159, 239);rgb(85, 198, 237)" dur="1.5s" repeatCount="indefinite" />
    </circle>
    <path id="canvas1-bezier1" stroke-width="0" stroke="rgb(0, 159, 239)" fill="rgb(0, 159, 239)" d="M 53.5 89 C 97 94 112 113 100 142 C 87 175 116 200 140 184 C 147 182 156 179 178 195.5 A84 84 0 0 1 53.5 89">
    <animate attributeName="fill" values="rgb(0, 159, 239);rgb(153, 223, 246);rgb(85, 198, 237)" dur="1.5s" repeatCount="indefinite" />
    </path>
    <path id="canvas1-bezier2" stroke-width="0" stroke="rgb(0, 159, 239)" fill="rgb(153, 223, 246)" d="M 116 44.5 C 122 59 165 63 144 102 C 134 123 153 151 180 146 C 194 139 195 136 210 144.5 A84 84 0 0 0 116 44.5">
    <animate attributeName="fill" values="rgb(153, 223, 246);rgb(85, 198, 237);rgb(0, 159, 239)" dur="1.5s" repeatCount="indefinite" />
    </path>
    <path id="canvas1-leftArm" stroke-width="8" stroke="rgb(0, 0, 0)" fill="none" d="M 45 150 C -6 197 70 187 129 161" />
    <path id="canvas1-rightArm" stroke-width="8" stroke="rgb(0, 0, 0)" fill="none" d="M 189 67 C 253 48 222 100 163 141" />
    <path id="canvas1-mouse" stroke-width="5" stroke="rgb(0, 0, 0)" fill="none" d="M 118 122 C 120 93.5 151 92.5 165 91" >
    <animate attributeName="d" values="M 118 122 C 120 93.5 151 92.5 165 91;M 118 122 C 149.5 115.5 174.5 111 165 91;M 118 122 C 120 93.5 151 92.5 165 91" dur="3s" repeatCount="indefinite" />
    </path>
    <circle id="canvas1-leftMouthPoint" stroke="none" fill="rgb(0, 0, 0)" cx="118" cy="122" r="2.5" />
    <circle id="canvas1-rightMouthPoint" stroke="none" fill="rgb(0, 0, 0)" cx="165" cy="91" r="2.5" />
    
    <rect id="leftHand" x="122" y="154" width="30" height="12" rx="6" ry="6" stroke="none" fill="rgb(0, 0, 0)" transform="rotate(-120 128 159)">
    <animateTransform attributeName="transform" begin="0s" dur="3s" type="rotate" values="-120 128 159;-60 128 159;-120 128 159" repeatCount="indefinite"/>
    </rect>
    
    <rect id="rightHand" x="159" y="135" width="30" height="12" rx="6" ry="6" stroke="none" fill="rgb(0, 0, 0)" transform="rotate(60 163 141)">
    <animateTransform attributeName="transform" begin="0s" dur="3s" type="rotate" values="60 163 141;120 163 141;60 163 141" repeatCount="indefinite"/>
    </rect>
    
    <rect id="leftEye1" x="119" y="93.5" width="26" height="5" rx="2.5" ry="2.5" stroke="none" fill="rgb(0, 0, 0)" transform="rotate(165 121.5 96)">
    <animateTransform attributeName="transform" begin="0s" dur="3s" type="rotate" values="165 121.5 96;225 124 96;165 121.5 96" repeatCount="indefinite"/>
    <animate attributeName="y" values="93.5;91;93.5" dur="3s" repeatCount="indefinite" />
    <animate attributeName="width" values="26;16;26" dur="3s" repeatCount="indefinite" />
    <animate attributeName="height" values="5;10;5" dur="3s" repeatCount="indefinite" />
    <animate attributeName="rx" values="2.5;5;2.5" dur="3s" repeatCount="indefinite" />
    <animate attributeName="ry" values="2.5;5;2.5" dur="3s" repeatCount="indefinite" />
    </rect>
    
    <rect id="leftEye2" x="119" y="93.5" width="26" height="5" rx="2.5" ry="2.5" stroke="none" fill="rgb(0, 0, 0)" transform="rotate(135 121.5 96)">
    <animateTransform attributeName="transform" begin="0s" dur="3s" type="rotate" values="135 121.5 96;45 124 96;135 121.5 96" repeatCount="indefinite"/>
    <animate attributeName="y" values="93.5;91;93.5" dur="3s" repeatCount="indefinite" />
    <animate attributeName="width" values="26;16;26" dur="3s" repeatCount="indefinite" />
    <animate attributeName="height" values="5;10;5" dur="3s" repeatCount="indefinite" />
    <animate attributeName="rx" values="2.5;5;2.5" dur="3s" repeatCount="indefinite" />
    <animate attributeName="ry" values="2.5;5;2.5" dur="3s" repeatCount="indefinite" />
    </rect>
    
    <rect id="rightEye1" x="147" y="77.5" width="26" height="5" rx="2.5" ry="2.5" stroke="none" fill="rgb(0, 0, 0)" transform="rotate(-15 149.5 80)">
    <animateTransform attributeName="transform" begin="0s" dur="3s" type="rotate" values="-15 149.5 80;45 152 80;-15 149.5 80" repeatCount="indefinite"/>
    <animate attributeName="y" values="77.5;75;77.5" dur="3s" repeatCount="indefinite" />
    <animate attributeName="width" values="26;16;26" dur="3s" repeatCount="indefinite" />
    <animate attributeName="height" values="5;10;5" dur="3s" repeatCount="indefinite" />
    <animate attributeName="rx" values="2.5;5;2.5" dur="3s" repeatCount="indefinite" />
    <animate attributeName="ry" values="2.5;5;2.5" dur="3s" repeatCount="indefinite" />
    </rect>
    
    <rect id="rightEye2" x="147" y="77.5" width="26" height="5" rx="2.5" ry="2.5" stroke="none" fill="rgb(0, 0, 0)" transform="rotate(-45 149.5 80)">
    <animateTransform attributeName="transform" begin="0s" dur="3s" type="rotate" values="-45 149.5 80;-135 152 80;-45 149.5 80" repeatCount="indefinite"/>
    <animate attributeName="y" values="77.5;75;77.5" dur="3s" repeatCount="indefinite" />
    <animate attributeName="width" values="26;16;26" dur="3s" repeatCount="indefinite" />
    <animate attributeName="height" values="5;10;5" dur="3s" repeatCount="indefinite" />
    <animate attributeName="rx" values="2.5;5;2.5" dur="3s" repeatCount="indefinite" />
    <animate attributeName="ry" values="2.5;5;2.5" dur="3s" repeatCount="indefinite" />
    </rect>
    <path id="canvas1-ligtning" stroke="none" fill="rgb(255,206,31)" d="M -11 -4 L -1 -1 -1 -5 11 4 1 1 1 5 -11 -4">
        <animate attributeName="d" values="M -11 -4 L -1 -1 -1 -5 11 4 1 1 1 5 -11 -4;M -5.5 -2 L -0.5 -0.5 -0.5 -2.5 5.5 2 0.5 0.5 0.5 2.5 -5.5 -2;M -11 -4 L -1 -1 -1 -5 11 4 1 1 1 5 -11 -4" dur="3s" repeatCount="indefinite"/>
        <animateTransform attributeName="transform" type="translate" values="146 151;146 151" dur="3s" repeatCount="indefinite" additive="sum"/>
        <animateTransform attributeName="transform" begin="0s" dur="3s" type="rotate" values="-45 0 0;5 0 0;-45 0 0" repeatCount="indefinite" additive="sum"/>
    </path>
</svg>
</body>
</html>

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

svg动画相关

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

<UserControl
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:earthAnimate"
             xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing" x:Class="earthAnimate.LoadAnimate"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" Width="250" Height="250">
    <UserControl.Resources>
        <Storyboard x:Key="LoadingAnimate" RepeatBehavior="Forever">
            <PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(BezierSegment.Point2)" Storyboard.TargetName="path">
                <EasingPointKeyFrame KeyTime="0" Value="26.0063068619414,1.29245203797722"/>
                <EasingPointKeyFrame KeyTime="0:0:1" Value="52.0063333333333,29.293"/>
                <EasingPointKeyFrame KeyTime="0:0:2" Value="26.0063068619414,1.29245203797722"/>
            </PointAnimationUsingKeyFrames>
            <PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(BezierSegment.Point3)" Storyboard.TargetName="path">
                <EasingPointKeyFrame KeyTime="0" Value="53.0779179714247,12.6239846356512"/>
                <EasingPointKeyFrame KeyTime="0:0:1" Value="47.1432691945085,10.4907378598698"/>
                <EasingPointKeyFrame KeyTime="0:0:2" Value="53.0779179714247,12.6239846356512"/>
            </PointAnimationUsingKeyFrames>
            <PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.StartPoint)" Storyboard.TargetName="path">
                <EasingPointKeyFrame KeyTime="0" Value="8.00601015857884,26.6251668973387"/>
                <EasingPointKeyFrame KeyTime="0:0:1" Value="10.673,23.9596666666667"/>
                <EasingPointKeyFrame KeyTime="0:0:2" Value="8.00601015857884,26.6251668973387"/>
            </PointAnimationUsingKeyFrames>
            <PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(BezierSegment.Point1)" Storyboard.TargetName="path">
                <EasingPointKeyFrame KeyTime="0" Value="8.00601015857884,26.6251668973387"/>
                <EasingPointKeyFrame KeyTime="0:0:1" Value="10.673,23.9596666666667"/>
                <EasingPointKeyFrame KeyTime="0:0:2" Value="8.00601015857884,26.6251668973387"/>
            </PointAnimationUsingKeyFrames>
            <PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.StartPoint)" Storyboard.TargetName="path1">
                <EasingPointKeyFrame KeyTime="0" Value="2.99999998384646,14.8115542651442"/>
                <EasingPointKeyFrame KeyTime="0:0:1" Value="21.4113333333333,9.667"/>
                <EasingPointKeyFrame KeyTime="0:0:2" Value="2.99999998384646,14.8115542651442"/>
            </PointAnimationUsingKeyFrames>
            <PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[1].(LineSegment.Point)" Storyboard.TargetName="path1">
                <EasingPointKeyFrame KeyTime="0" Value="13.0927202192036,33.6863477007917"/>
                <EasingPointKeyFrame KeyTime="0:0:1" Value="26.828,22.667"/>
                <EasingPointKeyFrame KeyTime="0:0:2" Value="13.0927202192036,33.6863477007917"/>
            </PointAnimationUsingKeyFrames>
            <PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[1].(LineSegment.Point)" Storyboard.TargetName="path2">
                <EasingPointKeyFrame KeyTime="0" Value="11.0927202192036,31.3470675723126"/>
                <EasingPointKeyFrame KeyTime="0:0:1" Value="27.337,21.292"/>
                <EasingPointKeyFrame KeyTime="0:0:2" Value="11.0927202192036,31.3470675723126"/>
            </PointAnimationUsingKeyFrames>
            <PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.StartPoint)" Storyboard.TargetName="path2">
                <EasingPointKeyFrame KeyTime="0" Value="2.99999998384645,13.4722741366651"/>
                <EasingPointKeyFrame KeyTime="0:0:1" Value="22.0870000000001,8.29200000000014"/>
                <EasingPointKeyFrame KeyTime="0:0:2" Value="2.99999998384645,13.4722741366651"/>
            </PointAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="path3">
                <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:2" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="path3">
                <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:2" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
            <PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.StartPoint)" Storyboard.TargetName="path5">
                <EasingPointKeyFrame KeyTime="0" Value="15.6546741275458,20.9010035613603"/>
                <EasingPointKeyFrame KeyTime="0:0:1" Value="15.6546741275458,20.9010035613603"/>
                <EasingPointKeyFrame KeyTime="0:0:2" Value="15.6546741275458,20.9010035613603"/>
            </PointAnimationUsingKeyFrames>
            <PointAnimationUsingKeyFrames Storyboard.TargetProperty="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(LineSegment.Point)" Storyboard.TargetName="path4">
                <EasingPointKeyFrame KeyTime="0" Value="2.49999572951243,2.50000361637382"/>
                <EasingPointKeyFrame KeyTime="0:0:1" Value="2.49999572951243,2.50000361637382"/>
                <EasingPointKeyFrame KeyTime="0:0:2" Value="2.49999572951243,2.50000361637382"/>
            </PointAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="b1">
                <EasingColorKeyFrame KeyTime="0" Value="#FF00B0F5"/>
                <EasingColorKeyFrame KeyTime="0:0:0.333" Value="#FF8BE6F7"/>
                <EasingColorKeyFrame KeyTime="0:0:0.7" Value="#FF00D4F1"/>
                <EasingColorKeyFrame KeyTime="0:0:1" Value="#FF00B0F5"/>
                <EasingColorKeyFrame KeyTime="0:0:1.333" Value="#FF8BE6F7"/>
                <EasingColorKeyFrame KeyTime="0:0:1.7" Value="#FF00D4F1"/>
                <EasingColorKeyFrame KeyTime="0:0:2" Value="#FF00B0F5"/>
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="b2">
                <EasingColorKeyFrame KeyTime="0" Value="#FF00D4F1"/>
                <EasingColorKeyFrame KeyTime="0:0:0.333" Value="#FF00B0F5"/>
                <EasingColorKeyFrame KeyTime="0:0:0.7" Value="#FF8BE6F7"/>
                <EasingColorKeyFrame KeyTime="0:0:1" Value="#FF00D4F1"/>
                <EasingColorKeyFrame KeyTime="0:0:1.333" Value="#FF00B0F5"/>
                <EasingColorKeyFrame KeyTime="0:0:1.7" Value="#FF8BE6F7"/>
                <EasingColorKeyFrame KeyTime="0:0:2" Value="#FF00D4F1"/>
            </ColorAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames x:Name="colorAnimationUsingKeyFrames" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="b3">
                <EasingColorKeyFrame KeyTime="0" Value="#FF8BE6F7"/>
                <EasingColorKeyFrame KeyTime="0:0:0.333" Value="#FF00D4F1"/>
                <EasingColorKeyFrame KeyTime="0:0:0.7" Value="#FF00B0F5"/>
                <EasingColorKeyFrame KeyTime="0:0:1" Value="#FF8BE6F7"/>
                <EasingColorKeyFrame KeyTime="0:0:1.333" Value="#FF00D4F1"/>
                <EasingColorKeyFrame KeyTime="0:0:1.7" Value="#FF00B0F5"/>
                <EasingColorKeyFrame KeyTime="0:0:2" Value="#FF8BE6F7"/>
            </ColorAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="path4">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="30"/>
                <EasingDoubleKeyFrame KeyTime="0:0:2" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
            <PointAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)" Storyboard.TargetName="path4">
                <EasingPointKeyFrame KeyTime="0" Value="0.5,0.5"/>
                <EasingPointKeyFrame KeyTime="0:0:1" Value="0.5,1"/>
                <EasingPointKeyFrame KeyTime="0:0:2" Value="0.5,0.5"/>
            </PointAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="path5">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="30"/>
                <EasingDoubleKeyFrame KeyTime="0:0:2" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.StrokeThickness)" Storyboard.TargetName="path1">
                <EasingDoubleKeyFrame KeyTime="0" Value="6"/>
                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="8"/>
                <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.StrokeThickness)" Storyboard.TargetName="path2">
                <EasingDoubleKeyFrame KeyTime="0" Value="6"/>
                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="8"/>
                <EasingDoubleKeyFrame KeyTime="0:0:2" Value="6"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </UserControl.Resources>
    <UserControl.Triggers>
        <EventTrigger RoutedEvent="FrameworkElement.Loaded">
            <BeginStoryboard Storyboard="{StaticResource LoadingAnimate}"/>
        </EventTrigger>
    </UserControl.Triggers>
    <Border Background="#FF777778" BorderThickness="0" CornerRadius="20">
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
            <Path x:Name="b2" Data="M49.25882,2.5 L49.891563,2.7516928 C99.700253,22.805404 93.89454,22.542268 106.69724,38.543294 119.37159,54.383912 131.67212,47.689239 136.78944,95.631171 L136.85231,96.256896 136.25598,97.943831 C128.63833,118.21517 112.2016,134.17039 91.62009,141.13518 L90.697735,141.43463 90.425785,140.36446 C84.315968,118.13202 56.595196,123.86007 46.366886,106.9448 33.468063,85.61312 78.159336,46.724566 4.1379318,42.211658 L2.5,42.118983 3.0165176,41.012725 C11.798109,22.78795 27.978783,8.7994452 47.661499,2.944242 z" HorizontalAlignment="Center" Height="137.267" Margin="59.633,57.056,57.515,55.677" Stretch="Fill" Stroke="Black" StrokeThickness="0" VerticalAlignment="Center" Width="132.852" Fill="#FF00D4F1"/>
            <Path x:Name="b3" Data="M21.6163,2.5 C61.656945,2.5 94.1163,34.959354 94.1163,75.000004 94.1163,83.133259 92.777036,90.953709 90.307004,98.252857 L90.100873,98.838108 77.418249,122.8896 C84.580697,82.416445 55.453409,93.956983 50.678444,73.639133 44.269802,46.369864 73.598277,17.561866 -7.0986351,10.735069 L2.5,5.0523987 3.4974225,4.7824936 C9.2886889,3.2924652 15.359949,2.5 21.6163,2.5 z" Margin="90,52.556,54.015,74" Stretch="Fill" Stroke="Black" StrokeThickness="0" Fill="#FF8BE6F7" Height="123.444" VerticalAlignment="Center" HorizontalAlignment="Center" Width="105.985"/>
            <Path x:Name="b1" Data="M9.1327693,2.5 L10.770701,2.5926743 C84.792105,7.1055832 40.100833,45.994137 52.999655,67.325817 63.227965,84.241085 90.948737,78.513035 97.058554,100.74547 L97.330504,101.81565 96.559279,102.06603 C89.748709,104.18435 82.507621,105.32549 74.999999,105.32549 34.959353,105.32549 2.4999988,72.866131 2.5,32.825489 2.4999988,22.189693 4.7902219,12.088806 8.9044149,2.9890862 z" HorizontalAlignment="Center" Height="104.825" Margin="53,92.175,100.169,53" Stretch="Fill" Stroke="Black" StrokeThickness="0" VerticalAlignment="Center" Width="96.831" Fill="#FF00B0F5"/>
            <Ellipse Margin="0" Stroke="Black" Width="150" Height="150" HorizontalAlignment="Center" VerticalAlignment="Center" StrokeThickness="5" d:IsLocked="True"/>
            <Path Data="M58.525936,156.73119 C7.8860635,210.3776 92.219771,185.79201 128.35962,164.64614" Height="37.34" Margin="40.891,154.585,118.5,58.075" Stretch="Fill" Stroke="Black" StrokeThickness="5" VerticalAlignment="Center" StrokeDashCap="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round" HorizontalAlignment="Center" Width="90.609" d:IsLocked="True"/>
            <Path Data="M198.32214,99.08387 C255.98402,87.950505 213.3333,138.58305 171.49993,161.83333" HorizontalAlignment="Center" Margin="157.5,82.507,32.66,98.167" Stretch="Fill" Stroke="Black" StrokeThickness="5" Width="59.84" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Height="69.326" VerticalAlignment="Center" d:IsLocked="True"/>
            <Path x:Name="path4" Margin="125.063,144.021,117.937,82.578" Stroke="Black" StrokeThickness="7" VerticalAlignment="Center" StrokeEndLineCap="Round" StrokeDashCap="Round" StrokeStartLineCap="Round" HorizontalAlignment="Center" Stretch="Fill" RenderTransformOrigin="0.5,1" d:IsLocked="True">
                <Path.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform/>
                        <TranslateTransform/>
                    </TransformGroup>
                </Path.RenderTransform>
                <Path.Data>
                    <PathGeometry>
                        <PathFigure StartPoint="3.96799520310798,20.9010028484696">
                            <LineSegment Point="2.49999572951243,2.50000361637382"/>
                        </PathFigure>
                    </PathGeometry>
                </Path.Data>
            </Path>
            <Path x:Name="path5" Margin="157.5,146.877,85.5,79.722" Stroke="Black" StrokeThickness="7" VerticalAlignment="Center" StrokeEndLineCap="Round" StrokeDashCap="Round" StrokeStartLineCap="Round" HorizontalAlignment="Center" Stretch="Fill" RenderTransformOrigin="0.5,0" d:IsLocked="True">
                <Path.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform/>
                        <TranslateTransform/>
                    </TransformGroup>
                </Path.RenderTransform>
                <Path.Data>
                    <PathGeometry>
                        <PathFigure StartPoint="15.6546741275458,20.9010035613603">
                            <LineSegment Point="14.1866746539502,2.50000432926441"/>
                        </PathFigure>
                    </PathGeometry>
                </Path.Data>
            </Path>
            <Path x:Name="path1" Margin="96.422,84.333,111.667,128.981" Stroke="Black" StrokeThickness="6" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeDashCap="Round" StrokeLineJoin="Round" Height="36.686" VerticalAlignment="Center" HorizontalAlignment="Center" Width="41.911" d:IsLocked="True">
                <Path.Data>
                    <PathGeometry>
                        <PathFigure StartPoint="2.99999998384646,14.8115542651442">
                            <LineSegment Point="23.9451613192717,16.0578231031614"/>
                            <LineSegment Point="13.0927202192036,33.6863477007917"/>
                        </PathFigure>
                    </PathGeometry>
                </Path.Data>
            </Path>
            <Path x:Name="path2" HorizontalAlignment="Center" Margin="150.275,83.167,68.369,132.486" Stroke="Black" StrokeThickness="6" Width="31.356" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeDashCap="Round" StrokeLineJoin="Round" Height="34.347" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5" d:IsLocked="True">
                <Path.Data>
                    <PathGeometry>
                        <PathFigure StartPoint="2.99999998384645,13.4722741366651">
                            <LineSegment Point="24.9451613192717,15.2185429746824"/>
                            <LineSegment Point="11.0927202192036,31.3470675723126"/>
                        </PathFigure>
                    </PathGeometry>
                </Path.Data>
                <Path.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform Angle="180"/>
                        <TranslateTransform X="-5.6689999999999969" Y="-12.346999999999994"/>
                    </TransformGroup>
                </Path.RenderTransform>
            </Path>
            <Path x:Name="path" Margin="115.327,102.707,75.267,111.582" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Stroke="Black" StrokeThickness="4" StrokeLineJoin="Round" Height="35.711" VerticalAlignment="Center" HorizontalAlignment="Center" Width="59.406" d:IsLocked="True">
                <Path.Data>
                    <PathGeometry>
                        <PathFigure StartPoint="8.00601015857884,26.6251668973387">
                            <BezierSegment Point3="53.0779179714247,12.6239846356512" Point2="26.0063068619414,1.29245203797722" Point1="8.00601015857884,26.6251668973387"/>
                        </PathFigure>
                    </PathGeometry>
                </Path.Data>
            </Path>
            <Path x:Name="path3" Data="M144.625,147.623 L141,159.873 145.125,159 146.25,166.748 150,153.998 145.625,155.123 z" Fill="#FFE2E68A" HorizontalAlignment="Center" Height="20.125" Margin="139.5,148.875,100.5,81" Stretch="Fill" Stroke="Black" VerticalAlignment="Center" Width="10" StrokeThickness="0" RenderTransformOrigin="0.5,0.5" d:IsLocked="True">
                <Path.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform Angle="90"/>
                        <TranslateTransform/>
                    </TransformGroup>
                </Path.RenderTransform>
            </Path>
        </Grid>
    </Border>
</UserControl>

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


WPF版本转场动画


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

// <copyright company="上海诸君信息科技有限公司">上海诸君信息科技有限公司版权所有</copyright>
// <author>海学权</author>
//
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


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值