Skip to content

Commit 5360909

Browse files
committed
路径变换动画demo和波浪动画demo
1 parent c3108d6 commit 5360909

14 files changed

+474
-7
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
android:roundIcon="@mipmap/ic_launcher_round"
1010
android:supportsRtl="true"
1111
android:theme="@style/AppTheme">
12-
<activity android:name=".ThirdBezierActivity"></activity>
12+
<activity android:name=".WaveActivity"></activity>
13+
<activity android:name=".PathMorphingActivity" />
14+
<activity android:name=".DrawPadActivity" />
15+
<activity android:name=".ThirdBezierActivity" />
1316
<activity android:name=".SecondBezierActivity" />
1417
<activity android:name=".VectorDemoActivity" />
1518
<activity android:name=".MainActivity">
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.hyd.animationart;
2+
3+
import androidx.appcompat.app.AppCompatActivity;
4+
5+
import android.os.Bundle;
6+
7+
public class DrawPadActivity extends AppCompatActivity {
8+
9+
@Override
10+
protected void onCreate(Bundle savedInstanceState) {
11+
super.onCreate(savedInstanceState);
12+
setContentView(R.layout.activity_draw_pad);
13+
}
14+
}

app/src/main/java/com/hyd/animationart/MainActivity.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,32 @@ protected void onCreate(Bundle savedInstanceState) {
1616
findViewById(R.id.vector_demo).setOnClickListener(this);
1717
findViewById(R.id.second_bezier).setOnClickListener(this);
1818
findViewById(R.id.third_bezier).setOnClickListener(this);
19+
findViewById(R.id.draw_pad).setOnClickListener(this);
20+
findViewById(R.id.path_morphing).setOnClickListener(this);
21+
findViewById(R.id.bezier_wave).setOnClickListener(this);
1922
}
2023

