HTML5 Canvas动画实例

news2024/11/19 6:41:06

 在开发在线游戏时,绘制动画是非常重要的。本文介绍一个使用Canvas API实现的动画实例——游戏人物的跑步动画。

01、动画的概念及原理

1、动画

动画是通过一幅幅静止的、内容不同的画面(即帧)快速播放来呈现的,使人们在视觉上产生动的感觉。这是利用了人类眼睛的视觉暂留原理。利用人的这种生理特性可制作出具有高度想象力和表现力的动画影片。

2. 原理

人们在看画面时,画面会在大脑视觉神经中停留大约1/24秒,如果每秒更替24个画面或更多,那么前一个画面还没在人脑中消失之前,下一个画面进入人脑,人们就会觉得画面动起来了,它的基本原理与电影、电视一样,都是视觉原理。

在计算机上要实现动画效果,除了绘图外,还需要解决下面两个问题。

(1) 定期绘图,也就是每隔一段时间就调用绘图函数进行绘图。动画是通过多次绘图实现的,一次绘图只能实现静态图像。

可以使用setInterval()函数设置一个定时器,语法如下:

setInterval(函数名,时间间隔)

时间间隔的单位是毫秒(ms),每经过指定的时间间隔系统都会自动调用指定的函数完成绘画。

(2) 清除先前绘制的所有图形。物体已经移动开来,可原来的位置上还保留先前绘制的图形,这样当然不行。解决这个问题最简单的方法是使用clearRect(x, y, width, height)方法清除画布中指定区域的内容。

图1是一个方向(一般都是4个方向)的跑步动作序列图。假如想获取一个姿态的位图,可利用Canvas的上下文2D对象的drawImage(image, sourceX, sourceY, sourceWidth,sourceHeight,destX,destY,destWidth,destHeight)方法将源位图上某个区域(sourceX,sourceY,sourceWidth,sourceHeight)复制到目标区域的(destX,destY)坐标处,显示大小为(destWidth,destHeight)。

 

■ 图1 一个方向的跑步动作序列

【例1】实现从跑步动作序列Snap1.jpg文件中截取的第3个动作(帧)。

分析:在Snap1.jpg文件中,每个人物动作的大小为60×80px,所以截取源位图的sourceX=120,sourceY=0,sourceWidth=60,sourceHeight=80就是第3个动作(帧)。

<canvas id="myCanvas" height=250 width=250>您的浏览器不支持 canvas。</canvas>
<script type="text/javascript">
function draw()
{
  var canvas=document.getElementById("myCanvas"); // 获取网页中的canvas对象
  var ctx = canvas.getContext("2d"); //获取canvas对象的上下文
  var imageObj = new Image(); // 创建图像对象
  imageObj.src = "Snap1.jpg";
  imageObj.onload = function(){
      //从原图(120, 0)位置开始截取中间一块宽60*高80的区域,原大小显示在屏幕(0,0)处
      ctx.drawImage(imageObj, 120, 0, 60, 80, 0, 0, 60, 80);
     };
}
window.addEventListener("load", draw, true);
</script>

 例1的运行结果如图2所示,在页面上仅仅显示第3个动作。

 ■ 图2 静态显示第3个动作

02、游戏人物的跑步动画

【例2】实现游戏人物的跑步动画。

首先定义一个Canvas元素,画布的长度和宽度都是300px,代码如下:

<!DOCTYPE html>
<html>
  <head>
    <title>HTML5 Canvas实现游戏人物的跑步动画</title>
  </head>
  <body>
    <canvas id="myCanvas" width="300" height="300"></canvas>
  </body>
</html>

 在JavaScript代码中定义一个Image对象,用于显示Snap1.jpg。然后定义一个init()函数,初始化Image对象,并设置定时器,代码如下:

