如何写有一个写纸使的动画很屌的动画

写一个动漫的简单剧本,要非常简单的那种
全部答案(共2个回答)
24.(宪兵队办公室)斋藤背对镜头。“报告太君,人带到了!”斋藤转过身,方昂首挺胸先走进,队长把潘拖过来甩在墙角。潘一眼看到斋藤,挣扎着想站起来:“斋藤,你这个...
搞笑剧本——唐僧收徒孙悟空大闹了天宫之后,被如来佛祖压在了五行山下, “biu”的一下,五百年过去了…
买小品光盘最快,或者找相关期刊,例如《幽默与笑话》,也可以去图书馆找找看以前的老艺术家的作品集。第一个方法最可行。具体符合要求的小品很难找啊,可以看看网上有没有...
参看弗洛伊德的书。俄狄浦斯情节可以吗?
答: 孩子爱看战争片是否会有暴力倾向 可以看看"大耳朵图图"之内的动画片吧
答: 罗密欧-朱丽叶梁山伯-祝英台西门庆-潘金莲杨宗保-穆桂英方渐鸿-孙柔嘉贾宝玉-林黛玉刘彻-卫子夫吕不韦-赵姬张生-崔莺莺许仙-白素珍猪八戒-高翠兰郭靖-黄蓉杨过...
大家还关注
确定举报此问题
举报原因(必选):
广告或垃圾信息
激进时政或意识形态话题
不雅词句或人身攻击
侵犯他人隐私
其它违法和不良信息
报告,这不是个问题
报告原因(必选):
这不是个问题
这个问题分类似乎错了
这个不是我熟悉的地区
相关问答:123456789101112131415android(14)
android进阶(2)
android知识点(12)
系列中其他文章:
文章中充满了很多很大的Gif图,请耐心等待加载或者刷新页面,谢谢~
本文有关源码在最下面的下载地址。
要写好一个动画,需要不少好帮手,利用好这些帮手,写一个屌屌的动画就事半功倍了。
好帮手一:图片素材&
一个酷炫的动画,尤其是原创的动画,必须要有一些好的图片素材,而且这些素材地位举足轻重。当然这些都是UI射鸡师需要做的,所以快去催图吧!
好帮手二:Canvas和Paint&
关于这个帮手比较详细的分析可以看看这个系列的文章
Canvas就是画布的意思,没有画布肯定画不出任何东西,所以Canvas是绘制动画的基础,而且它提供了许多极其伟大的api,让我们绘制东西十分方便。Paint可以理解是画笔,它不是普通的画笔,而是一个有七十二变的画笔,想它变粗,变细,变红,变绿,怎样都行,可谓是“屌中之王”。
相信大家对于Canvas和Paint有哪些基础的api(如drawPath,drawRect等等)都十分熟悉,所以一些基础的用法就不介绍。我会详细说说一些比较重要的小帮手api。
小帮手1、Shader类&
Shader是着色器的意思,它提供了五个子类的Shader来渲染图像,分别是BitmapShader(图片渲染)、ComposeShader(混合渲染)、LinearGradient(线性渐变渲染)、RadialGradient(环形渐变渲染)以及SweepGradient(梯度渐变渲染);
a、BitmapShader可以用一张图片作为纹理,然后绘制的时候,就会用这张图片填充要绘制的区域:
//加载图像资源
mBitmap = ((BitmapDrawable) getResources().
getDrawable(R.drawable.snow)).getBitmap()
//创建Bitmap渲染对象
mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT,
Shader.TileMode.MIRROR)
public void onDraw(Canvas canvas) {
super.onDraw(canvas)
//绘制Bitmap渲染的椭圆
mPaint.setShader(mBitmapShader)
canvas.drawOval(new RectF(90, 20, 90+mBitmap.getWidth(),
20+mBitmap.getHeight()), mPaint)
b、LinearGradient,RadialGradient,SweepGradient则可以让不同颜色按照不同的规律渐变,例如线性渐变,或者环形渐变等等,
//创建线性渲染对象
int mColorLinear[] = {Color.RED, Color.GREEN, Color.BLUE, Color.WHITE}
mLinearGradient = new LinearGradient(0, 0, 100, 100, mColorLinear, null,
Shader.TileMode.REPEAT)
//创建环形渲染对象
int mColorRadial[] = {Color.GREEN, Color.RED, Color.BLUE, Color.WHITE}
mRadialGradient = new RadialGradient(350, 325, 75, mColorRadial, null,
Shader.TileMode.REPEAT)
//创建梯形渲染对象
int mColorSweep[] = {Color.GREEN, Color.RED, Color.BLUE, Color.YELLOW, Color.GREEN}
mSweepGradient = new SweepGradient(370, 495, mColorSweep, null)
//绘制线性渐变的矩形
mPaint.setShader(mLinearGradient)
canvas.drawRect(10, 250, 250, 400, mPaint)
//绘制环形渐变的圆
mPaint.setShader(mRadialGradient)
canvas.drawCircle(350, 325, 75, mPaint)
//绘制梯形渐变的矩形
mPaint.setShader(mSweepGradient)
canvas.drawRect(270, 420, 470, 570, mPaint)
c.ComposeShader混合渲染其作用就是把两个Shader效果按一定规则组合,这点跟下面将要介绍的Xfermode是一样的,请往下看。
绘制出来的结果如下图:&
关于Shader更详细的用法可看
小帮手2、PorterDuff.Mode / Xfermode&
这个也是一个极其凶残的帮手,它的作用就是将不同的图像按照一定要求混合成一个图像。官方的ApiDemos工程也有专门介绍该类的使用方法,下面的ApiDemos的截图:
为何说它凶残?因为它能做到的事实在太屌了。请看上图,其中src,dst分别是两张图片,后面的效果就是将这两张图片按照一定规则组合起来的效果。&
注意一点:只有有像素值的地方才会被组合出来,透明处是组合一起就是透明。这个也是该接口最重要的地方。
来看看一个效果:&
像上图中部分字被染成红色了,但染的的方法并不是工整的一定字数,这种效果用Xfermode就可以轻易的做到了。请看下图:
假设src就是层下黑色的文字,而dst是上面红色的圆,那么按照DST_IN组合在一起之后就可以得到被染成红色部分的字了。&
关于这个可以看看我另一篇:
如果想详细了解Xfermode,可以看看此文章:
小帮手3、saveLayer()方法&
saveLayer是Canvas里的一个api,我们接触最多的是save这个接口,两者有什么区别呢?&
我们看看源码对两者的注释:
* Saves the current matrix and clip onto a private stack.
* Subsequent calls to translate,scale,rotate,skew,concat or clipRect,
* clipPath will all operate as usual, but when the balancing call to
* restore() is made, those calls will be forgotten, and the settings that
* existed before the save() will be reinstated.
* @return The value to pass to restoreToCount() to balance this save()
public int save() {
return native_save(mNativeCanvasWrapper, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
* This behaves the same as save(), but in addition it allocates and
* redirects drawing to an offscreen bitmap.
* &p class=&note&&&strong&Note:&/strong& this method is very expensive,
* incurring more than double rendering cost for contained content. Avoid
* using this method, especially if the bounds provided are large, or if
* the {@link
* {@code saveFlags} parameter. It is recommended to use a
* {@link android.view.View
* to apply an xfermode, color filter, or alpha, as it will perform much
* better than this method.
* All drawing calls are directed to a newly allocated offscreen bitmap.
* Only when the balancing call to restore() is made, is that offscreen
* buffer drawn back to the current target of the Canvas (either the
* screen, it's target Bitmap, or the previous layer).
* Attributes of the Paint - {@link Paint
* {@link Paint
* {@link Paint
* offscreen bitmap is drawn back when restore() is called.
* @param bounds May be null. The maximum size the offscreen bitmap
needs to be (in local coordinates)
* @param paint
This is copied, and is applied to the offscreen when
restore() is called.
* @param saveFlags see _SAVE_FLAG constants, generally {@link
for performance reasons.
value to pass to restoreToCount() to balance this save()
public int saveLayer(@Nullable RectF bounds, @Nullable Paint paint, @Saveflags int saveFlags) {
if (bounds == null) {
bounds = new RectF(getClipBounds());
return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
save方法可以保存当前的matrix and clip,并且在restore把它恢复,一些平移,旋转,缩放等操作都会影响Canvas的matrix,所以save操作一般可以保存这些信息以及clip信息;
而saveLayer则强大很多,它相当于另外起一张干净图层,并在上面进行绘制操作,然后在restoreToCount的时候,把刚才所绘制的重新绘制在原本的Canvas上。当时正如所知的那样,它会绘制两次,所以消耗是十分巨大。
具体分析可以看看我另一篇文章:
小帮手4、clipXXXX,裁剪区域的api和drawPath&
在Canvas中以“clip”开头的api都是代表裁剪区域,在调用该方法后,canvas可绘制的区域就剩下clip出来的区域,例如:
protected void onDraw(Canvas canvas) {
canvas.clipRect(100, 100, 300, 300);
canvas.drawColor(Color.GREEN);
上述代码裁剪了一个坐标为(100,100,300,300)的正方形,并且为该区域绘制绿色,结果如下:&
clip开头的还有clipPath和clipRegion,一个用来裁剪Path路径包围的区域,另一个则裁剪Region类定义区域,两者都身材绝技。但是要注意,clipPath方法有兼容性问题,应该说是Android的一个bug,在旧版(貌似是4.3以下)clipPath绘制的效果是有问题的,要关闭硬件加速才能正常。所以,如果条件允许下,我一般使用drawPath作为代替方案,只是drawPath可以实现的效果有限,自行取舍吧。
小帮手5、ColorFilter&
大神ColorFilter终于来了,它有多牛逼?给你看几个图就知道:&
第一张是原图,下面两张都是设置ColorFilter后画出来的效果。太不可思议了!&
ColorFilter有三个子类,分别是ColorMatrixColorFilter、LightingColorFilter和PorterDuffColorFilter,关于它们具体可以详细看看这篇文章:,有时间一定要看看。
熟悉使用上面几个小帮手,已经可以足够绘制出十分惊艳的效果了。
好帮手三、数学,高等输血,函数,各种含树等&
虽然很多人都讨厌数学,但是数学真的很重要,数学很重要,数学很重要!事实上,很多动画插值器(Interpolator)就是用各种函数计算插值的。
先来看看一个简单的动画例子:
看看这魔性的滑动,看似混乱,但是也好有节奏感。可能一时间会觉得这个动画有点复杂,因为不知道要怎么实现。&
其实实现起来不难,简单分析就知道了。如果把每一条方块单独来看,你会发现其实每一条的运动轨迹是一模一样的,只是开始运动的时间有快有慢而已。所以,我们只要实现其中一条方块的运动,就足够了。&
但是它是按照什么规律运动呢?看着像是普通的匀速地上下滑动而已,是这样吗?我写一个出来就知道,下面是效果图:
两者实现上固然有一定差异,但是后者无论怎样实现,出来的效果都无法达到前者的平滑,因为后者是匀速滑动,而前者是用了sin函数计算滑动值。
如果仔细看,前者的效果本身就是一个sin函数图像。这就是数学的魅力,做出来的效果会有一种觉得屌屌的感觉。这只是sin函数,我再换换别的函数:&
运动轨迹很诡异吧?这个是我随意写一个函数做成的,虽然诡异,但是效果不错,可以尝试把各种函数带进去试试效果,相信会有很多非常酷炫的效果。
还有一个家伙不得不说,那就是“贝塞尔曲线”。它经常被用来做各种动画的效果,例如水流波动的效果,请看看这篇文章,看完你会爱上这个曲线。
看看效果图:
下一节我将用一个实践的例子--高仿手机管家火箭的动画,具体介绍如何一步一步写一个动画出来。
http://download.csdn.net/detail/scnuxisan225/9389457
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:21026次
排名:千里之外
评论:14条
(3)(4)(3)(2)(2)(1)(1)&!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&
&html xmlns="http://www.w3.org/1999/xhtml"&
&meta http-equiv="Content-Type" content="text/ charset=utf-8" /&
&title&轨迹&/title&
var speed = [1, 1]; //初始位移值:[水平,垂直]
var speedMax = 5; //最大位移值
var length = 1; //位移系数
var boxSpace = [50, 50, 500, 300]; //画布参数:[起始点水平位置,起始点垂直位置,宽度,高度]
var item = [200, 150, 50, 50]; //控件参数:[起始点水平位置,起始点垂直位置,宽度,高度]
var millisec = 5; //执行周期间隔,单位:毫秒
var playFlag = true; //初始状态:播放/停止
function init(){
//初始化控制栏
var styleBar = $("bar").
styleBar.left = boxSpace[0] + "px";
styleBar.width = boxSpace[2] + "px";
//初始化画布
var styleBox = $("box").
styleBox.left = boxSpace[0] + "px";
styleBox.top = boxSpace[1] + "px";
styleBox.width = boxSpace[2] + "px";
styleBox.height = boxSpace[3] + "px";
//初始化控件
var styleClk = $("clk").
styleClk.left = item[0] + "px";
styleClk.top = item[1] + "px";
styleClk.width = item[2] + "px";
styleClk.height = item[3] + "px";
//注册控件鼠标事件
$("clk").onmouseover =
$("clk").onmouseout =
//注册控制栏事件
$("btnPlay").onclick =
$("btnStop").onclick =
//默认播放或停止
if(playFlag) play();
function play(){
playFlag = true;
autoMove();
function stop(){
playFlag = false;
//返回Dom对象
function $(elmId){
return document.getElementById(elmId);
//生成随机数
function randomNum(min, max){
var Range = max -
var Rand = Math.random();
return(min + Math.round(Rand * Range));
//动画逻辑
function autoMove(){
//生成本次位移量
var xBool = randomNum(0, 100) & 50 ? 1 : -1; //水平位移趋势,1:向右,-1:向左
var yBool = randomNum(0, 100) & 50 ? 1 : -1; //垂直位移趋势,1:向下,-1:向上
speed[0] += xBool * //在原来水平位移量的基础上,加入趋势影响
speed[1] += yBool * //在原来垂直位移量的基础上,加入趋势影响
//处理本次位移量是否已经超过最大值
if(speed[0] & -1 * speedMax) speed[0] = -1 * speedM //水平位移量不允许超过最大值
if(speed[0] & speedMax) speed[0] = speedM //水平位移量不允许超过最大值
if(speed[1] & -1 * speedMax) speed[1] = -1 * speedM //垂直位移量不允许超过最大值
if(speed[1] & speedMax) speed[1] = speedM //垂直位移量不允许超过最大值
//允许控件活动的画布坐标范围
var leftLimit = boxSpace[0];
var topLimit = boxSpace[1];
var rightLimit = boxSpace[0] + boxSpace[2] - item[2];
var bottomLimit = boxSpace[1] + boxSpace[3] - item[3];
//当前控件坐标位置
var xNow = parseInt($("clk").style.left);
var yNow = parseInt($("clk").style.top);
//对控件活动超出范围时进行反弹处理
if((xNow + speed[0]) & leftLimit || (xNow + speed[0]) & rightLimit) speed[0] *= -1;
if((yNow + speed[1]) & topLimit || (yNow + speed[1]) & bottomLimit) speed[1] *= -1;
//重新设定控件坐标,形成动画
$("clk").style.left = xNow + speed[0] + "px";
$("clk").style.top = yNow + speed[1] + "px";
//调用下一次动画逻辑
if(playFlag) setTimeout(autoMove, millisec);
window.onload =
#bar { position: absolute; background: #F5F1C2; border: 1px solid #996600; z-index: 30; text-align: center; line-height:26px; height:30px; top: 20px }
#bar a { color: #FFF; font-size: 10pt; margin: 2px 2px; display: block; width: 80px; height: 26px; background: #7C7514; float: left; text-decoration:none}
#bar a:hover { background:#C00; }
#box { position: absolute; background: #FFFFCC; border: 1px solid #996600; z-index: 10 }
#clk { position: absolute; cursor:pointer; background: #000000; color: #FFF; text-align: center; line-height:50px; z-index: 20 }
&div id="bar"&&a href="#" id="btnPlay"&播放&/a&&a href="#" id="btnStop"&停止&/a&&/div&
&div id="box"&&/div&
&div id="clk"&点这&/div&
没有任何美感的运行效果:
阅读(...) 评论()}

我要回帖

更多关于 如何写动画脚本 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信