2124
@Override
2225
public void onClick(View v) {
23-
if (v.getId() == R.id.vector_demo) {
24-
startActivity(new Intent(this, VectorDemoActivity.class));
25-
} else if (v.getId() == R.id.second_bezier) {
26-
startActivity(new Intent(this, SecondBezierActivity.class));
27-
} else if (v.getId() == R.id.third_bezier) {
28-
startActivity(new Intent(this, ThirdBezierActivity.class));
26+
switch (v.getId()) {
27+
case R.id.vector_demo:
28+
startActivity(new Intent(this, VectorDemoActivity.class));
29+
break;
30+
case R.id.second_bezier:
31+
startActivity(new Intent(this, SecondBezierActivity.class));
32+
break;
33+
case R.id.third_bezier:
34+
startActivity(new Intent(this, ThirdBezierActivity.class));
35+
break;
36+
case R.id.draw_pad:
37+
startActivity(new Intent(this, DrawPadActivity.class));
38+
break;
39+
case R.id.path_morphing:
40+
startActivity(new Intent(this, PathMorphingActivity.class));
41+
break;
42+
case R.id.bezier_wave:
43+
startActivity(new Intent(this, WaveActivity.class));
44+
break;
2945
}
3046
}
3147
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.hyd.animationart;
2+
3+
import androidx.appcompat.app.AppCompatActivity;
4+
5+
import android.os.Bundle;
6+
7+
public class PathMorphingActivity extends AppCompatActivity {
8+
9+
@Override
10+
protected void onCreate(Bundle savedInstanceState) {
11+
super.onCreate(savedInstanceState);
12+
setContentView(R.layout.activity_path_morphing);
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.hyd.animationart;
2+
3+
import androidx.appcompat.app.AppCompatActivity;
4+
5+
import android.os.Bundle;
6+
7+
public class WaveActivity extends AppCompatActivity {
8+
9+
@Override
10+
protected void onCreate(Bundle savedInstanceState) {
11+
super.onCreate(savedInstanceState);
12+
setContentView(R.layout.activity_wave);
13+
}
14+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.hyd.animationart.utils;
2+
3+
import android.graphics.PointF;
4+
5+
public class BezierUtil {
6+
7+
/**
8+
* B(t) = (1 - t)^2 * P0 + 2t * (1 - t) * P1 + t^2 * P2, t ∈ [0,1]
9+
*
10+
* @param t 曲线长度比例
11+
* @param p0 起始点
12+
* @param p1 控制点
13+
* @param p2 终止点
14+
* @return t对应的点
15+
*/
16+
public static PointF CalculateBezierPointForQuadratic(float t, PointF p0, PointF p1, PointF p2) {
17+
PointF point = new PointF();
18+
float temp = 1 - t;
19+
point.x = temp * temp * p0.x + 2 * t * temp * p1.x + t * t * p2.x;
20+
point.y = temp * temp * p0.y + 2 * t * temp * p1.y + t * t * p2.y;
21+
return point;
22+
}
23+
24+
/**
25+
* B(t) = P0 * (1-t)^3 + 3 * P1 * t * (1-t)^2 + 3 * P2 * t^2 * (1-t) + P3 * t^3, t ∈ [0,1]
26+
*
27+
* @param t 曲线长度比例
28+
* @param p0 起始点
29+
* @param p1 控制点1
30+
* @param p2 控制点2
31+
* @param p3 终止点
32+
* @return t对应的点
33+
*/
34+
public static PointF CalculateBezierPointForCubic(float t, PointF p0, PointF p1, PointF p2, PointF p3) {
35+
PointF point = new PointF();
36+
float temp = 1 - t;
37+
point.x = p0.x * temp * temp * temp + 3 * p1.x * t * temp * temp + 3 * p2.x * t * t * temp + p3.x * t * t * t;
38+
point.y = p0.y * temp * temp * temp + 3 * p1.y * t * temp * temp + 3 * p2.y * t * t * temp + p3.y * t * t * t;
39+
return point;
40+
}
41+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package com.hyd.animationart.views;
2+
3+
import android.content.Context;
4+
import android.graphics.Canvas;
5+
import android.graphics.Paint;
6+
import android.graphics.Path;
7+
import android.util.AttributeSet;
8+
import android.view.MotionEvent;
9+
import android.view.View;
10+
11+
import androidx.annotation.Nullable;
12+
13+
/**
14+
* Created by hydCoder on 2019/12/26.
15+
* 以梦为马,明日天涯。
16+
*/
17+
public class DrawPadView extends View {
18+
19+
private Path mPath;
20+
private Paint mPaint;
21+
22+
private float mX;
23+
private float mY;
24+
25+
public DrawPadView(Context context) {
26+
super(context);
27+
init();
28+
}
29+
30+
public DrawPadView(Context context, @Nullable AttributeSet attrs) {
31+
super(context, attrs);
32+
init();
33+
}
34+
35+
public DrawPadView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
36+
super(context, attrs, defStyleAttr);
37+
init();
38+
}
39+
40+
private void init() {
41+
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
42+
mPaint.setStyle(Paint.Style.STROKE);
43+
mPaint.setStrokeWidth(5);
44+
45+
mPath = new Path();
46+
}
47+
48+
@Override
49+
public boolean onTouchEvent(MotionEvent event) {
50+
switch (event.getAction()) {
51+
case MotionEvent.ACTION_DOWN:
52+
mPath.reset();
53+
mX = event.getX();
54+
mY = event.getY();
55+
mPath.moveTo(mX, mY);
56+
break;
57+
case MotionEvent.ACTION_MOVE:
58+
float x1 = event.getX();
59+
float y1 = event.getY();
60+
float midX = (x1 + mX) / 2;
61+
float midY = (y1 + mY) / 2;
62+
// 过于生硬
63+
// mPath.lineTo(x1, y1);
64+
mPath.quadTo(mX, mY, midX, midY);
65+
mX = x1;
66+
mY = y1;
67+
break;
68+
}
69+
invalidate();
70+
return true;
71+
}
72+
73+
@Override
74+
protected void onDraw(Canvas canvas) {
75+
super.onDraw(canvas);
76+
canvas.drawPath(mPath, mPaint);
77+
}
78+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package com.hyd.animationart.views;
2+
3+
import android.animation.ValueAnimator;
4+
import android.content.Context;
5+
import android.graphics.Canvas;
6+
import android.graphics.Paint;
7+
import android.graphics.Path;
8+
import android.util.AttributeSet;
9+
import android.view.MotionEvent;
10+
import android.view.View;
11+
import android.view.animation.BounceInterpolator;
12+
13+
import androidx.annotation.Nullable;
14+
15+
/**
16+
* Created by hydCoder on 2019/12/26.
17+
* 以梦为马,明日天涯。
18+
*/
19+
public class PathMorphingView extends View implements View.OnClickListener {
20+
21+
private float mStartPointX;
22+
private float mStartPointY;
23+
24+
private float mEndPointX;
25+
private float mEndPointY;
26+
27+
private float mFlagPointOneX;
28+
private float mFlagPointOneY;
29+
30+
private float mFlagPointTwoX;
31+
private float mFlagPointTwoY;
32+
33+
private Path mPath;
34+
private Paint mPaintBezier;
35+
private Paint mPaintFlag;
36+
private Paint mPaintText;
37+
38+
private ValueAnimator mValueAnimator;
39+
40+
public PathMorphingView(Context context) {
41+
super(context);
42+
init();
43+
}
44+
45+
public PathMorphingView(Context context, @Nullable AttributeSet attrs) {
46+
super(context, attrs);
47+
48+
49+
init();
50+
}
51+
52+
public PathMorphingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
53+
super(context, attrs, defStyleAttr);
54+
init();
55+
}
56+
57+
private void init() {
58+
mPaintBezier = new Paint(Paint.ANTI_ALIAS_FLAG);
59+
mPaintBezier.setStrokeWidth(8);
60+
mPaintBezier.setStyle(Paint.Style.STROKE);
61+
62+
mPaintFlag = new Paint(Paint.ANTI_ALIAS_FLAG);
63+
mPaintFlag.setStrokeWidth(5);
64+
mPaintFlag.setStyle(Paint.Style.STROKE);
65+
66+
mPaintText = new Paint(Paint.ANTI_ALIAS_FLAG);
67+
mPaintText.setStyle(Paint.Style.STROKE);
68+
mPaintText.setTextSize(26);
69+
}
70+
71+
@Override
72+
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
73+
super.onSizeChanged(w, h, oldw, oldh);
74+
75+
mStartPointX = w / 4;
76+
mStartPointY = h / 2 - 200;
77+
78+
mEndPointX = w * 3 / 4;
79+
mEndPointY = h / 2 - 200;
80+
81+
mFlagPointOneX = mStartPointX;
82+
mFlagPointOneY = mStartPointY;
83+
mFlagPointTwoX = mEndPointX;
84+
mFlagPointTwoY = mEndPointY;
85+
86+
mPath = new Path();
87+
88+
mValueAnimator = ValueAnimator.ofFloat(mStartPointY, h);
89+
mValueAnimator.setInterpolator(new BounceInterpolator());
90+
mValueAnimator.setDuration(1500);
91+
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
92+
@Override
93+
public void onAnimationUpdate(ValueAnimator animation) {
94+
mFlagPointOneY = (float) animation.getAnimatedValue();
95+
mFlagPointTwoY = (float) animation.getAnimatedValue();
96+
invalidate();
97+
}
98+
});
99+
setOnClickListener(this);
100+
}
101+
102+
@Override
103+
protected void onDraw(Canvas canvas) {
104+
super.onDraw(canvas);
105+
mPath.reset();
106+
mPath.moveTo(mStartPointX, mStartPointY);
107+
mPath.cubicTo(mFlagPointOneX, mFlagPointOneY, mFlagPointTwoX, mFlagPointTwoY, mEndPointX, mEndPointY);
108+
109+
canvas.drawPoint(mStartPointX, mStartPointY, mPaintFlag);
110+
canvas.drawText("起点", mStartPointX, mStartPointY, mPaintText);
111+
canvas.drawPoint(mEndPointX, mEndPointY, mPaintFlag);
112+
canvas.drawText("终点", mEndPointX, mEndPointY, mPaintText);
113+
canvas.drawPoint(mFlagPointOneX, mFlagPointOneY, mPaintFlag);
114+
canvas.drawText("控制点1", mFlagPointOneX, mFlagPointOneY, mPaintText);
115+
canvas.drawText("控制点2", mFlagPointTwoX, mFlagPointTwoY, mPaintText);
116+
canvas.drawLine(mStartPointX, mStartPointY, mFlagPointOneX, mFlagPointOneY, mPaintFlag);
117+
canvas.drawLine(mFlagPointOneX, mFlagPointOneY, mFlagPointTwoX, mFlagPointTwoY, mPaintFlag);
118+
canvas.drawLine(mEndPointX, mEndPointY, mFlagPointTwoX, mFlagPointTwoY, mPaintFlag);
119+
120+
canvas.drawPath(mPath, mPaintBezier);
121+
}
122+
123+
@Override
124+
public void onClick(View v) {
125+
mValueAnimator.start();
126+
}
127+
}

0 commit comments

Comments
 (0)