浅谈Android实现3D旋转
来源:互联网 发布:php面向对象 实战项目 编辑:程序博客网 时间:2024/05/18 00:13
本文主要记录有关View以及Bitmap的3D旋转效果的实现方法与相关思考。
1 使用Animation实现View的3D旋转
采用继承Animation的方法实现View的3D旋转效果,在ApiDemos里面有详细的代码,具体路径为src/com/example/android/apis/animation/Rotate3dAnimation.java
贴一下代码,记录一下:
/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.example.android.apis.animation;import android.view.animation.Animation;import android.view.animation.Transformation;import android.graphics.Camera;import android.graphics.Matrix;/** * An animation that rotates the view on the Y axis between two specified angles. * This animation also adds a translation on the Z axis (depth) to improve the effect. */public class Rotate3dAnimation extends Animation { private final float mFromDegrees; private final float mToDegrees; private final float mCenterX; private final float mCenterY; private final float mDepthZ; private final boolean mReverse; private Camera mCamera; /** * Creates a new 3D rotation on the Y axis. The rotation is defined by its * start angle and its end angle. Both angles are in degrees. The rotation * is performed around a center point on the 2D space, definied by a pair * of X and Y coordinates, called centerX and centerY. When the animation * starts, a translation on the Z axis (depth) is performed. The length * of the translation can be specified, as well as whether the translation * should be reversed in time. * * @param fromDegrees the start angle of the 3D rotation * @param toDegrees the end angle of the 3D rotation * @param centerX the X center of the 3D rotation * @param centerY the Y center of the 3D rotation * @param reverse true if the translation should be reversed, false otherwise */ public Rotate3dAnimation(float fromDegrees, float toDegrees, float centerX, float centerY, float depthZ, boolean reverse) { mFromDegrees = fromDegrees; mToDegrees = toDegrees; mCenterX = centerX; mCenterY = centerY; mDepthZ = depthZ; mReverse = reverse; } @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); mCamera = new Camera(); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { final float fromDegrees = mFromDegrees; float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime); final float centerX = mCenterX; final float centerY = mCenterY; final Camera camera = mCamera; final Matrix matrix = t.getMatrix(); camera.save(); if (mReverse) { camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime); } else { camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime)); } camera.rotateY(degrees); camera.getMatrix(matrix); camera.restore(); matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); }}具体我也就不分析了,网上有很多的详细的说明,这里最主要的是applyTransformation函数,该函数第一个参数是当前动画的进度范围在[0, 1],该函数根据当前的动画进度interpolatedTime,先得出当前帧的y轴旋转角度degrees,然后计算出当前帧的变换矩阵Matrix。
调用上述代码实现旋转:
final float centerX = mContainer.getWidth() / 2.0f; final float centerY = mContainer.getHeight() / 2.0f; final Rotate3dAnimation rotation = new Rotate3dAnimation(start, end, centerX, centerY, 310.0f, true); rotation.setDuration(500); rotation.setFillAfter(true); rotation.setInterpolator(new AccelerateInterpolator()); rotation.setAnimationListener(new DisplayNextView(position)); mContainer.startAnimation(rotation);上面的mContainer可以是任意的一个View,如果想再旋转回来,只要调用:
Rotate3dAnimation(-90, 0, centerX, centerY, 310.0f, false);
2 Camera、Matrix、Canvas实现ImageView的3D旋转
Android中动画的本质还是矩阵变换,每种变换对应着不同的矩阵,上述applyTransformation函数计算了每一帧变换的Matrix,下面就直接用Matrix来变换ImageView,实现3D旋转动画,与Animation方法不同的是:Animation自带了动画的驱动以及每一帧的计算,如果不借助系统提供的Animation框架,则需要自己计算每一帧,同时驱动每一帧动画的更新,下面模拟一下简易的动画过程,模拟每16ms刷新一帧的效果,其实很简单,就是每16ms发送一条消息,驱动下一帧动画的计算和刷新(Animation框架用的是Choreographer,这个对象的postCallback函数可以传进来一个Runnable,同时去请求下一个同步信号,在信号被SurfaceFlinger回调回来的时候运行前面的Runnbale对象,但是这个方法是hide的)。
public void scheduleAnimation() {if (!mStarted) { return;}Message msg = mHandler.obtainMessage();mHandler.sendMessageDelayed(msg, 15);} public class InnerHandler extends Handler { public void handleMessage(Message msg) { scheduleAnimation(); } }用这种方法只能简单的模拟动画的过程,肯定是不准确的,因为每个消息在MessageQueue中排队,实际被执行的时间是不确定的,这里只是简单的模拟动画的过程,下面需要计算每一帧的变换矩阵Matrix:
protected Matrix applyTransformation(float interpolatedTime) { final float fromDegrees = mFromDegrees; // 生成中间角度 float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime); final float centerX = mCenterX; final float centerY = mCenterY; final Camera camera = mCamera; final Matrix matrix = new Matrix(); camera.save(); if (mReverse) { camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime); } else { camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime)); } camera.rotateY(degrees); camera.getMatrix(matrix); camera.restore(); matrix.preTranslate(-centerX, -centerY); matrix.postTranslate(centerX, centerY); return matrix; }
计算出变换的Matrix以后可以使用,需要利用该Matrix调用ImageView.setImageMatrix方法。使用该方法需要注意将scaleType属性设置为"matrix"
<ImageView android:id="@+id/img1" android:layout_width="200dp" android:layout_height="200dp" android:layout_gravity="left" android:scaleType="matrix" android:src="@drawable/img1_1" />
3 Camera、Matrix、Canvas实现Bitmap的3D旋转
这种方法是利用第二种方法中的动画驱动框架,手动计算出当前的每一帧Bitmap,然后显示到ImageView上面。
首先做一些必要的Bitmap、Canvas的初始化:
mImg = (ImageView)findViewById(R.id.img1);mCanvas = new Canvas();mSrcBitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.img1_1)).getBitmap();mBitmap = Bitmap.createBitmap(mSrcBitmap.getWidth(), mSrcBitmap.getHeight(), Config.ARGB_8888);mCanvas.setBitmap(mBitmap);根据变换矩阵,计算出每一帧Bitmap:
mBitmap.eraseColor(0);Matrix matrix = applyTransformation(progress);mCanvas.drawBitmap(mSrcBitmap, matrix, null);mImg.setImageBitmap(mBitmap);这样就能够实现图片的3D旋转动画,这里需要主要的一点是,每次在绘制Bitmap之前,都需要将Bitmap清空,否则有些像素在本次绘制的时候没有绘制到,会保留之前的像素值,造成动画异常。
源码下载:https://github.com/houliang/Android-Widget3DRotation
- 浅谈Android实现3D旋转
- Android系列之浅谈Android 3D旋转
- Android实现3D旋转效果
- Android 3D旋转动画实现
- android 实现3D动画旋转效果
- android实现3D旋转效果
- Android实现3D旋转效果
- Android实现对角线3D旋转
- 【android】Rotate3dAnimation实现3D旋转动画
- 3d旋转 android
- Android如何实现3D旋转,我只要旋转,而不是旋转动画
- Android中 3D 圆形旋转动态实现
- 利用Android的Camera类实现3D旋转功能
- iOS实现3D旋转
- GPUImageTransformFilter实现3D旋转
- Android的3D旋转
- Android的3D旋转
- Android的3D旋转
- Context应用场景
- lucene中的Filter
- 碎片的生命周期
- 关键子工程
- caffe|Fine-tuning for driver
- 浅谈Android实现3D旋转
- docker 入门
- JavaScript中的call()和apply()方法
- 238. Product of Array Except Self
- 网络编程socket(服务端简单模拟)(OC)
- [疯狂Java]面向对象:继承、覆盖、super
- C语言基础 求余运算
- Android项目之仿360手机助手项目
- Qt之QImageReader