
ctx.clearRect(0, 0, canvas_size_x, canvas_size_y)
if (x_icon <0 || x_icon >canvas_size_x - size_x) {
stepX = -stepX
}
if (y_icon <0 || y_icon >canvas_size_y - size_y) {
stepY = -stepY
}
x_icon += stepX
y_icon += stepY
ctx.drawImage(anim_img, x_icon, y_icon)
}以上方法每隔一定时间清除画布内容,并且重新计算绘制图形位置,一旦超过了画布大小,则反转坐标绘制图形。
1、首先,重写控件View,自定义一个展示gif图的GifView,代码如下:package net.loonggg.gif.view
import net.loonggg.gif.R
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.TypedArray
import android.graphics.Canvas
import android.graphics.Movie
import android.os.Build
import android.util.AttributeSet
import android.view.View
public class GifView extends View {
/**
* 默认为1秒
*/
private static final int DEFAULT_MOVIE_DURATION = 1000
private int mMovieResourceId
private Movie mMovie
private long mMovieStart
private int mCurrentAnimationTime = 0
private float mLeft
private float mTop
private float mScale
private int mMeasuredMovieWidth
private int mMeasuredMovieHeight
private boolean mVisible = true
private volatile boolean mPaused = false
public GifView(Context context) {
this(context, null)
}
public GifView(Context context, AttributeSet attrs) {
this(context, attrs, R.styleable.CustomTheme_gifViewStyle)
}
public GifView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle)
setViewAttributes(context, attrs, defStyle)
}
@SuppressLint("NewApi")
private void setViewAttributes(Context context, AttributeSet attrs,
int defStyle) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null)
}
// 从描述文件中读出gif的值,创建出Movie实例
final TypedArray array = context.obtainStyledAttributes(attrs,
R.styleable.GifView, defStyle, R.style.Widget_GifView)
mMovieResourceId = array.getResourceId(R.styleable.GifView_gif, -1)
mPaused = array.getBoolean(R.styleable.GifView_paused, false)
array.recycle()
if (mMovieResourceId != -1) {
mMovie = Movie.decodeStream(getResources().openRawResource(
mMovieResourceId))
}
}
/**
* 设置gif图资源
*
* @param movieResId
*/
public void setMovieResource(int movieResId) {
this.mMovieResourceId = movieResId
mMovie = Movie.decodeStream(getResources().openRawResource(
mMovieResourceId))
requestLayout()
}
public void setMovie(Movie movie) {
this.mMovie = movie
requestLayout()
}
public Movie getMovie() {
return mMovie
}
public void setMovieTime(int time) {
mCurrentAnimationTime = time
invalidate()
}
/**
* 设置暂停
*
* @param paused
*/
public void setPaused(boolean paused) {
this.mPaused = paused
if (!paused) {
mMovieStart = android.os.SystemClock.uptimeMillis()
- mCurrentAnimationTime
}
invalidate()
}
/**
* 判断gif图是否停止了
*
* @return
*/
public boolean isPaused() {
return this.mPaused
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mMovie != null) {
int movieWidth = mMovie.width()
int movieHeight = mMovie.height()
int maximumWidth = MeasureSpec.getSize(widthMeasureSpec)
float scaleW = (float) movieWidth / (float) maximumWidth
mScale = 1f / scaleW
mMeasuredMovieWidth = maximumWidth
mMeasuredMovieHeight = (int) (movieHeight * mScale)
setMeasuredDimension(mMeasuredMovieWidth, mMeasuredMovieHeight)
} else {
setMeasuredDimension(getSuggestedMinimumWidth(),
getSuggestedMinimumHeight())
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b)
mLeft = (getWidth() - mMeasuredMovieWidth) / 2f
mTop = (getHeight() - mMeasuredMovieHeight) / 2f
mVisible = getVisibility() == View.VISIBLE
}
@Override
protected void onDraw(Canvas canvas) {
if (mMovie != null) {
if (!mPaused) {
updateAnimationTime()
drawMovieFrame(canvas)
invalidateView()
} else {
drawMovieFrame(canvas)
}
}
}
@SuppressLint("NewApi")
private void invalidateView() {
if (mVisible) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
postInvalidateOnAnimation()
} else {
invalidate()
}
}
}
private void updateAnimationTime() {
long now = android.os.SystemClock.uptimeMillis()
// 如果第一帧,记录起始时间
if (mMovieStart == 0) {
mMovieStart = now
}
// 取出动画的时长
int dur = mMovie.duration()
if (dur == 0) {
dur = DEFAULT_MOVIE_DURATION
}
// 算出需要显示第几帧
mCurrentAnimationTime = (int) ((now - mMovieStart) % dur)
}
private void drawMovieFrame(Canvas canvas) {
// 设置要显示的帧,绘制即可
mMovie.setTime(mCurrentAnimationTime)
canvas.save(Canvas.MATRIX_SAVE_FLAG)
canvas.scale(mScale, mScale)
mMovie.draw(canvas, mLeft / mScale, mTop / mScale)
canvas.restore()
}
@SuppressLint("NewApi")
@Override
public void onScreenStateChanged(int screenState) {
super.onScreenStateChanged(screenState)
mVisible = screenState == SCREEN_STATE_ON
invalidateView()
}
@SuppressLint("NewApi")
@Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility)
mVisible = visibility == View.VISIBLE
invalidateView()
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility)
mVisible = visibility == View.VISIBLE
invalidateView()
}
}
Movie其实管理着GIF动画中的多个帧,只需要通过 setTime() 一下就可以让它在draw()的时候绘出相应的那帧图像。通过当前时间与duration之间的换算关系,是很容易实现GIF动起来的效果。
其次,在xml布局文件中,把这个view定义进去,代码如下:
[html] view plain copy
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<net.loonggg.gif.view.GifView
android:id="@+id/gif1"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center_horizontal"
android:enabled="false" />
<net.loonggg.gif.view.GifView
android:id="@+id/gif2"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center_horizontal"
android:enabled="false" />
</LinearLayout>
2、最后,在MainActivity中的使用,代码如下:
package net.loonggg.gif
import net.loonggg.gif.view.GifView
import android.app.Activity
import android.os.Bundle
public class Gif extends Activity {
private GifView gif1, gif2
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
gif1 = (GifView) findViewById(R.id.gif1)
// 设置背景gif图片资源
gif1.setMovieResource(R.raw.kitty)
gif2 = (GifView) findViewById(R.id.gif2)
gif2.setMovieResource(R.raw.b)
// 设置暂停
// gif2.setPaused(true)
}
}
html5 canvas首屏自适应背景动画循环效果的插入方法:1、demo.html代码如下:
<html lang="en" class="no-js"><head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>html5 canvas首屏自适应背景动画循环效果代码</title>
<link rel="stylesheet" type="text/css" href="css/normalize.css">
<link rel="stylesheet" type="text/css" href="css/demo.css">
<!--必要样式-->
<link rel="stylesheet" type="text/css" href="css/component.css">
<!--[if IE]>
<script src="js/html5.js"></script>
<![endif]-->
</head>
<body>
<div class="container demo-1">
<div class="content">
<div id="large-header" class="large-header" style="height: 185px">
<canvas id="demo-canvas" width="1304" height="185"></canvas>
<h1 class="main-title">Connect <span class="thin">Three</span></h1>
</div>
<nav class="codrops-demos">
<a class="current-demo" href="index.html">Demo 1</a>
</nav>
</div>
</div><!-- /container -->
<script src="js/TweenLite.min.js"></script>
<script src="js/EasePack.min.js"></script>
<script src="js/rAF.js"></script>
<script src="js/demo-1.js"></script>
<div class="sogoutip" style="z-index: 2147483645visibility: hiddendisplay: none"></div><div class="sogoubottom" id="sougou_bottom" style="display: none"></div><div id="ext_stophi" style="z-index: 2147483647"><div class="extnoticebg"></div><div class="extnotice"><h2>关闭提示 <a href="#" title="关闭提示" id="closenotice" class="closenotice">关闭</a></h2><p id="sogouconfirmtxt"></p> <a id="sogouconfirm" href="#" class="extconfirm">确 认</a><a id="sogoucancel" href="#" class="extconfirm">取 消</a></div></div><div id="ext_overlay" class="ext_overlayBG" style="display: nonez-index: 2147483646"></div><iframe class="sogou_sugg_feedbackquan" frameborder="0" scrolling="no" src="http://ht.www.sogou.com/websearch/features/yun6.jsp?pid=sogou-brse-d2a452edff079ca6&w=1366&v=7400&st=1465483516429&od=6612&ls=1465482970132&lc=&lk=1463925952631&sd=72&cd=0&kd=0&u=1450532590172818&y=EC8B5B0919EDD514D2F1263AA4A58EF6&query=html5%20canvas%E9%A6%96%E5%B1%8F%E8%87%AA%E9%80%82%E5%BA%94%E8%83%8C%E6%99%AF%E5%8A%A8%E7%94%BB%E5%BE%AA%E7%8E%AF%E6%95%88%E6%9E%9C%E4%BB%A3%E7%A0%81|http%3A%2F%2Fwww.777moban.com%2FPreview%2F35_196%2Findex.html&r=http%3A%2F%2Fwww.777moban.com%2FPreview%2F35_196%2Findex2.html" style="border: nonedisplay: nonez-index: 2147483645background: transparent"></iframe><script src="http://pb.sogou.com/pv.gif?hintbl=-1&uigs_productid=webext&type=ext_sugg&uigs_t=1465483517392&lt=212&ie=0&v=7400&y=EC8B5B0919EDD514D2F1263AA4A58EF6&query=html5%20canvas%E9%A6%96%E5%B1%8F%E8%87%AA%E9%80%82%E5%BA%94%E8%83%8C%E6%99%AF%E5%8A%A8%E7%94%BB%E5%BE%AA%E7%8E%AF%E6%95%88%E6%9E%9C%E4%BB%A3%E7%A0%81|http%3A%2F%2Fwww.777moban.com%2FPreview%2F35_196%2Findex.html"></script>
</body>
</html>
2、css样式如下:
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:noneheight:0}[hidden]{display:none}html{font-family:sans-serif-ms-text-size-adjust:100%-webkit-text-size-adjust:100%}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2emmargin:0.67em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{-moz-box-sizing:content-boxbox-sizing:content-boxheight:0}mark{background:#ff0color:#000}code,kbd,pre,samp{font-family:monospace,seriffont-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%line-height:0position:relativevertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{border:1px solid #c0c0c0margin:0 2pxpadding:0.35em 0.625em 0.75em}legend{border:0padding:0}button,input,select,textarea{font-family:inheritfont-size:100%margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:buttoncursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-boxpadding:0}input[type="search"]{-webkit-appearance:textfield-moz-box-sizing:content-box-webkit-box-sizing:content-boxbox-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0padding:0}textarea{overflow:autovertical-align:top}table{border-collapse:collapseborder-spacing:0}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)