h5教程利用SurfaceView实现下雨与下雪动画的效果
更新时间:2024-01-19前言
本教程将使用SurfaceView实现下雨与下雪动画的效果。在移动应用程序开发中,使用动画效果可以提升用户体验,增加应用的吸引力。下雨和下雪动画可以模拟自然环境中的天气现象,为应用增添一丝趣味和活力。
实现下雨动画
下雨动画通常由多个垂直下落的线条组成,每个线条表示一滴雨滴。我们可以通过绘制矩形并在每次绘制过程中更新矩形的位置,来实现下雨的效果。
public class RainView extends SurfaceView implements SurfaceHolder.Callback { private RainThread rainThread; private Listraindrops; public RainView(Context context) { super(context); SurfaceHolder holder = getHolder(); holder.addCallback(this); rainThread = new RainThread(holder); raindrops = new ArrayList<>(); } @Override public void surfaceCreated(SurfaceHolder holder) { // 初始化雨滴 for (int i = 0; i < 100; i++) { RainDrop raindrop = new RainDrop(getWidth(), getHeight()); raindrops.add(raindrop); } // 启动下雨动画线程 rainThread.setRunning(true); rainThread.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 处理SurfaceView尺寸变化的情况 } @Override public void surfaceDestroyed(SurfaceHolder holder) { // 停止下雨动画线程 boolean retry = true; rainThread.setRunning(false); while (retry) { try { rainThread.join(); retry = false; } catch (InterruptedException e) { // 处理线程中断异常 } } } private class RainThread extends Thread { private final SurfaceHolder surfaceHolder; private boolean running; public RainThread(SurfaceHolder surfaceHolder) { this.surfaceHolder = surfaceHolder; running = false; } public void setRunning(boolean running) { this.running = running; } @Override public void run() { Canvas canvas; while (running) { canvas = null; try { // 获取SurfaceView的Canvas对象 canvas = surfaceHolder.lockCanvas(); synchronized (surfaceHolder) { // 清空画布 canvas.drawColor(Color.BLACK); // 更新和绘制雨滴 for (RainDrop raindrop : raindrops) { raindrop.update(); raindrop.draw(canvas); } } } finally { if (canvas != null) { // 解锁Canvas并提交绘制结果 surfaceHolder.unlockCanvasAndPost(canvas); } } } } } } public class RainDrop { private static final int SPEED = 10; private int x; private int y; private int width; private int height; public RainDrop(int screenWidth, int screenHeight) { x = generateRandomNumber(screenWidth); y = generateRandomNumber(screenHeight); width = generateRandomNumber(5, 10); height = generateRandomNumber(40, 80); } public void update() { y += SPEED; // 当雨滴超出屏幕范围时,重新设置位置 if (y > screenHeight) { x = generateRandomNumber(screenWidth); y = generateRandomNumber(screenHeight); width = generateRandomNumber(5, 10); height = generateRandomNumber(40, 80); } } public void draw(Canvas canvas) { Paint paint = new Paint(); paint.setColor(Color.BLUE); canvas.drawRect(x, y, x + width, y + height, paint); } private int generateRandomNumber(int max) { return new Random().nextInt(max); } private int generateRandomNumber(int min, int max) { return new Random().nextInt(max - min + 1) + min; } }
实现下雪动画
下雪动画由多个随机漂浮的雪花组成。我们可以使用类似的方法,在每次绘制过程中更新雪花的位置,来实现下雪效果。
public class SnowView extends SurfaceView implements SurfaceHolder.Callback { private SnowThread snowThread; private Listsnowflakes; public SnowView(Context context) { super(context); SurfaceHolder holder = getHolder(); holder.addCallback(this); snowThread = new SnowThread(holder); snowflakes = new ArrayList<>(); } @Override public void surfaceCreated(SurfaceHolder holder) { // 初始化雪花 for (int i = 0; i < 100; i++) { Snowflake snowflake = new Snowflake(getWidth(), getHeight()); snowflakes.add(snowflake); } // 启动下雪动画线程 snowThread.setRunning(true); snowThread.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 处理SurfaceView尺寸变化的情况 } @Override public void surfaceDestroyed(SurfaceHolder holder) { // 停止下雪动画线程 boolean retry = true; snowThread.setRunning(false); while (retry) { try { snowThread.join(); retry = false; } catch (InterruptedException e) { // 处理线程中断异常 } } } private class SnowThread extends Thread { private final SurfaceHolder surfaceHolder; private boolean running; public SnowThread(SurfaceHolder surfaceHolder) { this.surfaceHolder = surfaceHolder; running = false; } public void setRunning(boolean running) { this.running = running; } @Override public void run() { Canvas canvas; while (running) { canvas = null; try { // 获取SurfaceView的Canvas对象 canvas = surfaceHolder.lockCanvas(); synchronized (surfaceHolder) { // 清空画布 canvas.drawColor(Color.BLACK); // 更新和绘制雪花 for (Snowflake snowflake : snowflakes) { snowflake.update(); snowflake.draw(canvas); } } } finally { if (canvas != null) { // 解锁Canvas并提交绘制结果 surfaceHolder.unlockCanvasAndPost(canvas); } } } } } } public class Snowflake { private static final int SPEED = 5; private float x; private float y; private float radius; private float angle; public Snowflake(int screenWidth, int screenHeight) { x = generateRandomNumber(screenWidth); y = generateRandomNumber(screenHeight); radius = generateRandomNumber(5, 10); angle = generateRandomNumber(0, 360); } public void update() { x += SPEED * Math.cos(Math.toRadians(angle)); y += SPEED * Math.sin(Math.toRadians(angle)); // 当雪花超出屏幕范围时,重新设置位置 if (x < 0 || x > screenWidth || y > screenHeight) { x = generateRandomNumber(screenWidth); y = generateRandomNumber(screenHeight); angle = generateRandomNumber(0, 360); } } public void draw(Canvas canvas) { Paint paint = new Paint(); paint.setColor(Color.WHITE); canvas.drawCircle(x, y, radius, paint); } private float generateRandomNumber(float max) { return new Random().nextFloat() * max; } private float generateRandomNumber(float min, float max) { return new Random().nextFloat() * (max - min) + min; } }
总结
通过SurfaceView实现下雨与下雪动画的效果,可以为移动应用程序添加一些生动和有趣的特效。通过绘制每个雨滴和雪花的位置,并在每次绘制过程中更新它们的位置,我们可以模拟出下雨和下雪的效果。在SurfaceView的回调方法中启动动画线程,并在线程中不断绘制动画效果,可以实现流畅的动画播放。希望本教程对您理解如何利用SurfaceView实现动画效果有所帮助。