Android在canvas中實現高效能的煙花/粒子特效
新年到了,本文將展示通過自定義view繪製煙花效果的案例,同時介紹一種優化canvas繪製時的效能的方法.
效果展示
每點選一下螢幕會產生一枚煙花,煙花飛到最上空會炸裂成60~100個碎片,
同屏可能有上千個粒子在不停更新它的位置.
專案地址
程式碼分析
- 首先專案結構
└─fireworks
ColorfullView.java -自定義的view
Firework.java -對煙花建立模型
MainActivity.java
Particle.java -粒子
PContext.java -工具類
PVector.java -向量類
- 使用GestureDetector處理使用者輸入,每點選一次在當前位置建立一枚煙花
mGesture = new GestureDetectorCompat(getContext(), new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
fireworks.add(new Firework(e.getX(), e.getY()));
ViewCompat.postInvalidateOnAnimation(ColorfullView.this);
return true;
}
});
- FireWork類包含兩個屬性
ArrayList<Particle> particles; // 炸開後的粒子
Particle firework; // 炸開前的粒子
- Particle類具有隨機的顏色、大小、速度以接近真實
- 每繪製一幀會呼叫FireWork的run方法,該方法中會呼叫當前粒子的update和display方法
void run(Canvas canvas, Paint paint) {
if (firework != null) {//炸裂前
firework.applyForce(gravity);
firework.update();
firework.display(canvas, paint);
if (firework.explode()) {
int fragments = (int) random(60, 100);//碎片個數
for (int i = 0; i < fragments; i++) {
particles.add(new Particle(firework.location, hu)); // Add "num" amount of particles to the arraylist
}
firework = null;
firstExplode = true;
}
} else {//炸裂後
if (firstExplode) {//螢幕一閃
firstExplode = false;
canvas.drawColor(Color.HSVToColor(new float[]{hu, 0.6f, 0.6f}));
}
for (int i = particles.size() - 1; i >= 0; i--) {
Particle p = particles.get(i);
p.applyForce(gravity);
p.update();
p.display(canvas, paint);
if (p.isDead()) {
particles.remove(i);
}
}
}
}
效能優化
這時候功能基本實現了,剩下的就是將每一個煙花繪製在canvas上,通常我們會這樣寫
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
for (int i = fireworks.size() - 1; i >= 0; i--) {
Firework f = fireworks.get(i);
f.run(canvas, mParticlePaint);
if (f.done()) {
fireworks.remove(i);
}
}
//canvas.drawBitmap(canvasBitmap,0, 0, mBitmapPaint);
if (!fireworks.isEmpty()) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
然而你會發現效能很糟糕,幀數隨著粒子數的增加直線下降直到個位數,優化如下
@Override
protected void onDraw(Canvas canvas) {
if (canvasBitmap == null || canvasBitmap.isRecycled()) {
canvasBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(canvasBitmap);
mBitmapShader = new BitmapShader(canvasBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mBitmapPaint.setShader(mBitmapShader);
mBitmapPaint.setDither(false);
}
bitmapCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
for (int i = fireworks.size() - 1; i >= 0; i--) {
Firework f = fireworks.get(i);
f.run(bitmapCanvas, mParticlePaint);
if (f.done()) {
fireworks.remove(i);
}
}
canvas.drawPaint(mBitmapPaint);
if (!fireworks.isEmpty()) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
Thanks
some codes were from Daniel Shiffman
附贈
相關文章
- HTML5+Canvas漂亮的3D煙花動畫生日特效,節日特效,煙花HTMLCanvas3D動畫特效
- 可以隨心所欲的canvas粒子特效Canvas特效
- 用canvas 畫煙花Canvas
- canvas 中普通動效與粒子動效的實現Canvas
- Canvas 放煙花合集 -- 用粉絲頭像做成煙花綻放?Canvas
- 用canvas實現流星特效Canvas特效
- 春節將至,喜慶的煙花安排上(js實現煙花)JS
- 實現一個煙花效果
- 【帶著canvas去流浪(10)】文字煙花Canvas
- threejs+vue3實現煙花效果JSVue
- HTML5 Canvas 超逼真煙花綻放動畫HTMLCanvas動畫
- 粒子類特效SDK,電影級的逼真特效特效
- 還在用canvas畫格子嗎?文字煙花效果更不錯噢Canvas
- canvas實現炫酷的黑客帝國數字雨特效Canvas黑客特效
- 基於 HTML5 Canvas 實現的文字動畫特效HTMLCanvas動畫特效
- 在Vue中使用WebSocket+HighCharts+Canvas實現高效能的頻譜瀑布圖VueWebCanvas
- 利用著色器在WPF中實現陰影特效特效
- 幾十行js實現很炫的canvas互動特效JSCanvas特效
- 基於 HTML5 Canvas 實現文字動畫特效HTMLCanvas動畫特效
- 炒雞簡單的canvas粒子Canvas
- web前端入門到實戰:H5-canvas實現粒子時鐘Web前端H5Canvas
- 棒呆!如何用css3實現煙花綻放效果CSSS3
- 從未設計過現實裡的煙花秀,他卻是一位資深“煙花模擬器”開發者
- Android粒子篇之文字的粒子化運動Android
- 說說在 Android 的 RecyclerView 中如何實現下拉刷AndroidView
- 在 iOS 中使用 GLSL 實現抖音特效iOS特效
- 基於canvas實現的高效能、跨平臺的股票圖表庫--clchartCanvas
- canvas動畫特效 之 星空Canvas動畫特效
- [譯] Story 中 Type Mode 在 iOS 和 Android 上的實現iOSAndroid
- 2-66. 製作石頭和稻草的粒子特效特效
- Statista:2019年美國從中國進口了煙花達3.15億美元 佔美國煙花總進口量的94%
- 【帶著canvas去流浪(9)】粒子動畫Canvas動畫
- loading動畫的效能優化-摒棄Canvas,擁抱CSS3-實現點選特效動畫優化CanvasCSSS3特效
- 過年有燃放煙花爆竹禁令那我們用css寫一個仙女棒煙花看看吧CSS
- Android撩妹特效系列!仿instagram文字自動排版功能實現!Android特效
- 紅巨星粒子特效合集外掛:Trapcode Suite 18 for Mac特效UIMac
- Flutter動畫實現粒子漂浮效果Flutter動畫
- Canvas中的剪刀手講解與實戰——Android高階UICanvasAndroidUI