想法:
嗨,这是我第一次尝试 Canvas 动画。我不确定这个概念是否已经存在,但我将我的版本称为“双态动画”。这个想法是这样的:为屏幕上的每个对象创建一个 map ,其中包含三个子 map 。其中一个子图保存当前状态属性(动画对象的),第二个保存最终目的地(动画对象的),第三个用于分割增量以确保对象(屏幕上)到达其最终目的地在`framesForChange 中设置的帧数。
问题:
请注意,随着动画的进行,对象逐渐向下推到右下角,但 x 和 y 轴的数字继续增长。我知道我正在生成随机数以将其限制在视口(viewport)的宽度 (x) 和高度 (y) 内。为什么会这样?我该如何解决?
代码:
如果您对我如何提高效率有任何建议(或者,更重要的是,解决 [上述] 问题),请在您的回答或评论中提及。谢谢。
window.addEventListener('load', initializeCanvasTwo());
function initializeCanvasTwo() {
var canvas, c, map = {},
framesForChange = 360;
initializeCanvas();
resizeCanvas();
initializeMapping();
draw();
window.addEventListener('resize', function() {
resizeCanvas();
});
function initializeCanvas() {
canvas = document.getElementById('canvasTwo');
c = canvas.getContext('2d');
}
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
c.width = window.innerWidth;
c.height = window.innerHeight;
}
function initializeMapping() {
var n = Math.floor(window.innerWidth * window.innerHeight / 20000);
for (var i = 0; i < n; i++) {
map[i] = {
current: {
startX: getRandomX(),
startY: getRandomY(),
endX: getRandomX(),
endY: getRandomY()
},
final: {
startX: getRandomX(),
startY: getRandomY(),
endX: getRandomX(),
endY: getRandomY()
},
increment: {
}
};
map[i].increment.startXIncrement = (map[i].final.startX - map[i].current.startX) / framesForChange;
map[i].increment.startYIncrement = (map[i].final.startY - map[i].current.startY) / framesForChange;
map[i].increment.endXIncrement = (map[i].final.endX - map[i].current.endX) / framesForChange;
map[i].increment.endYIncrement = (map[i].final.endY - map[i].current.endY) / framesForChange;
}
}
function getRandomX() {
return Math.floor(Math.random() * window.innerWidth);
}
function getRandomY() {
return Math.floor(Math.random() * window.innerHeight);
}
function updateMap() {
var n = Object.keys(map).length;
for (var i = 0; i < n; i++) {
if (map[i].final.startX - map[i].current.startX < map[i].increment.startXIncrement) {
//startX transition complete: set new destination...
map[i].final.startX = getRandomX();
map[i].increment.startXIncrement = (map[i].final.startX - map[i].current.startX) / framesForChange;
} else {
map[i].current.startX += map[i].increment.startXIncrement;
}
if (map[i].final.startY - map[i].current.startY < map[i].increment.startYIncrement) {
//startY transition complete: set new destination...
map[i].final.startY = getRandomY();
map[i].increment.startYIncrement = (map[i].final.startY - map[i].current.startY) / framesForChange;
} else {
map[i].current.startY += map[i].increment.startYIncrement;
}
if (map[i].final.endX - map[i].current.endX < map[i].increment.endXIncrement) {
//endX transition complete: set new destination...
map[i].final.endX = getRandomX();
map[i].increment.endXIncrement = (map[i].final.endX - map[i].current.endX) / framesForChange;
} else {
map[i].current.endX += map[i].increment.endXIncrement;
}
if (map[i].final.endY - map[i].current.endY < map[i].increment.endYIncrement) {
//endY transition complete: set new destination...
map[i].final.endY = getRandomY();
map[i].increment.endYIncrement = (map[i].final.endY - map[i].current.endY) / framesForChange;
} else {
map[i].current.endY += map[i].increment.endYIncrement;
}
}
}
function draw() {
c.clearRect(0, 0, window.innerWidth, window.innerHeight);
c.strokeStyle = 'blue';
var n = Object.keys(map).length;
for (var i = 0; i < n; i++) {
c.beginPath();
c.moveTo(map[i].current.startX, map[i].current.startY);
c.lineTo(map[i].current.endX, map[i].current.endY);
c.stroke();
c.closePath();
}
updateMap();
requestAnimationFrame(draw);
}
}
html,
body {
margin: 0;
padding: 0;
}
canvas {
width: 100%;
height: 100%;
margin-bottom: -4px;
}
<canvas id="canvasTwo"></canvas>
最佳答案
主要问题在于 if
条件。
您检查最终电流是否小于增量。但是,当 x 试图向左移动或 y 向上移动时(这意味着开始 > 最终),您就会为它们创建新的值。所以只允许去右边和底部。 (要解决此问题,您应该在 if 的两边使用 Math.abs
,但这会进一步降低性能)
作为轻微的改进,您应该为 map
使用一个数组,并且由于所有元素都采用相同的帧来完成它们的动画,因此您不应该检查每个点是否已到达其目的地,而是计算帧和一次更新结束位置。
window.addEventListener('load', initializeCanvasTwo());
function initializeCanvasTwo() {
var canvas, c, map = [],
framesForChange = 360,
currentFrame = 360;
initializeCanvas();
resizeCanvas();
initializeMapping();
draw();
window.addEventListener('resize', function() {
resizeCanvas();
});
function initializeCanvas() {
canvas = document.getElementById('canvasTwo');
c = canvas.getContext('2d');
}
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
c.width = window.innerWidth;
c.height = window.innerHeight;
}
function initializeMapping() {
var n = Math.floor(window.innerWidth * window.innerHeight / 20000);
for (var i = 0; i < n; i++) {
map[i] = {
current: {
startX: getRandomX(),
startY: getRandomY(),
endX: getRandomX(),
endY: getRandomY()
},
final: {
startX: getRandomX(),
startY: getRandomY(),
endX: getRandomX(),
endY: getRandomY()
},
increment: {
}
};
map[i].increment.startXIncrement = (map[i].final.startX - map[i].current.startX) / framesForChange;
map[i].increment.startYIncrement = (map[i].final.startY - map[i].current.startY) / framesForChange;
map[i].increment.endXIncrement = (map[i].final.endX - map[i].current.endX) / framesForChange;
map[i].increment.endYIncrement = (map[i].final.endY - map[i].current.endY) / framesForChange;
}
}
function getRandomX() {
return Math.floor(Math.random() * window.innerWidth);
}
function getRandomY() {
return Math.floor(Math.random() * window.innerHeight);
}
function updateMap() {
var n = map.length;
currentFrame = --currentFrame || framesForChange;
if (currentFrame == framesForChange){
// create new values
for (var i = 0; i < n; i++) {
map[i].final.startX = getRandomX();
map[i].final.startY = getRandomY();
map[i].final.endX = getRandomX();
map[i].final.endY = getRandomY();
map[i].increment.startXIncrement = (map[i].final.startX - map[i].current.startX) / framesForChange;
map[i].increment.startYIncrement = (map[i].final.startY - map[i].current.startY) / framesForChange;
map[i].increment.endXIncrement = (map[i].final.endX - map[i].current.endX) / framesForChange;
map[i].increment.endYIncrement = (map[i].final.endY - map[i].current.endY) / framesForChange;
}
}
for (var i = 0; i < n; i++) {
map[i].current.startX += map[i].increment.startXIncrement;
map[i].current.startY += map[i].increment.startYIncrement;
map[i].current.endX += map[i].increment.endXIncrement;
map[i].current.endY += map[i].increment.endYIncrement;
}
}
function draw() {
c.clearRect(0, 0, window.innerWidth, window.innerHeight);
var n = map.length;
c.strokeStyle = 'blue';
for (var i = 0; i < n; i++) {
c.beginPath();
c.moveTo(map[i].current.startX, map[i].current.startY);
c.lineTo(map[i].current.endX, map[i].current.endY);
c.stroke();
c.closePath();
}
updateMap();
requestAnimationFrame(draw);
}
}
html,
body {
margin: 0;
padding: 0;
}
canvas {
width: 100%;
height: 100%;
margin-bottom: -4px;
}
<canvas id="canvasTwo"></canvas>
关于javascript - Canvas 动画,我的 JavaScript 代码中的数学计算问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40274835/