<script type="text/javascript"> 
    var imageObj = new Image(); // 创建图像对象
    var x =300;
    var n =0; // 计数器
    function init(){
      imageObj.src = 'Snap1.jpg';
      imageObj.onload = function(){
         setInterval(draw,100);// 定时器,每0.1秒执行一次draw()函数
      };
// 此处省略draw()函数的代码
   window.addEventListener("load", init, true);
  </script>

 

使用了定时器,每隔100毫秒就会在Snap1.jpg图片截取一张60×80px大小的小图并绘制出来,且每次向左移15px,直到最左端时重新从右侧开始,不停循环,就可见游戏人物在屏幕上不停地奔跑。

下面分析draw()函数的实现。例5-14中仅仅显示人物的第三个动作,而为了实现动画,需要clearRect(x,y,width,height)不断清除先前绘制的动作图形,再绘制后续的动作。所以需要一个计数器n,记录当前绘制到第几动作(帧)了。

function draw()
    {
        var canvas=document.getElementById("myCanvas"); // 获取网页中的canvas对象
        var ctx = canvas.getContext("2d"); //获取canvas对象的上下文
           ctx.clearRect(0,0,300,300); // 清除canvas画布
           //从原图(60*n)位置开始截取中间一块宽60*高80的区域,显示在屏幕(x,0)处
           ctx.drawImage(imageObj, 60*n, 0, 60, 80, x, 0, 60, 80);
           if(n>=8){
              n=0;
           }else{
              n++;
           }
           if(x>=0){
              x=x-30; //前移30像素
           }else{
              x=300; //回到右侧
           }
    }

 例2的运行结果是一个游戏人物不停且重复地从右侧跑到左侧的动画。

03、雪花飘落动画

在HTML5中制作雪花飘落动画,需要使用Canvas画圆arc(x,y,r,start,stop)以构成圆形雪花;网页加载时,需要生成一定数量(如200个)的不同半径及位置的雪花,故半径、坐标为随机数;雪花在飘落过程中,其半径不变,坐标在一定幅度内变化。

制作雪花飘落动画,首先产生一个画布Canvas。

<script type="text/javascript"> 
        var canvas=document.getElementById("myCanvas")
        var context = canvas.getContext("2d"); //2d即指二维平面
        var w =window.innerWidth
        var h =window.innerHeight
        canvas.width = w;
        canvas.height =h;

 

然后再生成200个雪花的对象组。当生成雪花时,每个雪花半径、位置都不同。如果把每个雪花当成一个对象,那么这个对象的属性就包含半径、坐标(X、Y)。一个雪花对象可以写成var snowOject={x: 1,y: 10,r: 5},代表一个坐标为(1,10)、半径为5的圆形雪花。

注意/

本示例中由于半径和坐标都为随机数,故使用Math.random()方法分别为200个雪花生成半径、坐标(X、Y);动画有200个雪花,所以为了方便后面操作,就用一个数组保存这200个雪花对象。

var count =200 //雪花的个数
        var snows=[] //雪花对象数组
        for (var i=0 ; i< count;i++){
            snows.push({
                x:Math.random()*w, //Math.random()用于生成0~1的随机数
                y:Math.random()*h,
                r:Math.random()*5,
            })
        }

 在绘制时设置雪花的样式。

function draw(){
            context.clearRect(0,0,w,h)
            context.beginPath()
            for(var i=0; i<count;i++){
                var snow = snows[i];
                context.fillStyle ="rgb(255,255,255)" //设置雪花的样式
                context.shadowBlur=10;
                context.shadowColor="rgb(255,255,255)";
                //moveTo 移动到指定的坐标
                context.moveTo(snow.x,snow.y);
                // 使用canvas arc()创建一个圆形
                 //x,y,r:圆的中心的x坐标和y坐标,r为半径
                //0,Math.PI * 2起始弧度和结束弧度
                context.arc(snow.x,snow.y,snow.r,0,Math.PI * 2);
            }
            context.fill(); //画布填充
            move();
        }

 move()函数让雪花它们飘动起来,就是雪花不停地移动位置。超出页面则重新设置位置和雪花大小。

function move(){
            for (var i=0;i<count;i++){
                var snow =snows[i];
                snow.y +=(7-snow.r)/10 //从上往下飘落
                snow.x+=((5-snow.r)/10)//从左到右飘落
                if(snow.y>h){
                    snows[i]={
                        x:Math.random()*w,
                        y:Math.random()*h,
                        r:Math.random()*5,
                    }
                }
            }
        }

 最后设置刷新频率。

setInterval(draw,10); //每10毫秒刷新一次
    </script>

 页面中定义一个Canvas元素,画布的长度和宽度都是300px。

<body>
    <canvas id="myCanvas" height=500 width=500 class="my">您的浏览器不支持 canvas。</canvas>
</body>

 例子的运行结果如图3所示。

 ■ 图3 雪花飘落

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/694505.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何让VSCode不生成 tempcoderunnerfile.py

原因 runcode插件默认包含执行选中文本功能&#xff0c;当运行程序时会优先执行光标选中的代码并生成temp文件 解决方法 方法一&#xff1a;删除生成文件 在setting.json中添加 "code-runner.executorMap": {"php": "php $fullFileName &&am…

【Linux】Ubuntu20.04使用xrdp远程桌面时,gnome桌面环境没有最小化、任务栏等问题

一、问题背景 如下图所示&#xff0c;终端窗口没有最小化&#xff0c;因此只能关闭或移到一边去。 二、解决办法 在安装任何扩展前&#xff0c;需要将xrdp的桌面尽量向原生桌面靠拢。 在~/.xsessionrc配置文件中添加下面三行。 export GNOME_SHELL_SESSION_MODEubuntu ex…

Mediapipe 人像分割;实时更换背景;人脸添加特效

参考&#xff1a; https://zhuanlan.zhihu.com/p/476351994 1、Mediapipe 人像分割 import cv2 import mediapipe as mp import numpy as np mp_drawing mp.solutions.drawing_utils mp_selfie_segmentation mp.solutions.selfie_segmentation # 图片人物抠图: IMAGE_FILES…

idea生成serialVersionUID序列号

设置idea file->settings,搜索serialVersionUID&#xff0c;勾选框起来的两项 实体类实现Serializable接口 Data public class User implements Serializable { }鼠标放到类名上 点击提示的uid 生成的uid 结束&#xff01; hy:17 生活是一面镜子&#xff0c;给予我们…

springboot 停车场管理系统-计算机毕设 附源码82061

springboot 停车场管理系统 2023年5月 摘要 由于数据库和数据仓库技术的快速发展&#xff0c;停车场管理系统建设越来越向模块化、智能化、自我服务和管理科学化的方向发展。停车场管理系统对处理对象和服务对象&#xff0c;自身的系统结构&#xff0c;处理能力&#xff0c;都…

GO 基本配置

其他 IDEA 配置go语言环境 https://blog.csdn.net/weixin_45719444/article/details/121726325 关于IDEA的 plugins下找不到GO插件 点击安装 安装插件 Go 安装插件 Generate struct tags for golang

Flink CDC 2.4 正式发布,新增 Vitess 数据源,更多连接器支持增量快照,升级 Debezium 版本...

01 Flink CDC 简介 Flink CDC [1] 是基于数据库的日志 CDC 技术&#xff0c;实现了全增量一体化读取的数据集成框架。配合 Flink 优秀的管道能力和丰富的上下游生态&#xff0c;Flink CDC 可以高效实现海量数据的实时集成。 作为新一代的实时数据集成框架&#xff0c;Flink CDC…

二进制搭建Kubernetes集群(三)——部署多master

本文将完成多master集群的部署&#xff0c;即部署master02&#xff0c;以及nginx负载均衡、keepalived高可用 多master集群架构图&#xff1a; 架构说明&#xff1a; node节点的kubelet只能对接一个master节点的apiserver&#xff0c;不可能同时对接多个master节点的apiserver…

【Solr】中文分词配置

提示&#xff1a;在设置中文分词前需确保已经生成过core&#xff0c;未生成core的可以使用&#xff1a;solr create -c "自定义名称"进行定义。 未分词前的效果预览&#xff1a; 下载分词器&#xff1a; 下载地址: https://mvnrepository.com/artifact/com.github.m…

山西电力市场日前价格预测【2023-06-29】

日前价格预测 预测明日&#xff08;2023-06-29&#xff09;山西电力市场全天平均日前电价为407.26元/MWh。其中&#xff0c;最高日前价格为539.37元/MWh&#xff0c;预计出现在21: 15。最低日前电价为312.43元/MWh&#xff0c;预计出现在13: 00。以上预测仅供学习参考&#xff…

Java调用ssl异常,javax.net.ssl.SSLHandshakeException: No appropriate protocol

现象&#xff1a;sqlserver 2017 安装在docker里&#xff0c;系统是mac 13&#xff0c;java 1.8.371运行java程序提示上面ssl错误&#xff0c;根据百度提供的方法&#xff0c;修改文件&#xff0c;重启程序搞定。 解决办法&#xff1a;java.security 找到这个文件修改保存 发…

RPC(Remote Procedure Call)学习

目录 一、概念 二、RPC 调用基本流程 一、概念 RPC 全称是 Remote Procedure Call &#xff08;远程过程调用&#xff09;&#xff0c;它是一种通过网络从远程计算机程序上请求服务&#xff0c;可以提供终结点映射程序以及RPC服务&#xff0c;而不需要了解底层网络技术的协议…

三位数字显示电容测试表

广大电子爱好者都有这样的体会&#xff0c;中、高档数字万用表虽有电容测试挡位&#xff0c;但测量范围一般仅为 1pF~20F&#xff0c;往往不能满足使用者的需要&#xff0c;给电容测量带来不便。本电路介绍的三位数显示电容测试表采用四块集成电路&#xff0c;电路简洁、容易制…

element-ui中el-table设置固定高度后,底部合计栏被遮盖

如图: 解决办法:el-table加上ref"summaryTab",然后在自定义合计计算方法getSummaries中加上如下代码就ok了 this.$nextTick(() > {this.$refs.summaryTab.doLayout(); }); 没用使用自定义合计计算函数的,也可以写在updated中,如下: updated() {this.$nextTick((…

关于ipad:无法验证服务器身份

ipad 连接网络后&#xff0c;有时候会冒出这个弹窗&#xff0c;并且关掉后仍继续弹出 可以尝试以下几种方法&#xff1a;&#xff08;我是用③解决的&#xff09; ①. 确保你的iPad连接的是稳定的网络。有时候网络连接不稳定会导致无法验证服务器身份。 我们学校这个校园网…

Karl Guttag评Vision Pro(三):为什么飞机上VR观影体验不佳?

在过去25年里&#xff0c;AR/VR头显显示技术得到长足发展&#xff0c;采用的屏幕规格越来越高。据早前报告预测&#xff0c;VR头显安装基数会在2023年达到约2500万台。尽管如此&#xff0c;相比于无处不在的手机&#xff0c;我们几乎看不到周围有人随身携带AR/VR头显&#xff0…

APP为什么没有被小程序取代呢?

在科技行业日新月异的发展下&#xff0c;一直存在一种声音&#xff0c;认为小程序将逐步取代APP。然而&#xff0c;事实却并非如此。APP至今仍然以其独特的优势&#xff0c;坚挺地存在于市场之中。这是为何呢&#xff1f;以下是我们对此的几点考察。 首先&#xff0c;APP在功能…

「RPA中国杯 · 第五届RPA极客挑战赛」成功举办及获奖名单公示

2023年6月26日&#xff0c;「RPA中国杯 第五届RPA极客挑战赛」在苏州国际博览中心圆满结束。本次挑战赛由RPA中国和全球人工智能产品应用博览会主办&#xff0c;容智信息、金智维、弘玑Cyclone、UiPath联合主办&#xff0c;centific、中投创展协办。 RPA已经成为提高企业生产…

uniapp 详细封装缓存定时过期方法,详细使用过程

最近在开发一个uniapp的项目&#xff0c;中间我们需要给缓存定时&#xff0c;为了解决这个问题&#xff0c;封装了一个方法用来解决这个问题&#xff0c;当时遇到这个问题是因为在项目中要给阿里的OSS上传文件&#xff0c;上传之间先要向服务端请求获取授权&#xff0c;授权我们…

3、动手学深度学习——多层感知机:多层感知机的实现(从零实现+内置函数实现)

1、多层感知机基础知识 1. 简述 加入隐藏层和激活函数&#xff0c;可以将线性模型变成非线性模型&#xff0c;引入了非线性拟合能力。 我们通过在网络中加入一个或多个隐藏层来克服线性模型的限制&#xff0c;使其能处理更普遍的函数关系类型。要做到这一点&#xff0c;最简…