Skip to content

Commit 27a71df

Browse files
committed
pathMeasure部分demo
1 parent 5360909 commit 27a71df

24 files changed

+699
-41
lines changed

README.md

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,13 +200,84 @@
200200

201201
**Bézier curve(**[贝塞尔曲线](https://baike.baidu.com/item/%E8%B4%9D%E5%A1%9E%E5%B0%94%E6%9B%B2%E7%BA%BF/1091769?fr=aladdin)**)**是应用于二维图形应用程序的[数学曲线](http://baike.baidu.com/view/627248.htm)。 曲线定义:起始点、终止点(也称锚点)、控制点。通过调整控制点,贝塞尔曲线的形状会发生变化。 1962年,法国数学家**Pierre Bézier**第一个研究了这种[矢量](http://baike.baidu.com/view/77474.htm)绘制曲线的方法,并给出了详细的计算公式,因此按照这样的公式绘制出来的曲线就用他的姓氏来命名,称为贝塞尔曲线。
202202

203+
Android提供了二阶贝塞尔曲线和三阶贝塞尔曲线的 API,利用这两个api可以将更高阶的贝塞尔曲线的效果转换成多个二阶贝塞尔曲线和三阶贝塞尔曲线。
204+
205+
206+
207+
##### 一阶贝塞尔曲线
208+
209+
描述:由 P0 至 P1 的连续点, 描述的一条线段
210+
211+
通用公式:
212+
213+
![一阶贝塞尔曲线通用公式](img\one_bezier_formula.jpg)
214+
215+
> B(t)为t时间下 点的坐标;
216+
>
217+
> P0为起点,Pn为终点,Pi为控制点。
218+
>
219+
> 下同
220+
221+
效果图:
222+
203223
![一阶贝塞尔曲线](img\one_bezier.webp)
204224

225+
##### 二阶贝塞尔曲线
226+
227+
描述:由 P0 至 P1 的连续点 Q0,描述一条线段。由 P1 至 P2 的连续点 Q1,描述一条线段。由 Q0 至 Q1 的连续点 B(t),描述一条二次贝塞尔曲线。
228+
229+
通用公式:
230+
231+
![一阶贝塞尔曲线通用公式](img\two_bezier_formula.jpg)
232+
233+
效果图:
234+
205235
![二阶贝塞尔曲线](img\two_bezier.webp)
206236

207-
![三阶贝塞尔曲线](img\three_bezier.webp)
237+
##### 三阶贝塞尔曲线
238+
239+
通用公式:
240+
241+
![一阶贝塞尔曲线通用公式](img\three_bezier_formula.jpg)
242+
243+
效果图:
208244

209-
![四阶贝塞尔曲线](img\four_bezier.webp)
245+
![五阶贝塞尔曲线](img\three_bezier.webp)
210246

211-
![五阶贝塞尔曲线](img\five_bezier.webp)
212247

248+
249+
### PathMeasure
250+
251+
#### 初步认识
252+
253+
- 初始化
254+
255+
```java
256+
// 创建PathMeasure对象
257+
PathMeasure pathMeasure = new PathMeasure();
258+
// 设置关联Path
259+
// PathMeasure(Path path, boolean forceClosed);
260+
// forceClosed: 对绑定的Path不会产生任何影响,对PathMeasure的测量结果有影响
261+
pathMeasure.setPath(path, true);
262+
```
263+
264+
- API
265+
266+
- **getLength**:获取计算的路径长度
267+
268+
- **getSegment**:用于截取path中的一个片段
269+
270+
```java
271+
public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo){...}
272+
```
273+
274+
- getPosTan:用于获取路径上某点的坐标及其切线的坐标
275+
276+
```java
277+
public boolean getPosTan(float distance, float pos[], float tan[]) {...}
278+
279+
// 通过getPosTan获取到某点切线的坐标去获取路径上某点的切线的角度
280+
(Math.atan2(tan[1], tan[0] * 180.0 / Math.PI))
281+
```
282+
283+

app/src/main/AndroidManifest.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@
99
android:roundIcon="@mipmap/ic_launcher_round"
1010
android:supportsRtl="true"
1111
android:theme="@style/AppTheme">
12-
<activity android:name=".WaveActivity"></activity>
12+
<activity android:name=".PathPosTanActivity"></activity>
13+
<activity android:name=".PathPaintActivity" />
14+
<activity android:name=".PathTracingActivity" />
15+
<activity android:name=".PathMeasureDemoActivity" />
16+
<activity android:name=".BezierDemoActivity" />
17+
<activity android:name=".PathBezierActivity" />
18+
<activity android:name=".WaveActivity" />
1319
<activity android:name=".PathMorphingActivity" />
1420
<activity android:name=".DrawPadActivity" />
1521
<activity android:name=".ThirdBezierActivity" />
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.hyd.animationart;
2+
3+
import androidx.appcompat.app.AppCompatActivity;
4+
5+
import android.content.Intent;
6+
import android.os.Bundle;
7+
import android.view.View;
8+
9+
public class BezierDemoActivity extends AppCompatActivity implements View.OnClickListener {
10+
11+
@Override
12+
protected void onCreate(Bundle savedInstanceState) {
13+
super.onCreate(savedInstanceState);
14+
setContentView(R.layout.activity_bezier_demo);
15+
16+
findViewById(R.id.second_bezier).setOnClickListener(this);
17+
findViewById(R.id.third_bezier).setOnClickListener(this);
18+
findViewById(R.id.draw_pad).setOnClickListener(this);
19+
findViewById(R.id.path_morphing).setOnClickListener(this);
20+
findViewById(R.id.bezier_wave).setOnClickListener(this);
21+
findViewById(R.id.bezier_path).setOnClickListener(this);
22+
}
23+
24+
@Override
25+
public void onClick(View v) {
26+
switch (v.getId()) {
27+
case R.id.second_bezier:
28+
startActivity(new Intent(this, SecondBezierActivity.class));
29+
break;
30+
case R.id.third_bezier:
31+
startActivity(new Intent(this, ThirdBezierActivity.class));
32+
break;
33+
case R.id.draw_pad:
34+
startActivity(new Intent(this, DrawPadActivity.class));
35+
break;
36+
case R.id.path_morphing:
37+
startActivity(new Intent(this, PathMorphingActivity.class));
38+
break;
39+
case R.id.bezier_wave:
40+
startActivity(new Intent(this, WaveActivity.class));
41+
break;
42+
case R.id.bezier_path:
43+
startActivity(new Intent(this, PathBezierActivity.class));
44+
break;
45+
}
46+
}
47+
}

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

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package com.hyd.animationart;
22

3-
import androidx.appcompat.app.AppCompatActivity;
4-
53
import android.content.Intent;
64
import android.os.Bundle;
75
import android.view.View;
86

7+
import androidx.appcompat.app.AppCompatActivity;
8+
99
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
1010

1111
@Override
@@ -14,11 +14,9 @@ protected void onCreate(Bundle savedInstanceState) {
1414
setContentView(R.layout.activity_main);
1515

1616
findViewById(R.id.vector_demo).setOnClickListener(this);
17-
findViewById(R.id.second_bezier).setOnClickListener(this);
18-
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);
17+
findViewById(R.id.bezier_demo).setOnClickListener(this);
18+
findViewById(R.id.path_measure_demo).setOnClickListener(this);
19+
findViewById(R.id.animation_demo).setOnClickListener(this);
2220
}
2321

2422
@Override
@@ -27,20 +25,14 @@ public void onClick(View v) {
2725
case R.id.vector_demo:
2826
startActivity(new Intent(this, VectorDemoActivity.class));
2927
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));
28+
case R.id.bezier_demo:
29+
startActivity(new Intent(this, BezierDemoActivity.class));
3830
break;
39-
case R.id.path_morphing:
40-
startActivity(new Intent(this, PathMorphingActivity.class));
31+
case R.id.path_measure_demo:
32+
startActivity(new Intent(this, PathMeasureDemoActivity.class));
4133
break;
42-
case R.id.bezier_wave:
43-
startActivity(new Intent(this, WaveActivity.class));
34+
case R.id.animation_demo:
35+
// startActivity(new Intent(this, DrawPadActivity.class));
4436
break;
4537
}
4638
}
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 PathBezierActivity extends AppCompatActivity {
8+
9+
@Override
10+
protected void onCreate(Bundle savedInstanceState) {
11+
super.onCreate(savedInstanceState);
12+
setContentView(R.layout.activity_path_bezier);
13+
}
14+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.hyd.animationart;
2+
3+
import androidx.appcompat.app.AppCompatActivity;
4+
5+
import android.content.Intent;
6+
import android.os.Bundle;
7+
import android.view.View;
8+
9+
public class PathMeasureDemoActivity extends AppCompatActivity implements View.OnClickListener {
10+
11+
@Override
12+
protected void onCreate(Bundle savedInstanceState) {
13+
super.onCreate(savedInstanceState);
14+
setContentView(R.layout.activity_path_measure_demo);
15+
16+
findViewById(R.id.path_tracing).setOnClickListener(this);
17+
findViewById(R.id.path_paint).setOnClickListener(this);
18+
findViewById(R.id.path_pos_tan).setOnClickListener(this);
19+
}
20+
21+
@Override
22+
public void onClick(View v) {
23+
switch (v.getId()) {
24+
case R.id.path_tracing:
25+
startActivity(new Intent(this, PathTracingActivity.class));
26+
break;
27+
case R.id.path_paint:
28+
startActivity(new Intent(this, PathPaintActivity.class));
29+
break;
30+
case R.id.path_pos_tan:
31+
startActivity(new Intent(this, PathPosTanActivity.class));
32+
break;
33+
}
34+
}
35+
}
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 PathPaintActivity extends AppCompatActivity {
8+
9+
@Override
10+
protected void onCreate(Bundle savedInstanceState) {
11+
super.onCreate(savedInstanceState);
12+
setContentView(R.layout.activity_path_paint);
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 PathPosTanActivity extends AppCompatActivity {
8+
9+
@Override
10+
protected void onCreate(Bundle savedInstanceState) {
11+
super.onCreate(savedInstanceState);
12+
setContentView(R.layout.activity_path_pos_tan);
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 PathTracingActivity extends AppCompatActivity {
8+
9+
@Override
10+
protected void onCreate(Bundle savedInstanceState) {
11+
super.onCreate(savedInstanceState);
12+
setContentView(R.layout.activity_path_tracing);
13+
}
14+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.hyd.animationart.other;
2+
3+
import android.animation.TypeEvaluator;
4+
import android.graphics.PointF;
5+
6+
import com.hyd.animationart.utils.BezierUtil;
7+
8+
/**
9+
* Created by hydCoder on 2019/12/27.
10+
* 以梦为马,明日天涯。
11+
*/
12+
public class BezierEvaluator implements TypeEvaluator<PointF> {
13+
14+
private PointF mFlagPointF;
15+
16+
public BezierEvaluator(PointF flagPointF) {
17+
this.mFlagPointF = flagPointF;
18+
}
19+
20+
@Override
21+
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
22+
return BezierUtil.CalculateBezierPointForQuadratic(fraction, startValue, mFlagPointF, endValue);
23+
}
24+
}

app/src/main/java/com/hyd/animationart/utils/BezierUtil.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
public class BezierUtil {
66

77
/**
8+
* 二阶贝塞尔曲线点坐标计算公式
89
* B(t) = (1 - t)^2 * P0 + 2t * (1 - t) * P1 + t^2 * P2, t ∈ [0,1]
910
*
1011
* @param t 曲线长度比例
@@ -22,6 +23,7 @@ public static PointF CalculateBezierPointForQuadratic(float t, PointF p0, PointF
2223
}
2324

2425
/**
26+
* 三阶贝塞尔曲线点坐标计算公式
2527
* B(t) = P0 * (1-t)^3 + 3 * P1 * t * (1-t)^2 + 3 * P2 * t^2 * (1-t) + P3 * t^3, t ∈ [0,1]
2628
*
2729
* @param t 曲线长度比例

0 commit comments

Comments
 (0)