Canvas动画(PC端 移动端)

一,介绍与需求

1.1,介绍

canvas是HTML5中新增一个HTML5标签与操作canvas的javascript API,它可以实现在网页中完成动态的2D与3D图像技术。<canvas> 标记和 SVG以及 VML 之间的一个重要的不同是,<canvas> 有一个基于 JavaScript 的绘图 API,而 SVG 和 VML 使用一个 XML 文档来描述绘图。SVG 绘图很容易编辑与生成,但功能明显要弱一些。canvas可以完成动画、游戏、图表、图像处理等原来需要Flash完成的一些功能

1.2,需求

实现特殊的动画效果

二,动画实现

以跟随鼠标/手指移动的火为例

第一步:创建Canvas标签

 <canvas id="fire"></canvas>

第二步:获取Canvas标签

  let canvas = document.getElementById('fire');
if (canvas.getContext){
var ctx = canvas.getContext('2d');
// drawing code here
} else {
alert("不支持Canvas")
}

第三步:绘制火花

 var Spark = function (mouse) {

             this.cx = mouse.x;
this.cy = mouse.y;
this.x = rand(this.cx - 40, this.cx + 40);
this.y = rand(this.cy, this.cy + 5);
this.lx = this.x;
this.ly = this.y;
this.vy = rand(1, 3);
this.vx = rand(-4, 4);
this.r = rand(0, 1);
this.life = rand(4, 5);
this.alive = true;
this.c = { h: Math.floor(rand(2, 40)),
s: 100,
l: rand(40, 100),
a: rand(0.8, 0.9) } }
Spark.prototype.update = function () { this.lx = this.x;
this.ly = this.y; this.y -= this.vy;
this.x += this.vx; if (this.x < this.cx)
this.vx += 0.2;
else
this.vx -= 0.2; this.vy += 0.08;
this.life -= 0.1; if (this.life <= 0) { this.c.a -= 0.05; if (this.c.a <= 0)
this.alive = false; } }
Spark.prototype.draw = function (ctx) { ctx.beginPath();
ctx.moveTo(this.lx, this.ly);
ctx.lineTo(this.x, this.y);
ctx.strokeStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + (this.c.a / 2) + ")";
ctx.lineWidth = this.r * 2;
ctx.lineCap = 'round';
ctx.stroke();
ctx.closePath(); ctx.beginPath();
ctx.moveTo(this.lx, this.ly);
ctx.lineTo(this.x, this.y);
ctx.strokeStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + this.c.a + ")";
ctx.lineWidth = this.r;
ctx.stroke();
ctx.closePath(); }

第四步:绘制火焰

     var Flame = function (mouse) {

             this.cx = mouse.x;
this.cy = mouse.y;
this.x = rand(this.cx - 25, this.cx + 25);
this.y = rand(this.cy - 5, this.cy + 5);
this.vy = rand(1, 3);
this.vx = rand(-1, 1);
this.r = rand(20, 30);
this.life = rand(3, 6);
this.alive = true;
this.c = { h: Math.floor(rand(2, 40)),
s: 100,
l: rand(80, 100),
a: 0,
ta: rand(0.8, 0.9) } }
Flame.prototype.update = function () { this.y -= this.vy;
this.vy += 0.05; this.x += this.vx; if (this.x < this.cx)
this.vx += 0.1;
else
this.vx -= 0.1; if (this.r > 0)
this.r -= 0.1; if (this.r <= 0)
this.r = 0; this.life -= 0.15; if (this.life <= 0) { this.c.a -= 0.05; if (this.c.a <= 0)
this.alive = false; } else if (this.life > 0 && this.c.a < this.c.ta) { this.c.a += .08; } }
Flame.prototype.draw = function (ctx) { ctx.beginPath();
ctx.arc(this.x, this.y, this.r * 3, 0, 2 * Math.PI);
ctx.fillStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + (this.c.a / 20) + ")";
ctx.fill(); ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
ctx.fillStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + this.c.a + ")";
ctx.fill(); }

