canvas-球体动画运动 目录

文章目录

  • 前言
  • 原版代码实现
    • 效果展示
    • `index.html`
    • `requestNextAnimationFrame.js`
    • `main.js`
  • 基于时间的运动
    • 效果
    • `index.html`
    • `top.js`
    • `bottom.js`
  • 基于时间的对比
    • 结果展示
    • `index.html`
    • `main.js`

前言

  • Polyfill多平台适用
  • 边缘检测
  • 球体运动

缺点:

  • 如果每次都要重新绘图,图很复杂就会拖累性能

解决办法:

  1. clip()每次只重绘剪辑出来的区域
  2. 建立副屏canvas实现双缓冲机制

原版代码实现

效果展示

index.html

<!DOCTYPE html><head><title>Using requestAnimationFrame()</title><style> body {background: #dddddd;}#canvas {background: #ffffff;cursor: pointer;margin-left: 10px;margin-top: 10px;-webkit-box-shadow: 3px 3px 6px rgba(0,0,0,0.5);-moz-box-shadow: 3px 3px 6px rgba(0,0,0,0.5);box-shadow: 3px 3px 6px rgba(0,0,0,0.5);}#controls {margin-top: 10px;margin-left: 15px;}</style></head><body><div id='controls'><input id='animateButton' type='button' value='Animate'/></div><canvas id='canvas' width='750' height='500'>Canvas not supported</canvas><script src='./requestNextAnimationFrame.js'></script><script src='./main.js'></script></body>
</html>

requestNextAnimationFrame.js

// requestNextAnimationFrame.js
window.requestNextAnimationFrame = (function() {let originalWebkitRequestAnimationFrame = undefined,wrapper = undefined,callback = undefined,geckoVersion = 0,userAgent = navigator.userAgent,index = 0;if(window.webkitRequestAnimationFrame) {wrapper = time => {if(time === undefined)  time = +new Date();this.callback(time);};originalWebkitRequestAnimationFrame = window.webkitRequestAnimationFrame;window.webkitRequestAnimationFrame = (callback, element) => {this.callback = callback;originalWebkitRequestAnimationFrame(wrapper, element);};}if(window.mozRequestAnimationFrame) {index = userAgent.indexOf('rv:');if(userAgent.indexOf('Gecko') !== -1){geckoVersion = userAgent.substr(index + 3, 3);if(geckoVersion === '2.0'){window.mozRequestAnimationFrame = undefined;}}}return window.requestAnimationFrame   ||window.webkitRequestAnimationFrame ||window.mozRequestAnimationFrame   ||window.oRequestAnimationFrame     ||window.msRequestAnimationFrame    ||function(callback, element) {let start,finish;window.setTimeout(function() {start = +new Date();callback(start);finish = +new Date();this.timeout = 1000 / 60 - (finish - start);}, this.timeout);};
})();

main.js

const discs = [{x: 150,y: 250,lastX: 150,lastY: 250,velocityX: -3.2,velocityY: 3.5,radius: 25,innerColor: 'rgba(255, 255, 0, 1)',middleColor: 'rgba(255, 255, 0, 0.7)',outerColor: 'rgba(255, 255, 0, 0.5)',strokeStyle: 'gray'},{x: 50,y: 150,lastX: 50,lastY: 150,velocityX: 2.2,velocityY: 2.5,radius: 25,innerColor: 'rgba(100, 145, 230, 1.0)',middleColor: 'rgba(100, 145, 230, 0.7)',outerColor: 'rgba(100, 145, 230, 0.5)',strokeStyle: 'blue'},{x: 150,y: 75,lastX: 150,lastY: 75,velocityX: 1.2,velocityY: 1.5,radius: 25,innerColor: 'rgba(255, 0, 0, 1.0)',middleColor: 'rgba(255, 0, 0, 0.7)',outerColor: 'rgba(255, 0, 0, 0.5)',strokeStyle: 'orange'},{x: 150,y: 75,lastX: 150,lastY: 75,velocityX: 1.4,velocityY: 1.6,radius: 20,innerColor: 'rgba(255, 0, 0, 1.0)',middleColor: 'rgba(255, 0, 0, 0.7)',outerColor: 'rgba(255, 0, 0, 0.5)',strokeStyle: 'green'}
];let canvas = document.getElementById('canvas'),context = canvas.getContext('2d'),paused = true,animateButton = document.getElementById('animateButton'),numDiscs = discs.length;// Functions
// 绘制背景线
function drawBackground() {let STEP_Y =12,i = context.canvas.height;context.strokeStyle = 'lightgray';context.lineWidth = 0.5;// 绘制横线while(i > STEP_Y * 4) {context.beginPath();context.moveTo(0, i);context.lineTo(context.canvas.width, i);context.stroke();i -= STEP_Y;}context.save();context.strokeStyle = 'rgba(100,0,0,0.3)';context.lineWidth = 1;context.beginPath();context.moveTo(35,0);context.lineTo(35, context.canvas.height);context.stroke();context.restore();
}// 运动和边界检测
function update(){let disc = null;for(let i of discs){disc = i;// 边缘检测// 横向边界定位if(disc.x + disc.velocityX + disc.radius > context.canvas.width ||disc.x + disc.velocityX - disc.radius < 0){disc.velocityX = -disc.velocityX;}// 纵向边界定位if(disc.y + disc.velocityY + disc.radius > context.canvas.height ||disc.y + disc.velocityY - disc.radius < 0){disc.velocityY = -disc.velocityY;}// 运动disc.x += disc.velocityX;disc.y += disc.velocityY;}
}//绘制渐变色的圆
function draw() {let disc = null;for(let i of discs) {disc = i;let gradient = context.createRadialGradient(disc.x, disc.y, 0, disc.x, disc.y, disc.radius);gradient.addColorStop(0.3, disc.innerColor);gradient.addColorStop(0.5, disc.middleColor);gradient.addColorStop(1.0, disc.outerColor);context.save();context.beginPath();context.arc(disc.x,disc.y,disc.radius,0,Math.PI*2,false);context.clip();context.fillStyle = gradient;context.strokeStyle = disc.strokeStyle;context.fill();context.stroke();context.restore();}
}// 动画
function animate(time) {if(!paused){context.clearRect(0,0,canvas.width,canvas.height);drawBackground();update();draw();window.requestNextAnimationFrame(arguments.callee);}
}// main入口
context.font = '48px Helvetica';animateButton.onclick = event => {paused = paused ? false : true;if(paused) {animateButton.value = 'Animate';} else {window.requestNextAnimationFrame(animate);animateButton.value = 'Pause';}
};

基于时间的运动

效果

  • 图片过大

index.html

<!DOCTYPE html><head><title>Time-based Motion</title><style> body {background: #dddddd;width: 770px;}.canvas {background: #ffffff;-webkit-box-shadow: rgba(0,0,0,0.5) 5px 5px 20px;-moz-box-shadow: rgba(0,0,0,0.5) 5px 5px 20px;box-shadow: rgba(0,0,0,0.5) 5px 5px 20px;margin-bottom: 10px;}#canvas {position: absolute;left: 0px;top: 20px;margin: 20px;border: thin inset rgba(100,150,230,0.5);}.floatingControls {font-family: Droid Sans, Arial, Helvetica, sans-serif;font-size: 12px;color: slateblue;padding: 10px;margin: 10px;width: 12em;background: rgba(255, 255, 255, 0.3);border: thin solid rgba(0, 0, 0, 0.6);-webkit-box-shadow: rgba(0,0,0,0.5) 5px 5px 20px;-moz-box-shadow: rgba(0,0,0,0.5) 5px 5px 20px;box-shadow: rgba(0,0,0,0.5) 5px 5px 20px;-webkit-border-radius: 10px;-moz-border-radius: 10px;border-radius: 10px;}#controls {margin-top: 10px;margin-left: 15px;}</style></head><body><div id='controls'><div class='floatingControls' id='timeBasedMotionControls'><input type='checkbox' id='timeBasedMotionCheckbox'/>Time-based Motion&nbsp;</div><input type='button' id='topAnimateButton' value='Animate'style='font-size: 0.75em; position: absolute; left: 670px; top: 70px; z-index: 2;'/><input type='button' id='bottomAnimateButton' value='Animate'style='font-size: 0.75em; position: absolute; left: 670px; top: 380px; z-index: 2;'/></div><canvas id='topCanvas' class='canvas' width='750' height='300'>Canvas not supported</canvas><canvas id='bottomCanvas' class='canvas' width='750' height='300'>Canvas not supported</canvas><script src='top.js'></script><script src='bottom.js'></script></body>
</html>

top.js

var COREHTML5 = COREHTML5 || {};COREHTML5.topLeftTimeBasedMotion = function () {var topCanvas = document.querySelector('#topCanvas'),topContext = topCanvas.getContext('2d'),paused = true,discs = [{ x: 150,y: 250,lastX: 150,lastY: 250,velocityX: -3.2,velocityY: 3.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 50,y: 150,lastX: 50,lastY: 150,velocityX: 2.2,velocityY: 2.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 150,y: 75,lastX: 150,lastY: 75,velocityX: 1.2,velocityY: 1.5,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 50,y: 150,lastX: 150,lastY: 250,velocityX: -3.2,velocityY: -3.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 50,y: 75,lastX: 50,lastY: 150,velocityX: 2.2,velocityY: -2.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 200,y: 175,lastX: 150,lastY: 75,velocityX: -1.9,velocityY: 1.2,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 250,y: 250,lastX: 150,lastY: 250,velocityX: 5.2,velocityY: -3.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 150,y: 100,lastX: 50,lastY: 150,velocityX: -2.9,velocityY: -1.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 215,y: 175,lastX: 150,lastY: 75,velocityX: -2.2,velocityY: 2.5,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 250,y: 150,lastX: 150,lastY: 250,velocityX: 4.2,velocityY: -5.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 150,y: 75,lastX: 50,lastY: 150,velocityX: 3.2,velocityY: -3.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 100,y: 100,lastX: 150,lastY: 75,velocityX: -2.9,velocityY: -2.2,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 150,y: 250,lastX: 150,lastY: 250,velocityX: -5.2,velocityY: 5.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 50,y: 150,lastX: 50,lastY: 150,velocityX: 4.2,velocityY: 4.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 150,y: 75,lastX: 150,lastY: 75,velocityX: 2.2,velocityY: 2.5,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 50,y: 150,lastX: 150,lastY: 250,velocityX: -0.2,velocityY: -1.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 50,y: 75,lastX: 50,lastY: 150,velocityX: 1.2,velocityY: -2.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 200,y: 175,lastX: 150,lastY: 75,velocityX: 1.9,velocityY: -1.2,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 250,y: 250,lastX: 150,lastY: 250,velocityX: 3.2,velocityY: -5.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 150,y: 100,lastX: 50,lastY: 150,velocityX: -1.9,velocityY: -2.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 215,y: 175,lastX: 150,lastY: 75,velocityX: -3.2,velocityY: 4.5,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 250,y: 150,lastX: 150,lastY: 250,velocityX: 2.2,velocityY: -4.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 150,y: 75,lastX: 50,lastY: 150,velocityX: 2.2,velocityY: -1.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 100,y: 100,lastX: 150,lastY: 75,velocityX: -5.9,velocityY: -0.2,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},],numDiscs = discs.length,startTime = 0,lastTime = 0,elapsedTime = 0,fps = 0,lastFpsUpdate = { time: 0, value: 0 },animateButton = document.querySelector('#topAnimateButton'),timeBasedMotionCheckbox = document.querySelector('#timeBasedMotionCheckbox'),timeBasedMotion = timeBasedMotionCheckbox.checked;function eraseBackground() {topContext.clearRect(0,0,topCanvas.width,topCanvas.height);}function drawBackground() {var STEP_Y = 12,i = topContext.canvas.height;topContext.strokeStyle = 'lightgray';topContext.lineWidth = 0.5;topContext.save();topContext.restore();while(i > STEP_Y*4) {topContext.beginPath();topContext.moveTo(0, i);topContext.lineTo(topContext.canvas.width, i);topContext.stroke();i -= STEP_Y;}topContext.save();topContext.strokeStyle = 'rgba(100,0,0,0.3)';topContext.lineWidth = 1;topContext.beginPath();topContext.moveTo(35,0);topContext.lineTo(35,topContext.canvas.height);topContext.stroke();topContext.restore();}function update() {var i = numDiscs,disc = null;while(i--) {disc = discs[i];if (disc.x + disc.velocityX + disc.radius > topContext.canvas.width ||disc.x + disc.velocityX - disc.radius < 0) disc.velocityX = -disc.velocityX;if (disc.y + disc.velocityY + disc.radius > topContext.canvas.height ||disc.y + disc.velocityY - disc.radius  < 0) disc.velocityY= -disc.velocityY;disc.x += disc.velocityX;disc.y += disc.velocityY;}}function updateTimeBased(time) {var i = numDiscs,disc = null;if (fps == 0)return;while(i--) {disc = discs[i];deltaX = disc.velocityX deltaX = disc.velocityX * (elapsedTime / 1000);deltaY = disc.velocityY * (elapsedTime / 1000);if (disc.x + deltaX + disc.radius > topContext.canvas.width ||disc.x + deltaX - disc.radius < 0) {disc.velocityX = -disc.velocityX;deltaX = -deltaX;}if (disc.y + deltaY + disc.radius > topContext.canvas.height ||disc.y + deltaY - disc.radius < 0) {disc.velocityY= -disc.velocityY;deltaY = -deltaY;}disc.x = disc.x + deltaX;disc.y = disc.y + deltaY;}}function draw() {var i = numDiscs,disc = discs[i];while(i--) {disc = discs[i];gradient = topContext.createRadialGradient(disc.x, disc.y, 0,disc.x, disc.y, disc.radius);gradient.addColorStop(0.3, disc.innerColor);gradient.addColorStop(0.5, disc.middleColor);gradient.addColorStop(1.0, disc.outerColor);topContext.beginPath();topContext.arc(disc.x, disc.y, disc.radius, 0, Math.PI*2, false);topContext.save();topContext.fillStyle = gradient;topContext.strokeStyle = disc.strokeStyle;topContext.fill();topContext.stroke();topContext.restore();}}function calculateFps(now) {elapsedTime = now - lastTime;fps = 1000 / elapsedTime;lastTime = now;}function updateFps() {var now = (+new Date);calculateFps(now);if (now - startTime < 2000) {return;}if (now - lastFpsUpdate.time > 1000) {lastFpsUpdate.time = now;lastFpsUpdate.value = fps;}if (!paused) {topContext.fillStyle = 'cornflowerblue';topContext.fillText(lastFpsUpdate.value.toFixed() + ' fps', 50, 48);}}function animateTopLeft(time) {if (time === undefined) {time = +new Date;}if (!paused) {eraseBackground();drawBackground();if (timeBasedMotion) {updateTimeBased(time);}else {update();}draw();}updateFps();}animateButton.addEventListener('click', function (e) {paused = paused ? false : true;if (paused) {animateButton.value = 'Animate';}else {animateButton.value = 'Pause';}});timeBasedMotionCheckbox.addEventListener('click', function (e) {if (timeBasedMotionCheckbox.checked) {timeBasedMotion = true;for (var i=0; i < discs.length; ++i) {discs[i].velocityX *= 50;discs[i].velocityY *= 50;}}else {timeBasedMotion = false;for (var i=0; i < discs.length; ++i) {discs[i].velocityX /= 50;discs[i].velocityY /= 50;}}});topContext.font = '36px Helvetica';drawBackground();startTime = +new Date;setInterval(animateTopLeft, 1000/60);
}();

bottom.js

var COREHTML5 = COREHTML5 || {};COREHTML5.bottomRightTimeBasedMotion = function () {var canvas = document.querySelector('#bottomCanvas'),context = canvas.getContext('2d'),paused = true,discs = [{ x: 150,y: 250,lastX: 150,lastY: 250,velocityX: -3.2,velocityY: 3.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 50,y: 150,lastX: 50,lastY: 150,velocityX: 2.2,velocityY: 2.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 150,y: 75,lastX: 150,lastY: 75,velocityX: 1.2,velocityY: 1.5,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 50,y: 150,lastX: 150,lastY: 250,velocityX: -3.2,velocityY: -3.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 50,y: 75,lastX: 50,lastY: 150,velocityX: 2.2,velocityY: -2.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 200,y: 175,lastX: 150,lastY: 75,velocityX: -1.9,velocityY: 1.2,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 250,y: 250,lastX: 150,lastY: 250,velocityX: 5.2,velocityY: -3.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 150,y: 100,lastX: 50,lastY: 150,velocityX: -2.9,velocityY: -1.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 215,y: 175,lastX: 150,lastY: 75,velocityX: -2.2,velocityY: 2.5,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 250,y: 150,lastX: 150,lastY: 250,velocityX: 4.2,velocityY: -5.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 150,y: 75,lastX: 50,lastY: 150,velocityX: 3.2,velocityY: -3.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 100,y: 100,lastX: 150,lastY: 75,velocityX: -2.9,velocityY: -2.2,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 150,y: 250,lastX: 150,lastY: 250,velocityX: -5.2,velocityY: 5.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 50,y: 150,lastX: 50,lastY: 150,velocityX: 4.2,velocityY: 4.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 150,y: 75,lastX: 150,lastY: 75,velocityX: 2.2,velocityY: 2.5,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 50,y: 150,lastX: 150,lastY: 250,velocityX: -0.2,velocityY: -1.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 50,y: 75,lastX: 50,lastY: 150,velocityX: 1.2,velocityY: -2.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 200,y: 175,lastX: 150,lastY: 75,velocityX: 1.9,velocityY: -1.2,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 250,y: 250,lastX: 150,lastY: 250,velocityX: 3.2,velocityY: -5.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 150,y: 100,lastX: 50,lastY: 150,velocityX: -1.9,velocityY: -2.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 215,y: 175,lastX: 150,lastY: 75,velocityX: -3.2,velocityY: 4.5,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 250,y: 150,lastX: 150,lastY: 250,velocityX: 2.2,velocityY: -4.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 150,y: 75,lastX: 50,lastY: 150,velocityX: 2.2,velocityY: -1.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 100,y: 100,lastX: 150,lastY: 75,velocityX: -5.9,velocityY: -0.2,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},],numDiscs = discs.length,startTime = 0,lastTime = 0,fps = 0,lastFpsUpdate = { time: 0, value: 0 },animateButton = document.querySelector('#bottomAnimateButton'),timeBasedMotionCheckbox = document.querySelector('#timeBasedMotionCheckbox'),timeBasedMotion = timeBasedMotionCheckbox.checked;function eraseBackground() {context.clearRect(0,0,canvas.width,canvas.height);}function drawBackground() {var STEP_Y = 12,i = context.canvas.height;context.strokeStyle = 'lightgray';context.lineWidth = 0.5;context.save();context.restore();while(i > STEP_Y*4) {context.beginPath();context.moveTo(0, i);context.lineTo(context.canvas.width, i);context.stroke();i -= STEP_Y;}context.save();context.strokeStyle = 'rgba(100,0,0,0.3)';context.lineWidth = 1;context.beginPath();context.moveTo(35,0);context.lineTo(35,context.canvas.height);context.stroke();context.restore();}function update() {var i = numDiscs,disc = null;while(i--) {disc = discs[i];if (disc.x + disc.velocityX + disc.radius > context.canvas.width ||disc.x + disc.velocityX - disc.radius < 0) disc.velocityX = -disc.velocityX;if (disc.y + disc.velocityY + disc.radius > context.canvas.height ||disc.y + disc.velocityY - disc.radius  < 0) disc.velocityY= -disc.velocityY;disc.x += disc.velocityX;disc.y += disc.velocityY;}}function updateTimeBased(time) {var i = numDiscs,disc = null;if (fps == 0)return;while(i--) {disc = discs[i];deltaX = disc.velocityX / fps;deltaY = disc.velocityY / fps;if (disc.x + deltaX + disc.radius > context.canvas.width ||disc.x + deltaX - disc.radius < 0) {disc.velocityX = -disc.velocityX;deltaX = -deltaX;}if (disc.y + deltaY + disc.radius > context.canvas.height ||disc.y + deltaY - disc.radius < 0) {disc.velocityY= -disc.velocityY;deltaX = -deltaX;}disc.x = disc.x + deltaX;disc.y = disc.y + deltaY;}}function draw() {var i = numDiscs,disc = discs[i];while(i--) {disc = discs[i];gradient = context.createRadialGradient(disc.x, disc.y, 0,disc.x, disc.y, disc.radius);gradient.addColorStop(0.3, disc.innerColor);gradient.addColorStop(0.5, disc.middleColor);gradient.addColorStop(1.0, disc.outerColor);context.beginPath();context.arc(disc.x, disc.y, disc.radius, 0, Math.PI*2, false);context.save();context.fillStyle = gradient;context.strokeStyle = disc.strokeStyle;context.fill();context.stroke();context.restore();}}function calculateFps(now) {fps = 1000 / (now - lastTime);lastTime = now;}function updateFps() {var now = (+new Date);calculateFps(now);if (now - startTime < 2000) {return;}if (now - lastFpsUpdate.time > 1000) {lastFpsUpdate.time = now;lastFpsUpdate.value = fps;}if (!paused) {context.fillStyle = 'cornflowerblue';context.fillText(lastFpsUpdate.value.toFixed() + ' fps', 50, 48);}}function animate(time) {if (time === undefined) {time = +new Date;}if (!paused) {eraseBackground();drawBackground();if (timeBasedMotion) {updateTimeBased(time);}else {update();}draw();}updateFps();}animateButton.addEventListener('click', function (e) {paused = paused ? false : true;if (paused) {animateButton.value = 'Animate';}else {animateButton.value = 'Pause';}});timeBasedMotionCheckbox.addEventListener('click', function (e) {if (timeBasedMotionCheckbox.checked) {timeBasedMotion = true;for (var i=0; i < discs.length; ++i) {discs[i].velocityX *= 50;discs[i].velocityY *= 50;}}else {timeBasedMotion = false;for (var i=0; i < discs.length; ++i) {discs[i].velocityX /= 50;discs[i].velocityY /= 50;}}});context.font = '36px Helvetica';drawBackground();startTime = +new Date;setInterval(animate, 1000/60);
}();

基于时间的对比

结果展示

  • 图片过大

index.html

<!DOCTYPE html><head><title>Time-based Motion</title><style> body {background: #dddddd;width: 770px;}.canvas {background: #ffffff;-webkit-box-shadow: rgba(0,0,0,0.5) 5px 5px 20px;-moz-box-shadow: rgba(0,0,0,0.5) 5px 5px 20px;box-shadow: rgba(0,0,0,0.5) 5px 5px 20px;margin-bottom: 10px;}#canvas {position: absolute;left: 0px;top: 20px;margin: 20px;border: thin inset rgba(100,150,230,0.5);}.floatingControls {font-family: Droid Sans, Arial, Helvetica, sans-serif;font-size: 12px;color: slateblue;padding: 10px;margin: 10px;width: 12em;background: rgba(255, 255, 255, 0.3);border: thin solid rgba(0, 0, 0, 0.6);-webkit-box-shadow: rgba(0,0,0,0.5) 5px 5px 20px;-moz-box-shadow: rgba(0,0,0,0.5) 5px 5px 20px;box-shadow: rgba(0,0,0,0.5) 5px 5px 20px;-webkit-border-radius: 10px;-moz-border-radius: 10px;border-radius: 10px;}#controls {margin-top: 10px;margin-left: 15px;}</style></head><body><div id='controls'><div class='floatingControls' id='timeBasedMotionControls'><input type='checkbox' id='timeBasedMotionCheckbox'/>Time-based Motion&nbsp;</div><input type='button' id='topAnimateButton' value='Animate'style='font-size: 0.75em; position: absolute; left: 670px; top: 70px; z-index: 2;'/></div><canvas id='topCanvas' class='canvas' width='750' height='600'>Canvas not supported</canvas><script src='main.js'></script></body>
</html>

main.js

var COREHTML5 = COREHTML5 || {};COREHTML5.topLeftTimeBasedMotion = function () {var topCanvas = document.querySelector('#topCanvas'),topContext = topCanvas.getContext('2d'),paused = true,discs = [{ x: 150,y: 250,lastX: 150,lastY: 250,velocityX: -3.2,velocityY: 3.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 50,y: 150,lastX: 50,lastY: 150,velocityX: 2.2,velocityY: 2.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 150,y: 75,lastX: 150,lastY: 75,velocityX: 1.2,velocityY: 1.5,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 50,y: 150,lastX: 150,lastY: 250,velocityX: -3.2,velocityY: -3.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 50,y: 75,lastX: 50,lastY: 150,velocityX: 2.2,velocityY: -2.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 200,y: 175,lastX: 150,lastY: 75,velocityX: -1.9,velocityY: 1.2,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 250,y: 250,lastX: 150,lastY: 250,velocityX: 5.2,velocityY: -3.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 150,y: 100,lastX: 50,lastY: 150,velocityX: -2.9,velocityY: -1.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 215,y: 175,lastX: 150,lastY: 75,velocityX: -2.2,velocityY: 2.5,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 250,y: 150,lastX: 150,lastY: 250,velocityX: 4.2,velocityY: -5.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 150,y: 75,lastX: 50,lastY: 150,velocityX: 3.2,velocityY: -3.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 100,y: 100,lastX: 150,lastY: 75,velocityX: -2.9,velocityY: -2.2,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 150,y: 250,lastX: 150,lastY: 250,velocityX: -5.2,velocityY: 5.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 50,y: 150,lastX: 50,lastY: 150,velocityX: 4.2,velocityY: 4.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 150,y: 75,lastX: 150,lastY: 75,velocityX: 2.2,velocityY: 2.5,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 50,y: 150,lastX: 150,lastY: 250,velocityX: -0.2,velocityY: -1.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 50,y: 75,lastX: 50,lastY: 150,velocityX: 1.2,velocityY: -2.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 200,y: 175,lastX: 150,lastY: 75,velocityX: 1.9,velocityY: -1.2,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 250,y: 250,lastX: 150,lastY: 250,velocityX: 3.2,velocityY: -5.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 150,y: 100,lastX: 50,lastY: 150,velocityX: -1.9,velocityY: -2.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 215,y: 175,lastX: 150,lastY: 75,velocityX: -3.2,velocityY: 4.5,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},{ x: 250,y: 150,lastX: 150,lastY: 250,velocityX: 2.2,velocityY: -4.5,radius: 25,innerColor: 'rgba(255,255,0,1)',middleColor: 'rgba(255,255,0,0.7)',outerColor: 'rgba(255,255,0,0.5)',shadowColor: 'rgba(175,175,175,0.7)',strokeStyle: 'gray',},{ x: 150,y: 75,lastX: 50,lastY: 150,velocityX: 2.2,velocityY: -1.5,radius: 25,innerColor: 'rgba(100,145,230,1.0)',middleColor: 'rgba(100,145,230,0.7)',outerColor: 'rgba(100,145,230,0.5)',shadowColor: 'rgba(100,145,230,0.8)',strokeStyle: 'blue'},{ x: 100,y: 100,lastX: 150,lastY: 75,velocityX: -5.9,velocityY: -0.2,radius: 25,innerColor: 'rgba(255,0,0,1.0)',middleColor: 'rgba(255,0,0,0.7)',outerColor: 'rgba(255,0,0,0.5)',shadowColor: 'rgba(255,0,0,0.7)',strokeStyle: 'orange'},],numDiscs = discs.length,startTime = 0,lastTime = 0,elapsedTime = 0,fps = 0,lastFpsUpdate = { time: 0, value: 0 },animateButton = document.querySelector('#topAnimateButton'),timeBasedMotionCheckbox = document.querySelector('#timeBasedMotionCheckbox'),timeBasedMotion = timeBasedMotionCheckbox.checked;function eraseBackground() {topContext.clearRect(0,0,topCanvas.width,topCanvas.height);
}function drawBackground() {var STEP_Y = 12,i = topContext.canvas.height;topContext.strokeStyle = 'lightgray';topContext.lineWidth = 0.5;topContext.save();topContext.restore();while(i > STEP_Y*4) {topContext.beginPath();topContext.moveTo(0, i);topContext.lineTo(topContext.canvas.width, i);topContext.stroke();i -= STEP_Y;}topContext.save();topContext.strokeStyle = 'rgba(100,0,0,0.3)';topContext.lineWidth = 1;topContext.beginPath();topContext.moveTo(35,0);topContext.lineTo(35,topContext.canvas.height);topContext.stroke();topContext.restore();
}function update() {var i = numDiscs,disc = null;while(i--) {disc = discs[i];if (disc.x + disc.velocityX + disc.radius > topContext.canvas.width ||disc.x + disc.velocityX - disc.radius < 0) disc.velocityX = -disc.velocityX;if (disc.y + disc.velocityY + disc.radius > topContext.canvas.height ||disc.y + disc.velocityY - disc.radius  < 0) disc.velocityY= -disc.velocityY;disc.x += disc.velocityX;disc.y += disc.velocityY;}
}function updateTimeBased(time) {var i = numDiscs,disc = null;if (fps == 0)return;while(i--) {disc = discs[i];deltaX = disc.velocityX deltaX = disc.velocityX * (elapsedTime / 1000);deltaY = disc.velocityY * (elapsedTime / 1000);if (disc.x + deltaX + disc.radius > topContext.canvas.width ||disc.x + deltaX - disc.radius < 0) {disc.velocityX = -disc.velocityX;deltaX = -deltaX;}if (disc.y + deltaY + disc.radius > topContext.canvas.height ||disc.y + deltaY - disc.radius < 0) {disc.velocityY= -disc.velocityY;deltaY = -deltaY;}disc.x = disc.x + deltaX;disc.y = disc.y + deltaY;}
}function draw() {var i = numDiscs,disc = discs[i];while(i--) {disc = discs[i];gradient = topContext.createRadialGradient(disc.x, disc.y, 0,disc.x, disc.y, disc.radius);gradient.addColorStop(0.3, disc.innerColor);gradient.addColorStop(0.5, disc.middleColor);gradient.addColorStop(1.0, disc.outerColor);topContext.beginPath();topContext.arc(disc.x, disc.y, disc.radius, 0, Math.PI*2, false);topContext.save();topContext.fillStyle = gradient;topContext.strokeStyle = disc.strokeStyle;topContext.fill();topContext.stroke();topContext.restore();}
}function calculateFps(now) {elapsedTime = now - lastTime;fps = 1000 / elapsedTime;lastTime = now;
}function updateFps() {var now = (+new Date);calculateFps(now);if (now - startTime < 2000) {return;}if (now - lastFpsUpdate.time > 1000) {lastFpsUpdate.time = now;lastFpsUpdate.value = fps;}if (!paused) {topContext.fillStyle = 'cornflowerblue';topContext.fillText(lastFpsUpdate.value.toFixed() + ' fps', 50, 48);}
}function animateTopLeft(time) {if (time === undefined) {time = +new Date;}if (!paused) {eraseBackground();drawBackground();if (timeBasedMotion) {updateTimeBased(time);}else {update();}draw();}updateFps();
}animateButton.addEventListener('click', function (e) {paused = paused ? false : true;if (paused) {animateButton.value = 'Animate';}else {animateButton.value = 'Pause';}
});timeBasedMotionCheckbox.addEventListener('click', function (e) {if (timeBasedMotionCheckbox.checked) {timeBasedMotion = true;for (var i=0; i < discs.length; ++i) {discs[i].velocityX *= 50;discs[i].velocityY *= 50;}}else {timeBasedMotion = false;for (var i=0; i < discs.length; ++i) {discs[i].velocityX /= 50;discs[i].velocityY /= 50;}}
});topContext.font = '36px Helvetica';
drawBackground();
startTime = +new Date;
setInterval(animateTopLeft, 1000/120);
}();

canvas-球体动画运动相关推荐

  1. java模拟摇摆小球程序代码_Android实现左右摆动的球体动画效果

    首先,看一下效果 可能各位在别处看到过类似的东西,我在微信的文章末尾看到有个玩意,感觉有意思,就用代码实现一下.这篇文章主要把握写代码的思路展示一下. 看到上图,我想各位能想到最简单的实现方案就是用动 ...

  2. 基于Canvas的动画基本原理与数理分析

    转载自https://www.jianshu.com/p/e70c9cfbdb38 什么是动画? 就像思考哲学问题无法回避思维和存在的关系一样,制作动画同样无法逃避的问题是动画的原理是什么?这里提一句 ...

  3. 球体动画Android,Android自定义View实现简单炫酷的球体进度球实例代码

    前言 最近一直在研究自定义view,正好项目中有一个根据下载进度来实现球体进度的需求,所以自己写了个进度球,代码非常简单.先看下效果: 效果还是非常不错的. 准备知识 要实现上面的效果我们只要掌握两个 ...

  4. 看你骨骼惊奇,这里有一套 Canvas 粒子动画方案了解一下?

    导语:在日常的开发过程中,我们会常常会用到canvas来制作一些动画特效,其中有一个动画种类,需要我们生成一定数量,形状类似且行为基本一致的粒子,通过这些粒子的运动,来展现动画效果,比如:下雨,闪烁的 ...

  5. 光滑粒子流体动力学_(图文+视频)C4D野教程:奇怪的流体包裹球体动画制作方法...

    难得有时间能够静下来写写文章,直接看问题吧: 这个球体的形状我尝试了一下,其实非常容易就做出来了. 但是只是写如何做出这个形状,感觉没有什么内容可以写,所以后面我又按照自己的想法胡乱的加入了一些东西进 ...

  6. canvas 制作动画(上)

    canvas 制作动画(上) canvas 制作动画(上) 1. 画布中的动画 2. 创建动画循环 2.1 循环 2.2 更新.清除.绘制 3. 记忆要绘制的形状 3.1 错误的方法 3.2 正确的方 ...

  7. canvas 制作动画(下)

    canvas 制作动画(下) 1. 改变方向 在 canvas 制作动画(上)已经介绍了如何创建动画,但还没有讨论如何控制形状动画的方式.我觉得只有直线动画会让人觉得很枯燥,不知你是否也这样想. 你已 ...

  8. 明日方舟页面球体动画

    了解明日方舟页面球体动画 这是对明日方舟登录界面与官网球体动画名称的探索记录,并没有什么实际意义 结论 最后的结论是,就是球体网格动画 起因 在登录游戏与进入游戏官网时一直都能看到以下这个球体动画 我 ...

  9. canvas粒子动画

    2019独角兽企业重金招聘Python工程师标准>>> 周末在家玩了一下canvas粒子动画,先看看效果,用的图是我们微众银行的干爹'qq',先看看效果 ##1.获取图片信息 ### ...

最新文章

  1. DKHadoop人力资源大数据解决方案架构
  2. 基于Java语言构建区块链(一)—— 基本原型
  3. 正则表达式匹配换行符
  4. 直击面试现场:神级程序员仅100秒,60行代码写出俄罗斯方块,成为全公司焦点!...
  5. oracle定时任务的编写及查看删除
  6. 6显示wan口未插线_WiFi 6到底6不6——华硕 AX56U热血版 路由器评测
  7. 获取当地天气_6 点起来看天气预报?正经人谁看天气预报,原来是为了看她
  8. singft 函数 matlab,(新)信号与系统MATLAB实验全.doc
  9. android intent跳转声音,android intent 跳转
  10. 深入浅出Python——Python高级语法之函数
  11. 【Clover】服务器环境中通过Clover boot引导黑群晖DSM(Linux)+Win系统的解决方案与常见bug排查
  12. UWB定位系统中为何要加入陀螺仪
  13. java堆的特点_java栈的特点是什么?java的堆和栈的优缺点介绍
  14. 解决Jar包双击打不开!
  15. Mysql各版本驱动包
  16. word可以画神经网络图吗,如何画神经网络结构图
  17. DirectSound学习(二)--流式缓冲区
  18. 灭霸级——如何选择最适合你的Linux发行版
  19. 深圳金证股份面试的经历
  20. 解决Android Studio不提示控件的XML属性

热门文章

  1. 图书音像全场满100返100
  2. 微信直连支付通道刷脸支付用户开通步骤
  3. 力扣题目归类,顺序刷题不再难
  4. 全球与中国中型徒步鞋市场深度研究分析报告
  5. MySQL远程连接的设置
  6. kubeadm安装K8s 1.16集群--问题集锦
  7. vue 组件第一次不渲染问题_解决vue页面渲染但dom没渲染的操作
  8. 一个可以不被广告拦截器拦截的弹出窗口
  9. EXT combobox赋值
  10. 钌碳Ru/NC7440-18-8制备碳化铁嵌入式碳复合材料