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動畫特效
- html5canvas全屏煙花動畫特效HTMLCanvas動畫特效
- canvas系列三之《煙花》效果實現Canvas
- Android實現粒子爆炸特效Android特效
- canvas實現煙花燃放效果程式碼例項Canvas
- 用canvas 畫煙花Canvas
- 可以隨心所欲的canvas粒子特效Canvas特效
- 春節將至,喜慶的煙花安排上(js實現煙花)JS
- Canvas 放煙花合集 -- 用粉絲頭像做成煙花綻放?Canvas
- 實現一個煙花效果
- canvas 中普通動效與粒子動效的實現Canvas
- 【帶著canvas去流浪(10)】文字煙花Canvas
- 用canvas實現流星特效Canvas特效
- Canvas 實現炫麗的粒子運動效果(粒子生成文字)Canvas
- Android製作粒子爆炸特效Android特效
- HTML5 Canvas 超逼真煙花綻放動畫HTMLCanvas動畫
- Android 中 View 炸裂特效的實現分析AndroidView特效
- threejs+vue3實現煙花效果JSVue
- Android超炫酷煙花程式Android
- canvas實現具有粒子效果的動態進度條Canvas
- 還在用canvas畫格子嗎?文字煙花效果更不錯噢Canvas
- 從未設計過現實裡的煙花秀,他卻是一位資深“煙花模擬器”開發者
- 基於 HTML5 Canvas 實現的文字動畫特效HTMLCanvas動畫特效
- 粒子類特效SDK,電影級的逼真特效特效
- 棒呆!如何用css3實現煙花綻放效果CSSS3
- 利用著色器在WPF中實現陰影特效特效
- 基於 HTML5 Canvas 實現文字動畫特效HTMLCanvas動畫特效
- canvas實現炫酷的黑客帝國數字雨特效Canvas黑客特效
- 幾十行js實現很炫的canvas互動特效JSCanvas特效
- html5canvas: 教你實現知乎登入動態粒子背景HTMLCanvas
- 炒雞簡單的canvas粒子Canvas
- web前端入門到實戰:H5-canvas實現粒子時鐘Web前端H5Canvas
- html5煙花效果HTML
- 在Vue中使用WebSocket+HighCharts+Canvas實現高效能的頻譜瀑布圖VueWebCanvas
- 在 iOS 中使用 GLSL 實現抖音特效iOS特效
- canvas實現web excel高效能表格(釋出開源)CanvasWebExcel
- canvas動畫特效 之 星空Canvas動畫特效
- 過年有燃放煙花爆竹禁令那我們用css寫一個仙女棒煙花看看吧CSS