第五步:绘制火

     var Fire = function () {

             this.canvas = document.getElementById('fire');
this.ctx = this.canvas.getContext('2d');
this.canvas.height = window.innerHeight;// window.innerHeight
this.canvas.width = window.innerWidth;//window.innerWidth this.aFires = [];
this.aSpark = [];
this.aSpark2 = []; this.mouse = {
x: this.canvas.width * .5,
y: this.canvas.height * .75,
} this.init(); }
Fire.prototype.init = function () {
//跳转语句
if (system.win || system.mac || system.xll) {
this.canvas.addEventListener('mousemove', this.updateMouse.bind(this), false);//PC端
} else {
this.canvas.addEventListener('touchmove', this.updateMouse.bind(this), false);//移动端
} }
Fire.prototype.run = function () { this.update();
this.draw(); if (this.bRuning)
requestAnimationFrame(this.run.bind(this)); }
Fire.prototype.start = function () { this.bRuning = true;
this.run(); }
Fire.prototype.stop = function () { this.bRuning = false; }
Fire.prototype.update = function () { this.aFires.push(new Flame(this.mouse));
this.aSpark.push(new Spark(this.mouse));
this.aSpark2.push(new Spark(this.mouse)); for (var i = this.aFires.length - 1; i >= 0; i--) { if (this.aFires[i].alive)
this.aFires[i].update();
else
this.aFires.splice(i, 1); } for (var i = this.aSpark.length - 1; i >= 0; i--) { if (this.aSpark[i].alive)
this.aSpark[i].update();
else
this.aSpark.splice(i, 1); } for (var i = this.aSpark2.length - 1; i >= 0; i--) { if (this.aSpark2[i].alive)
this.aSpark2[i].update();
else
this.aSpark2.splice(i, 1); } } Fire.prototype.draw = function () { this.ctx.globalCompositeOperation = "source-over";
this.ctx.fillStyle = "rgba( 15, 5, 2, 1 )";
this.ctx.fillRect(0, 0, window.innerWidth, window.innerHeight); this.grd = this.ctx.createRadialGradient(this.mouse.x, this.mouse.y - 200, 200, this.mouse.x, this.mouse.y - 100, 0);
this.grd.addColorStop(0, "rgb( 15, 5, 2 )");
this.grd.addColorStop(1, "rgb( 30, 10, 2 )");
this.ctx.beginPath();
this.ctx.arc(this.mouse.x, this.mouse.y - 100, 200, 0, 2 * Math.PI);
this.ctx.fillStyle = this.grd;
this.ctx.fill(); this.ctx.font = "15em Amatic SC";
this.ctx.textAlign = "center";
this.ctx.strokeStyle = "rgb(50, 20, 0)";
this.ctx.fillStyle = "rgb(120, 10, 0)";
this.ctx.lineWidth = 2;
this.ctx.strokeText("", this.canvas.width / 2, this.canvas.height * .72);
this.ctx.fillText("", this.canvas.width / 2, this.canvas.height * .72); this.ctx.globalCompositeOperation = "overlay";//or lighter or soft-light for (var i = this.aFires.length - 1; i >= 0; i--) { this.aFires[i].draw(this.ctx); } this.ctx.globalCompositeOperation = "soft-light";//"soft-light";//"color-dodge"; for (var i = this.aSpark.length - 1; i >= 0; i--) { if ((i % 2) === 0)
this.aSpark[i].draw(this.ctx); } this.ctx.globalCompositeOperation = "color-dodge";//"soft-light";//"color-dodge"; for (var i = this.aSpark2.length - 1; i >= 0; i--) { this.aSpark2[i].draw(this.ctx); } } Fire.prototype.updateMouse = function (e) {
//跳转语句
if (system.win || system.mac || system.xll) {//PC端
this.mouse.x = e.clientX;
this.mouse.y = e.clientY;
} else {//移动端
e.preventDefault();//阻止默认行为
this.mouse.x = e.changedTouches[0].clientX;
this.mouse.y = e.changedTouches[0].clientY;
} }

第六步:调用

 var oCanvas;
init = function () { oCanvas = new Fire();
oCanvas.start(); }
window.onload = init;

随机数函数

  rand = function (min, max) { return Math.random() * (max - min) + min; };

效果如下:

三,PC端与移动端处理

3.1,判断是PC端还是移动端

     //平台、设备和操作系统
var system = {
win: false,
mac: false,
xll: false
};
//检测平台
var p = navigator.platform;
system.win = p.indexOf("Win") == 0;
system.mac = p.indexOf("Mac") == 0;
system.x11 = (p == "X11") || (p.indexOf("Linux") == 0); //跳转语句
if (system.win || system.mac || system.xll) {
this.canvas.addEventListener('mousemove', this.updateMouse.bind(this), false);//PC端 鼠标移动
} else {
this.canvas.addEventListener('touchmove', this.updateMouse.bind(this), false);//移动端 手指滑动
}

3.2,PC端还是移动端的事件处理

 //跳转语句
if (system.win || system.mac || system.xll) {//PC端
this.mouse.x = e.clientX;
this.mouse.y = e.clientY;
} else {//移动端
e.preventDefault();//阻止默认行为
this.mouse.x = e.changedTouches[0].clientX;
this.mouse.y = e.changedTouches[0].clientY;
}

移动端需禁止缩放

     <meta name="viewport" content="target-densitydpi=320,width=640,user-scalable=no">

