HTML Canvas 调整大小后形状动画卡在 window 的末尾
HTML Canvas shape animation stuck at end of window after resize
我正在为 HTML Canvas 做一个有趣的介绍项目。基本概念是,在这种情况下,圆圈中的某些形状会四处移动并从侧面反弹。我想帮助解决的两个问题是:
调整浏览器大小后,圆圈可能会卡在屏幕末端的开放边(底部和右侧),它们的边界是宽度Canvas 和高度Canvas.理想情况下,我希望圆圈的行为方式与它们在以 0 为界的两侧(左侧和顶部)的行为方式相同。(请参阅 animate() 函数中的 if 语句)
如何去掉canvas周围因使用而留下的白色space:
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html,
body {
overflow: hidden;
}
</style>
</head>
<body onresize="resizeCanvas()">
<div>
<canvas id="canvas"></canvas>
</div>
<script>
const canvas = document.getElementById('canvas');
/** @type {CanvasRenderingContext2D} */
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
widthCanvas = canvas.width;
heightCanvas = canvas.height;
draw(40);
function draw(num) {
//number of cycles
num_cycles = num;
// speed bounds
min_speed = 4;
// real max_speed is + min_speed
max_speed = 3;
// create arrays for changing values
const arr_x = new Array(num_cycles);
const arr_y = new Array(num_cycles);
const arr_dx = new Array(num_cycles);
const arr_dy = new Array(num_cycles);
const arr_r = new Array(num_cycles);
// populate arrays with random vaalues in range so circles
// have different velocities on y and x as well as vary in radii
for (let index = 0; index < num_cycles; index++) {
arr_x[index] = ((widthCanvas * 0.2) * Math.random()) + (widthCanvas * 0.4);
arr_y[index] = ((heightCanvas * 0.2) * Math.random()) + (heightCanvas * 0.4);
arr_dx[index] = (min_speed + Math.random() * max_speed) * (Math.round(Math.random()) ? -1 : 1);
arr_dy[index] = (min_speed + Math.random() * max_speed) * (Math.round(Math.random()) ? 1 : -1);
arr_r[index] = 50 + Math.random() * widthCanvas / 12;
}
let arr_color = ["rgba(47, 133, 209, 0.6)", "rgba(244, 67, 54, 0.6)", "rgba(71, 50, 123, 0.6)", "rgba(241, 194, 50, 0.6)", "rgba(56, 118, 29, 0.6)"];
function animate() {
//clear the canvas so that new drawings are on a blank canvas
ctx.clearRect(0, 0, widthCanvas, heightCanvas)
ctx.fillStyle = "rgba(224, 31, 92, 1)";
ctx.fillRect(0, 0, widthCanvas, heightCanvas)
// Draw shapes aand animations
for (var i = 0; i <= widthCanvas; i += widthCanvas / 120) {
addLinesPath(i, i, 0, heightCanvas, "rgba(31, 118, 224, 0.5)");
}
for (let index = 0; index < num_cycles; index++) {
draw_circle(arr_x[index], arr_y[index], arr_r[index], arr_color[index % arr_color.length])
if (arr_x[index] + arr_r[index] > widthCanvas || arr_x[index] - arr_r[index] < 0)
arr_dx[index] = -arr_dx[index];
if (arr_y[index] + arr_r[index] > heightCanvas || arr_y[index] - arr_r[index] < 0)
arr_dy[index] = -arr_dy[index];
arr_x[index] += arr_dx[index];
arr_y[index] += arr_dy[index];
}
requestAnimationFrame(animate);
}
animate()
}
// resize
function resizeCanvas() {
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
widthCanvas = canvas.width;
heightCanvas = canvas.height;
}
function get_width() {
return canvas.width;
}
function get_height() {
return canvas.height;
}
// draw line
function addLinesPath(y_start, y_end, x_start, x_end, color) {
ctx.strokeStyle = color;
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(y_start, x_start);
ctx.lineTo(y_end, x_end);
ctx.stroke();
}
// draw circle
function draw_circle(x, y, r, color) {
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, r, 0, 2 * Math.PI);
ctx.fill();
}
</script>
</body>
</html>
After resizing the browser the circles may get stuck...
考虑使用您的代码段中的以下简化代码:
if (arr_x[index] + arr_r[index] > widthCanvas)
arr_dx[index] = -arr_dx[index];
这里,当圆圈由于调整大小超出右边界时,if
语句的计算结果始终为真。因为你每一帧都在切换方向!
确保在圆圈离开 canvas 后仅切换一次方向。
How to remove the white space around the canvas left...
默认情况下 <body>
有一些余量。在 Chrome 8px。需要检查其他浏览器。如果所有涉及的元素上有任何边距和填充,请去掉这些边距和填充。或者相应地调整代码中的 canvas 宽度。
演示:
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html,
body {
overflow: hidden;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
</style>
</head>
<body onresize="resizeCanvas()">
<div>
<canvas id="canvas"></canvas>
</div>
<script>
const canvas = document.getElementById('canvas');
/** @type {CanvasRenderingContext2D} */
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
widthCanvas = canvas.width;
heightCanvas = canvas.height;
draw(10);
function draw(num) {
//number of cycles
num_cycles = num;
// speed bounds
min_speed = 2;
// real max_speed is + min_speed
max_speed = 2;
// create arrays for changing values
const arr_x = new Array(num_cycles);
const arr_y = new Array(num_cycles);
const arr_dx = new Array(num_cycles);
const arr_dy = new Array(num_cycles);
const arr_r = new Array(num_cycles);
// populate arrays with random vaalues in range so circles
// have different velocities on y and x as well as vary in radii
for (let index = 0; index < num_cycles; index++) {
arr_x[index] = ((widthCanvas * 0.2) * Math.random()) + (widthCanvas * 0.4);
arr_y[index] = ((heightCanvas * 0.2) * Math.random()) + (heightCanvas * 0.4);
arr_dx[index] = (min_speed + Math.random() * max_speed) * (Math.round(Math.random()) ? -1 : 1);
arr_dy[index] = (min_speed + Math.random() * max_speed) * (Math.round(Math.random()) ? 1 : -1);
arr_r[index] = 50 + Math.random() * widthCanvas / 12;
}
let arr_color = ["rgba(47, 133, 209, 0.6)", "rgba(244, 67, 54, 0.6)", "rgba(71, 50, 123, 0.6)", "rgba(241, 194, 50, 0.6)", "rgba(56, 118, 29, 0.6)"];
function animate() {
//clear the canvas so that new drawings are on a blank canvas
ctx.clearRect(0, 0, widthCanvas, heightCanvas)
ctx.fillStyle = "rgba(224, 31, 92, 1)";
ctx.fillRect(0, 0, widthCanvas, heightCanvas)
// Draw shapes and animations
for (var i = 0; i <= widthCanvas; i += widthCanvas / 120) {
addLinesPath(i, i, 0, heightCanvas, "rgba(31, 118, 224, 0.5)");
}
for (let index = 0; index < num_cycles; index++) {
draw_circle(arr_x[index], arr_y[index], arr_r[index], arr_color[index % arr_color.length])
if (arr_x[index] + arr_r[index] > widthCanvas && arr_dx[index] > 0)
arr_dx[index] *= -1;
else if (arr_x[index] - arr_r[index] < 0 && arr_dx[index] < 0)
arr_dx[index] *= -1;
if (arr_y[index] + arr_r[index] > heightCanvas && arr_dy[index] > 0)
arr_dy[index] *= -1;
else if (arr_y[index] - arr_r[index] < 0 && arr_dy[index] < 0)
arr_dy[index] *= -1;
arr_x[index] += arr_dx[index];
arr_y[index] += arr_dy[index];
}
requestAnimationFrame(animate);
}
animate()
}
// resize
function resizeCanvas() {
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
widthCanvas = canvas.width;
heightCanvas = canvas.height;
console.log(widthCanvas, '=', heightCanvas);
}
function get_width() {
return canvas.width;
}
function get_height() {
return canvas.height;
}
// draw line
function addLinesPath(y_start, y_end, x_start, x_end, color) {
ctx.strokeStyle = color;
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(y_start, x_start);
ctx.lineTo(y_end, x_end);
ctx.stroke();
}
// draw circle
function draw_circle(x, y, r, color) {
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, r, 0, 2 * Math.PI);
ctx.fill();
}
</script>
</body>
</html>
在这里,为了避免复杂的代码,我将 if 语句分开了。
通过简单的调试,我们可以很容易地找出这些讨厌的错误。本指南可能会有所帮助:https://developer.chrome.com/docs/devtools/javascript/
我正在为 HTML Canvas 做一个有趣的介绍项目。基本概念是,在这种情况下,圆圈中的某些形状会四处移动并从侧面反弹。我想帮助解决的两个问题是:
调整浏览器大小后,圆圈可能会卡在屏幕末端的开放边(底部和右侧),它们的边界是宽度Canvas 和高度Canvas.理想情况下,我希望圆圈的行为方式与它们在以 0 为界的两侧(左侧和顶部)的行为方式相同。(请参阅 animate() 函数中的 if 语句)
如何去掉canvas周围因使用而留下的白色space:
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html,
body {
overflow: hidden;
}
</style>
</head>
<body onresize="resizeCanvas()">
<div>
<canvas id="canvas"></canvas>
</div>
<script>
const canvas = document.getElementById('canvas');
/** @type {CanvasRenderingContext2D} */
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
widthCanvas = canvas.width;
heightCanvas = canvas.height;
draw(40);
function draw(num) {
//number of cycles
num_cycles = num;
// speed bounds
min_speed = 4;
// real max_speed is + min_speed
max_speed = 3;
// create arrays for changing values
const arr_x = new Array(num_cycles);
const arr_y = new Array(num_cycles);
const arr_dx = new Array(num_cycles);
const arr_dy = new Array(num_cycles);
const arr_r = new Array(num_cycles);
// populate arrays with random vaalues in range so circles
// have different velocities on y and x as well as vary in radii
for (let index = 0; index < num_cycles; index++) {
arr_x[index] = ((widthCanvas * 0.2) * Math.random()) + (widthCanvas * 0.4);
arr_y[index] = ((heightCanvas * 0.2) * Math.random()) + (heightCanvas * 0.4);
arr_dx[index] = (min_speed + Math.random() * max_speed) * (Math.round(Math.random()) ? -1 : 1);
arr_dy[index] = (min_speed + Math.random() * max_speed) * (Math.round(Math.random()) ? 1 : -1);
arr_r[index] = 50 + Math.random() * widthCanvas / 12;
}
let arr_color = ["rgba(47, 133, 209, 0.6)", "rgba(244, 67, 54, 0.6)", "rgba(71, 50, 123, 0.6)", "rgba(241, 194, 50, 0.6)", "rgba(56, 118, 29, 0.6)"];
function animate() {
//clear the canvas so that new drawings are on a blank canvas
ctx.clearRect(0, 0, widthCanvas, heightCanvas)
ctx.fillStyle = "rgba(224, 31, 92, 1)";
ctx.fillRect(0, 0, widthCanvas, heightCanvas)
// Draw shapes aand animations
for (var i = 0; i <= widthCanvas; i += widthCanvas / 120) {
addLinesPath(i, i, 0, heightCanvas, "rgba(31, 118, 224, 0.5)");
}
for (let index = 0; index < num_cycles; index++) {
draw_circle(arr_x[index], arr_y[index], arr_r[index], arr_color[index % arr_color.length])
if (arr_x[index] + arr_r[index] > widthCanvas || arr_x[index] - arr_r[index] < 0)
arr_dx[index] = -arr_dx[index];
if (arr_y[index] + arr_r[index] > heightCanvas || arr_y[index] - arr_r[index] < 0)
arr_dy[index] = -arr_dy[index];
arr_x[index] += arr_dx[index];
arr_y[index] += arr_dy[index];
}
requestAnimationFrame(animate);
}
animate()
}
// resize
function resizeCanvas() {
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
widthCanvas = canvas.width;
heightCanvas = canvas.height;
}
function get_width() {
return canvas.width;
}
function get_height() {
return canvas.height;
}
// draw line
function addLinesPath(y_start, y_end, x_start, x_end, color) {
ctx.strokeStyle = color;
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(y_start, x_start);
ctx.lineTo(y_end, x_end);
ctx.stroke();
}
// draw circle
function draw_circle(x, y, r, color) {
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, r, 0, 2 * Math.PI);
ctx.fill();
}
</script>
</body>
</html>
After resizing the browser the circles may get stuck...
考虑使用您的代码段中的以下简化代码:
if (arr_x[index] + arr_r[index] > widthCanvas)
arr_dx[index] = -arr_dx[index];
这里,当圆圈由于调整大小超出右边界时,if
语句的计算结果始终为真。因为你每一帧都在切换方向!
确保在圆圈离开 canvas 后仅切换一次方向。
How to remove the white space around the canvas left...
默认情况下 <body>
有一些余量。在 Chrome 8px。需要检查其他浏览器。如果所有涉及的元素上有任何边距和填充,请去掉这些边距和填充。或者相应地调整代码中的 canvas 宽度。
演示:
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html,
body {
overflow: hidden;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
</style>
</head>
<body onresize="resizeCanvas()">
<div>
<canvas id="canvas"></canvas>
</div>
<script>
const canvas = document.getElementById('canvas');
/** @type {CanvasRenderingContext2D} */
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
widthCanvas = canvas.width;
heightCanvas = canvas.height;
draw(10);
function draw(num) {
//number of cycles
num_cycles = num;
// speed bounds
min_speed = 2;
// real max_speed is + min_speed
max_speed = 2;
// create arrays for changing values
const arr_x = new Array(num_cycles);
const arr_y = new Array(num_cycles);
const arr_dx = new Array(num_cycles);
const arr_dy = new Array(num_cycles);
const arr_r = new Array(num_cycles);
// populate arrays with random vaalues in range so circles
// have different velocities on y and x as well as vary in radii
for (let index = 0; index < num_cycles; index++) {
arr_x[index] = ((widthCanvas * 0.2) * Math.random()) + (widthCanvas * 0.4);
arr_y[index] = ((heightCanvas * 0.2) * Math.random()) + (heightCanvas * 0.4);
arr_dx[index] = (min_speed + Math.random() * max_speed) * (Math.round(Math.random()) ? -1 : 1);
arr_dy[index] = (min_speed + Math.random() * max_speed) * (Math.round(Math.random()) ? 1 : -1);
arr_r[index] = 50 + Math.random() * widthCanvas / 12;
}
let arr_color = ["rgba(47, 133, 209, 0.6)", "rgba(244, 67, 54, 0.6)", "rgba(71, 50, 123, 0.6)", "rgba(241, 194, 50, 0.6)", "rgba(56, 118, 29, 0.6)"];
function animate() {
//clear the canvas so that new drawings are on a blank canvas
ctx.clearRect(0, 0, widthCanvas, heightCanvas)
ctx.fillStyle = "rgba(224, 31, 92, 1)";
ctx.fillRect(0, 0, widthCanvas, heightCanvas)
// Draw shapes and animations
for (var i = 0; i <= widthCanvas; i += widthCanvas / 120) {
addLinesPath(i, i, 0, heightCanvas, "rgba(31, 118, 224, 0.5)");
}
for (let index = 0; index < num_cycles; index++) {
draw_circle(arr_x[index], arr_y[index], arr_r[index], arr_color[index % arr_color.length])
if (arr_x[index] + arr_r[index] > widthCanvas && arr_dx[index] > 0)
arr_dx[index] *= -1;
else if (arr_x[index] - arr_r[index] < 0 && arr_dx[index] < 0)
arr_dx[index] *= -1;
if (arr_y[index] + arr_r[index] > heightCanvas && arr_dy[index] > 0)
arr_dy[index] *= -1;
else if (arr_y[index] - arr_r[index] < 0 && arr_dy[index] < 0)
arr_dy[index] *= -1;
arr_x[index] += arr_dx[index];
arr_y[index] += arr_dy[index];
}
requestAnimationFrame(animate);
}
animate()
}
// resize
function resizeCanvas() {
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
widthCanvas = canvas.width;
heightCanvas = canvas.height;
console.log(widthCanvas, '=', heightCanvas);
}
function get_width() {
return canvas.width;
}
function get_height() {
return canvas.height;
}
// draw line
function addLinesPath(y_start, y_end, x_start, x_end, color) {
ctx.strokeStyle = color;
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(y_start, x_start);
ctx.lineTo(y_end, x_end);
ctx.stroke();
}
// draw circle
function draw_circle(x, y, r, color) {
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, r, 0, 2 * Math.PI);
ctx.fill();
}
</script>
</body>
</html>
在这里,为了避免复杂的代码,我将 if 语句分开了。
通过简单的调试,我们可以很容易地找出这些讨厌的错误。本指南可能会有所帮助:https://developer.chrome.com/docs/devtools/javascript/