java代码实现的帧动画 用java制作一个动画

求java做动画代码import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class TestImage extends Frame
{
private static final long serialVersionUID = 1L;
private static boolean PRESSED = false;
private static int pointX = 0;
private static int pointy = 200;
private static int RIGHT_GO = 0;
private static int LEFT_GO = 0;
private static int DIR = 0;
private static int ANGLE = 0;
private static int W = 50;
private static int H = 60;
private _Canvas canvas = null;
public TestImage ()
{
add (canvas = new _Canvas ());
setIgnoreRepaint (true);
requestFocus ();
}
public class _Canvas extends Canvas implements Runnable
{
private static final long serialVersionUID = 1L;
private BufferedImage bi = null;
private Image bufferedImage = null;
private Thread thread = null;
private long sleepTime = 10;
public _Canvas ()
{
try
{
bi = ImageIO.read (new File ("go.png"));
}
catch (IOException e)
{}
setBackground (Color.BLACK);
requestFocus ();
addKeyListener (new KeyListener ()
{
@Override
public void keyTyped ( KeyEvent e )
{}
@Override
public void keyReleased ( KeyEvent e )
{
RIGHT_GO = 0;
PRESSED = false;
}
@Override
public void keyPressed ( KeyEvent e )
{
// 38 40 37 39上下左右
DIR = e.getKeyCode ();
PRESSED = true;
}
});
}
@Override
public void paint ( Graphics g )
{
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint (RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage (rotateImage (bi.getSubimage (RIGHT_GO, LEFT_GO, W, H), ANGLE, true), pointX, pointy, W, H,
this);
g2d.dispose ();
}
@Override
public void update ( Graphics g )
{
if (null == bufferedImage)
{
bufferedImage = createImage (getWidth (), getHeight ());
}
Graphics bufferedG = bufferedImage.getGraphics ();
bufferedG.clearRect (0, 0, getWidth (), getHeight ());
paint (bufferedG);
bufferedG.dispose ();
g.drawImage (bufferedImage, 0, 0, this);
g.dispose ();
}
public void start ()
{
thread = new Thread (this);
thread.setName ("TestImage");
thread.setPriority (Thread.MIN_PRIORITY);
thread.start ();
}
public synchronized void stop ()
{
thread = null;
notify ();
}
@Override
public void run ()
{
Thread me = Thread.currentThread ();
while (thread == me!isShowing () || getSize ().width == 0)
{
try
{
Thread.sleep (555);
}
catch (InterruptedException e)
{
return;
}
}
while (thread == meisShowing ())
{
if (PRESSED)
{
try
{
if (DIR == 39)
{
RIGHT_GO = RIGHT_GO50;
LEFT_GO = 0;
pointX = pointX1;
if (pointX420)
{
ANGLE = 90;
pointX--;
pointy--;
W = 60;
H = 50;
}
if (RIGHT_GO50)
{
RIGHT_GO = 0;
}
}
else if (DIR == 37)
{
pointX = pointX - 1;
RIGHT_GO = RIGHT_GO50;
LEFT_GO = 60;
if (pointX0)
{
ANGLE = -90;
pointX;
pointy--;
W = 60;
H = 50;
}
if (RIGHT_GO50)
{
RIGHT_GO = 0;
}
}
else if (DIR == 38)
{
W = 50;
H = 60;
pointy = 150;
ANGLE = 0;
RIGHT_GO = 100;
}
else if (DIR == 40)
{
W = 50;
H = 60;
ANGLE = 0;
pointy = 200;
RIGHT_GO = 0;
}
Thread.sleep (sleepTime);
repaint ();
}
catch (InterruptedException e)
{
break;
}
}
else
{
RIGHT_GO = RIGHT_GO50;
LEFT_GO = 0;
pointX = pointX1;
if (RIGHT_GO50)
{
RIGHT_GO = 0;
}
if (pointX500)
{
pointX = 0;
}
try
{
Thread.sleep (sleepTime);
repaint ();
}
catch (InterruptedException e)
{
break;
}
}
}
thread = null;
}
}
/**
* 旋转图像为指定角度
*
* @param degree
* @return
*/
public static BufferedImage rotateImage ( final BufferedImage image, final int angdeg, final boolean d )
{
int w = image.getWidth ();
int h = image.getHeight ();
int type = image.getColorModel ().getTransparency ();
BufferedImage img;
Graphics2D graphics2d;
( graphics2d = ( img = new BufferedImage (w, h, type) ).createGraphics () ).setRenderingHint (
RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2d.rotate (d ? -Math.toRadians (angdeg) : Math.toRadians (angdeg), w / 2, h / 2);
graphics2d.drawImage (image, 0, 0, null);
graphics2d.dispose ();
return img;
}
public static void main ( String[] args )
{
EventQueue.invokeLater (new Runnable ()
{
@Override
public void run ()
{
final TestImage ti = new TestImage ();
ti.setSize (new Dimension (500, 300));
ti.setLocationRelativeTo (null);
ti.addWindowListener (new WindowAdapter ()
{
@Override
public void windowClosing ( WindowEvent e )
{
System.exit (0);
}
@Override
public void windowDeiconified ( WindowEvent e )
{
ti.canvas.start ();
}
@Override
public void windowIconified ( WindowEvent e )
{
ti.canvas.stop ();
}
});
ti.setResizable (false);
ti.canvas.start ();
ti.setVisible (true);
}
});
}
}
求助一个android动画怎么写,音乐播放状态的动画在Android3.0(即API Level11)以前,Android仅支持2种动画:分别是Frame Animation(逐帧动画)和Tween Animation(补间动画),在3.0之后Android支持了一种新的动画系统,称为:Property Animation(属性动画) 。
一、Frame Animation:(逐帧动画)
这个很好理解 , 一帧帧的播放图片,利用人眼视觉残留原理,给我们带来动画的感觉 。它的原理的GIF图片、电影播放原理一样 。
1.定义逐帧动画比较简单,只要在中使用子元素定义所有播放帧即可 。
(1) android:oneshot 设置是否仅播放一次
(2) android:drawable 设置每一帧图片
(3) android:duration 设置图片间切换间隔
2.习惯上把AnimationDrawable设置为ImageView的背景
android:background=@anim/frame_anim
然后我们就可以在java代码中获取AnimationDrawable对象了
AnimationDrawable anim = (AnimationDrawable)imageView.getBackground();
(需要注意的是,AnimationDrawable默认是不播放的,调用其start()方法开始播放,stop停止播放)
3.上面的动画文件是通过xml文件来配置的,如果你喜欢,也可以通过在java代码中创建AnimationDrawable对象,然后通过addFrame(Drawable frame, int duration)方法向动画添加帧 , 然后start() 。。。
二、Tween Animation:(补间动画)
补间动画就是我们只需指定开始、结束的“关键帧“,而变化中的其他帧由系统来计算,不必自己一帧帧的去定义 。
1. Android使用Animation代表抽象动画,包括四种子类:AlphaAnimation(透明度动画)、ScaleAnimation(缩放动画)、TranslateAnimation(位移动画)、RotateAnimation(透明度动画) 。Android里面允许在java中创建Animation类对象,但是一般都会采用动画资源文件来定义动画 , 把界面与逻辑分离
set android:interpolator="@android:anim/linear_interpolator" xmlns:android=""
!-- 定义透明度的变换 --
!-- 定义旋转变换 --
rotate android:duration="3000/" android:fromdegrees="0" android:pivotx="50%" android:pivoty="50%" android:todegrees="1800"
/rotate/alpha/set
(一个set可以同时定义多个动画,一起执行 。)
2. android:interpolator=@android:anim/linear_interpolator控制动画期间需要补入多少帧,简单来说就是控制动画速度,有些地方翻译为“插值“ 。Interpolator有几种实现类:LinearInterpolator、AccelerateInterpolator、AccelerateDecelerateInterpolator、CycleInterpolator、DecelerateInterpolator,具体使用可以参考官方API Demo 。
3. 定义好anim文件后,我们可以通过AnimationUtils工具类来加载它们,加载成功后返回一个Animation 。然后就可以通过View的startAnimation(anim)开始执行动画了 。
Animation anim = AnimationUtils.loadAnimation(this, R.anim.anim);
//设置动画结束后保留结束状态
anim.setFillAfter(true);
//设置插值效果
anim.setInterpolator(interpolator);
//对view执行动画
view. startAnimation(anim);
三、Property Animation:(属性动画)
属性动画,这个是在Android 3.0中才引进的 , 它可以直接更改我们对象的属性 。在上面提到的Tween Animation中 , 只是更改View的绘画效果而View的真实属性是不改变的 。假设你用Tween动画将一个Button从左边移到右边,无论你怎么点击移动后的Button,他都没有反应 。而当你点击移动前Button的位置时才有反应 , 因为Button的位置属性木有改变 。而Property Animation则可以直接改变View对象的属性值,这样可以让我们少做一些处理工作,提高效率与代码的可读性 。
(1)ValueAnimator:包含Property Animation动画的所有核心功能,如动画时间,开始、结束属性值,相应时间属性值计算方法等 。应用ValueAnimator有两个步骤
1计算属性值 。
2根据属性值执行相应的动作,如改变对象的某一属性 。
我们的主是第二步,需要实现ValueAnimator.onUpdateListener接口,这个接口只有一个函数onAnimationUpdate() , 将要改变View对象属性的事情在该接口中do 。
animation.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//do your work
}
});
(2)ObjectAnimator:继承自ValueAnimator,要指定一个对象及该对象的一个属性,当属性值计算完成时自动设置为该对象的相应属性,即完成了Property Animation的全部两步操作 。实际应用中一般都会用ObjectAnimator来改变某一对象的某一属性,但用ObjectAnimator有一定的限制,要想使用ObjectAnimator,应该满足以下条件:
1.对象应该有一个setter函数:set(驼峰命名法)
2如下面的例子,像ofFloat之类的工场方法,第一个参数为对象名 , 第二个为属性名,后面的参数为可变参数,如果values…参数只设置了一个值的话,那么会假定为目的值 , 属性值的变化范围为当前值到目的值,为了获得当前值,该对象要有相应属性的getter方法:get
3如果有getter方法,其应返回值类型应与相应的setter方法的参数类型一致 。
ObjectAnimator oa=ObjectAnimator.ofFloat(tv, alpha, 0f, 1f);
oa.setDuration(3000);
oa.start();
如果不满足上面的条件,我们只能乖乖的使用ValueAnimator来创建动画 。
(3)Animator.AnimatorListener:可以为Animator设置动画监听,需要重写下面四个方法 。
onAnimationStart()
onAnimationEnd()
onAnimationRepeat()
onAnimationCancel()
这里我们也可以实现AnimatorListenerAdapter,他的好处是可以只用定义想监听的事件而不用实现每个函数却只定义一空函数体 。如下:
anim.addListener(new AnimatorListenerAdapter() {
public void on AnimationEnd(Animator animation){
//do your work
}
});
(4)AnimationSet:可以组合多个动画共同工作
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(anim1).before(anim2);
bouncer.play(anim2).with(anim3);
bouncer.play(anim2).with(anim4)
bouncer.play(anim5).after(amin2);
animatorSet.start();
上面的代码意思是: 首先播放anim1;同时播放anim2,anim3,anim4;最后播放anim5 。
(5)TimeInterplator:与Tween中的interpolator类似 。有以下几种
AccelerateInterpolator加速 , 开始时慢中间加速
DecelerateInterpolator减速,开始时快然后减速
AccelerateDecelerateInterolator先加速后减速,开始结束时慢 , 中间加速
AnticipateInterpolator 反向 , 先向相反方向改变一段再加速播放
AnticipateOvershootInterpolator反向加回弹 , 先向相反方向改变,再加速播放,会超出目的值然后缓慢移动至目的值
BounceInterpolator跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90 , 100
CycleIinterpolator 循环 , 动画循环一定次数,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)
LinearInterpolator 线性,线性均匀改变
OvershottInterpolator 回弹,最后超出目的值然后缓慢改变到目的值
TimeInterpolator 一个接口 , 允许你自定义interpolator,以上几个都是实现了这个接口
(6)Keyframes:可以让我们定义除了开始和结束以外的关键帧 。KeyFrame是抽象类,要通过ofInt(),ofFloat(),ofObject()获得适当的KeyFrame,然后通过PropertyValuesHolder.ofKeyframe获得PropertyValuesHolder对象 , 如下:
Keyframe kf0 = Keyframe.ofInt(0, 400);
Keyframe kf1 = Keyframe.ofInt(0.25f, 200);
Keyframe kf2 = Keyframe.ofInt(0.5f, 400);
Keyframe kf4 = Keyframe.ofInt(0.75f, 100);
Keyframe kf3 = Keyframe.ofInt(1f, 500);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe(width, kf0, kf1, kf2, kf4, kf3);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(btn, pvhRotation);
上述代码的意思是:设置btn对象的width属性值使其:开始时 Width=400,动画开始1/4时 Width=200,动画开始1/2时 Width=400,动画开始3/4时 Width=100,动画结束时 Width=500 。
(7)ViewPropertyAnimator:对一个View同时改变多种属性 , 非常推荐用这种 。该类对多属性动画进行了优化,会合并一些invalidate()来减少刷新视图 。而且使用起来非常简便,但是要求API LEVEL 12,即Android 3.1以上 。仅需要一行代码即可完成水平、竖直移动
myView.animate().translationX(50f). translationY(100f);
(8)常需要改变的一些属性:
translationX,translationY: View相对于原始位置的偏移量
rotation,rotationX,rotationY: 旋转 , rotation用于2D旋转角度,3D中用到后两个
scaleX,scaleY: 缩放比
x,y: View的最终坐标 , 是View的left,top位置加上translationX,translationY
alpha: 透明度
四、最后自己总结一下这三种动画的优缺点:
(1)Frame Animation(帧动画)主要用于播放一帧帧准备好的图片,类似GIF图片,优点是使用简单方便、缺点是需要事先准备好每一帧图片;
(2)Tween Animation(补间动画)仅需定义开始与结束的关键帧,而变化的中间帧由系统补上,优点是不用准备每一?。?缺点是只改变了对象绘制,而没有改变View本身属性 。因此如果改变了按钮的位置,还是需要点击原来按钮所在位置才有效 。
(3)Property Animation(属性动画)是3.0后推出的动画,优点是使用简单、降低实现的复杂度、直接更改对象的属性、几乎可适用于任何对象而仅非View类,缺点是需要3.0以上的API支持,限制较大!但是目前国外有个开源库,可以提供低版本支持!
怎么用vector drawable实现帧动画1. 创建Vector Drawable
从相似角度来看,VectorDrawable与标准SVG图形都是利用path值绘制完成的 。不过如何利用SVG path绘制图形并不在本篇文章的探讨范围之内,大家可以点击此处从W3C网站处获取必要的说明资料 。在本文当中,我们只需要了解到path标签的作用是进行图形绘制即可 。让我们首先从SVG文件入手,看看以下图形是如何被绘制出来的:
这一图形共由五个主要部分所组成:
?一个圆角四边形作为CPU主体,该四边形由两条拱状弧线构成 。
?四组各自包含五根线条的图形,用于充当CPU的外延线路 。
虽然看起来有点繁杂,但大家其实用不着纠结于以上代码的具体含义 , 而且这完全不会影响到我们接下来要进行的VectorDrawable绘制工作 。不过需要强调的是,我将前面提到的五大图形组成部分在代码中作为独立的区块来处理,这是为了增强代码内容的可读性 。
首先,我们需要利用两条拱形弧线来绘制出圆角四边形,而在接下来的内容中我们会探讨如何分别表现出上、下、左、右四个方位的外延线条 。为了将上述SVG代码转化为VectorDrawable , 大家首先需要在XML当中定义vector对象 。以下代码提取自本篇文章示例代码当中的vector_drawable_cpu.xml文件 。
vector xmlns:android=""android:height="64dp"android:width="64dp"android:viewportHeight="600"android:viewportWidth="600"/vector
在此之后,大家可以向其中添加path数据 。下列代码同样被拆分成了五个不同的path标签而非将其作为整体处理,这当然也是为了保证内容的可读性 。
正如大家所见,每个path片段都只需要利用pathData属性进行绘制 。现在我们可以将VectorDrawable XML文件作为一个可绘制对象纳入到标准ImageView当中,而且其能够根据应用程序的实际需要任意进行尺寸缩放——完全不需要再修改任何Java代码 。
2. 为Vector Drawables添加动画效果
现在我们已经了解了如何以纯代码方式创建图形 , 接下来要做的是找点乐子——为其添加动画效果 。在以下动画中,大家会发现作为延伸线路的各组线条会不断指向并远离CPU本体进行移动 。
为了达到这一目标,大家需要将包含动画效果的每个片段包含在一个group标签当中 。
接下来,我们需要为每个动画类型创建animator文件 。在本次示例中,每组线路各使用一个animator,这就意味着共需要四个animator 。以下代码所示为上方线路的动画效果,大家还需要为下、左、右线路设定类似的效果 。每个animator XML文件都被包含在了本项目的示例代码当中 。
如大家所见,propertyName被设定为translateY,这意味着该动画将沿Y轴方向移动 。而valueFrom与valueTo则控制着位移的起点与终点 。通过将repeatMode设置为reverse而repeatCount设置为infinite , 整个动画会一直循环下去,其效果则在VectorDrawable处体现出来 。该动画的duration被设定为250,其时长单位为毫秒 。
为了将该动画应用到自己的可绘制文件当中 , 大家需要创建一个新的animated-vector XML文件,从而将这些animator分配给各VectorDrawable组 。以下代码的作用是创建该animated_cpu.xml文件 。
?xml version="1.0" encoding="utf-8"? animated-vector xmlns:android=""android:drawable="@drawable/vector_drawable_cpu"targetandroid:animation="@animator/pulse_top"android:name="top" /targetandroid:animation="@animator/pulse_right"android:name="right" /targetandroid:animation="@animator/pulse_left"android:name="left" /targetandroid:animation="@animator/pulse_bottom"android:name="bottom" / /animated-vector
当所有必要的XML文件都已经准备完成后,大家就可以将animated_cpu.xml加入到ImageView当中进行显示了 。
JAVA如何获取gif图片的帧数?用PS CS5/6打开gif图
(其他版本的PS,不能直接读出动图)
然后在“时间轴”处,选择“创建帧动画”
按住需要减少的帧,拖动到蓝色框内,就可以删除了
最后把图片保存下来,就行了
java 动画闪烁,怎么解决?代码有130来行,百度传不上,求高手留邮箱,我发 。我记得双缓存,就是画的时候在一张全新的Graphics上画 , 画好后直接覆盖就可以了 。好多年前的事情了,记不起来了 。
【java代码实现的帧动画 用java制作一个动画】java代码实现的帧动画的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于用java制作一个动画、java代码实现的帧动画的信息别忘了在本站进行查找喔 。

    推荐阅读