Canvas动画(PC端 移动端)的更多相关文章

  1. 把图片画到画布上,适应PC和移动端

    画一张图片到画布上 <canvas id="myCanvas" width="1000px" height="200px" >您 ...

  2. 用react开发一个新闻列表网站(PC和移动端)

    最近在学习react,试着做了一个新闻类的网站,结合ant design框架, 并且可以同时在PC和移动端运行: 主要包含登录和注册组件.头部和脚部组件.新闻块类组件.详情页组件.评论和收藏组件等: ...

  3. JS判断PC和移动端设备

    1.方法一 function IsPC() { var userAgentInfo = navigator.userAgent; var Agents = ["Android", ...

  4. 前端分辨pc和移动端导入不同css

    通过navigator获取浏览器,根据浏览器的不同判断出pc和移动端然后设置不同的css 分辨不同屏幕导入不同的css文件: function loadCSS() { if((navigator.us ...

  5. 判断PC机大小端

    判断PC机大小端 #include<stdio.h> #include<stdlib.h> int main() { short a = 0x0102; char *p = ( ...

  6. 兼顾pc和移动端的textarea字数监控的实现方法

    概述 pc端移动端中文本框监控字数的功能的一种较为简单的实现,考虑到安卓和IOS输入法输入过程中是否触发keyup的差异.利用监听compositionstart判断是否开启了输入法.从而实现体验较为 ...

  7. js判断是pc还是移动端

    //判断pc还是移动端 var isM = function () { var ua = navigator.userAgent; /* navigator.userAgent 浏览器发送的用户代理标 ...

  8. 一个 VUE 组件:实现子元素 scroll 父元素容器不跟随滚动(兼容PC、移动端)

    介绍 我们经常遇到一种情况.当滑动滚动条区域时,子元素滚动条到底部或顶部时就会触发父级滚动条,父级滚动条同理会继续向上触发,直至body容器.这是浏览器默认的滚动行为. 但是很多情况,我们想要子元素滚 ...

  9. bootstrap导航栏PC端移动端之不同样式

    在此之前,我先说我之所以要改变网站PC移动双端不同样式的原因. 首先我的网站用到了bootstrap响应式布局,这是我网站的PC端导航栏: 这是我网站的移动端导航栏,看着就难受: 我用谷歌浏览器F12 ...

随机推荐

  1. 十年后,我又开始研究SEO了

    2009年的时候,我就小打小闹式地要创业了,其实就是和同学在北京阜成门开了一家特产店.但我们的想法不止在这个店,有更大的目标,目前也不便在这里展开了.反正当时我就注意到了SEO,即搜索引擎优化.通俗地 ...

  2. BZOJ 2115:Xor(线性基+DFS)

    题目链接 题意 中文题意 思路 因为存在环和重边,边来回走是没有意义的,因此最终的答案应该是一条从1到n的路径权值异或上若干个环的权值,那么难点在于如何选取这些环的权值使得最终的答案更优. 使用到线性 ...

  3. Codeforces 776C:Molly's Chemicals(思维)

    http://codeforces.com/problemset/problem/776/C 题意:给出一个有n个数的序列,还有一个k,问在这个序列中有多少个子序列使得sum[l, r] = k^0, ...

  4. JDK源码阅读(一):Object源码分析

    最近经过某大佬的建议准备阅读一下JDK的源码来提升一下自己 所以开始写JDK源码分析的文章 阅读JDK版本为1.8 目录 Object结构图 构造器 equals 方法 getClass 方法 has ...

  5. Autocad2017破解版下载|Autodesk Autocad 2017中文破解版下载 64位(附注册机/序列号)

    Autocad2017是Autodesk公司开发的自动计算机辅助设计软件,可用于二维绘图.详细绘制.设计文档和基本三维设计,它具有良好的用户界面,允许用户通过交互菜单或命令行方式来进行各种操作,包括图 ...

  6. 托管堆和垃圾回收(GC)

    一.基础 首先,为了深入了解垃圾回收(GC),我们要了解一些基础知识: CLR:Common Language Runtime,即公共语言运行时,是一个可由多种面向CLR的编程语言使用的"运 ...

  7. android_layout_linearlayout(一)

    这几天一直在研究线性布局这块,记录下一些研究心得,作为参考之用. 一.金刚钻:(线性布局,英文名 linearLayout) 布局xml文件中统大者是一个线性布局,它的长宽都已经fill_parent ...

  8. 最新 centos7下zabbix 监控redis状态

    准备 先准备两台服务器,已经部署好了zabbix-sever和zabbix-agent zabbix-server 192.168.1.70 centos7.2 zabbix-agent 192.16 ...

  9. MyBatis从入门到精通:第一章数据库创建文件

    /*创建数据库mybatis,并指定编码方式为utf8,字符比较规则为utf8_general_ci*/ CREATE DATABASE mybatis DEFAULT CHARACTER SET u ...

  10. 深入理解Java虚拟机一 阅读笔记

    xl_echo编辑整理.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!! --- > 以下内容摘抄自 ...