我目前正在一个项目上,我希望背景是一块空白的画布,球从墙上弹起。
到目前为止,我已经做到了,但是遇到了一个问题。 每当我调整浏览器窗口的大小时,画布或其中的球都不会通过。我不知道我在做什么错。
const canvas = document.querySelector('#responsive-canvas')
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let c = canvas.getContext('2d');
function Circle(x, y, dx, dy, radius, colour) {
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.radius = radius;
this.colour = colour;
this.draw = function() {
this.getNewColour = function() {
let symbols, colour;
symbols = "0123456789ABCDEF";
colour = "#";
for (let i = 0; i < 6; i++) {
colour += symbols[Math.floor(Math.random() * 16)];
}
c.strokeStyle = colour;
c.fillStyle = colour;
}
this.getNewColour();
this.x = x;
this.y = y;
this.radius = radius;
//this.getNewColour().colour = colour;
c.beginPath();
c.arc(x, y, radius, 0, Math.PI * 2, false);
// c.strokeStyle = 'blue';
c.stroke();
//c.fill();
}
this.update = function() {
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.radius = radius;
if (x + radius > innerWidth || x - radius < 0) {
dx = -dx;
}
if (y + radius > innerHeight || y - radius < 0) {
dy = -dy;
}
x += dx;
y += dy;
this.draw();
}
}
let circleArr = [];
for (let i = 0; i < 23; i++) {
let radius = 50;
let x = Math.random() * (innerWidth - radius * 2) + radius;
let y = Math.random() * (innerHeight - radius * 2) + radius;
let dx = (Math.random() - 0.5);
let dy = (Math.random() - 0.5);
circleArr.push(new Circle(x, y, dx, dy, radius));
};
function animate() {
requestAnimationFrame(animate);
c.clearRect(0, 0, innerWidth, innerHeight)
for (var i = 0; i < circleArr.length; i++) {
circleArr[i].update();
}
};
animate();
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
/* BODY
*/
html,
body {
width: 100%;
height: 100%;
margin: 0;
}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<meta name="description" content="">
<link rel="stylesheet" href="../dist/css/style.css">
<body>
<canvas id="responsive-canvas"></canvas>
</body>
<script src="js/canvas.js"></script>
</html>
答案 0 :(得分:2)
您可以使用
<!--I want to take data that looks like this-->
<Foo xmlns:e="http://schemas.cch.com/FooBar/MDS/2007/12/04/Foo">
<e:Description></e:Description>
<e:Name i:nil="true"></e:Name>
<e:DisplaySeqNo>0</e:DisplaySeqNo>
</Foo>
<!--I want to make that data that looks like this-->
<Foo>
<Description xmlns="http://schemas.cch.com/FooBar/MDS/2007/12/04/Foo"></Description>
<Name i:nil="true" xmlns="http://schemas.cch.com/FooBar/MDS/2007/12/04/Foo"></Name>
<DisplaySeqNo xmlns="http://schemas.cch.com/FooBar/MDS/2007/12/04/Foo">0</DisplaySeqNo>
</Foo>
按给定的比例缩放画布上的所有内容,X和Y分别在X和Y轴上缩放。
您可能想使用以下方法重置画布
ctx.scale(x,y);
或ctx.resetTransform()
然后从0,0绘制背景到canvas.width和canvas.height
然后绘制所有内容(所有圆圈),最后将缩放比例设置为所需的值。
答案 1 :(得分:1)
如果要更改宽度和高度,只需在{border-box}所在的CSS区域中添加宽度和高度。
但是,如果要使其中的图像不被拉伸,则需要使用上述注释方法专门访问画布中的高度。
最好使用:
width:() => document.documentElement.clientWidth
答案 2 :(得分:0)
首先,您必须修复冲突逻辑,然后可以根据需要安全地更改画布大小。
未解决的碰撞意味着您的SIM卡处于不可能的状态(例如,墙内的球)。从那时起,以下状态将不再有意义。
球移出画布的原因是,如果球不在外面,则不要将其移回画布。
此外,当您改变击球方向时的方向时,也不能确保方向是正确的符号。
// if the dx = 1 and x > innerWidth + 1000 then dx becomes -1
// Next tine x is still > innerWidth + 1000 and you flip the sign of dx again to 1,
// Then dx to -1 and so on. You never move the ball
if(x + radius > innerWidth || x - radius < 0) {
dx = -dx;
}
在碰撞测试中保持系统性,以便在运动场(画布)改变大小时不会出现意外结果
更新时,请先移动然后检查是否有碰撞。如果发生碰撞,请再次移动球以确保墙体中没有魔术球发生。
update() {
this.x += this.dx;
this.y += this.dy;
if (this.x < this.radius) {
this.x = this.radius;
this.dx = Math.abs(this.dx);
}
if (this.y < this.radius) {
this.y = this.radius;
this.dy = Math.abs(this.dy);
}
if (this.x > ctx.canvas.width - this.radius) {
this.x = ctx.canvas.width - this.radius;
this.dx = -Math.abs(this.dx);
}
if (this.y > ctx.canvas.height - this.radius) {
this.y = ctx.canvas.height - this.radius;
this.dy = -Math.abs(this.dy);
}
}
解决了碰撞问题后,您现在可以随时更改画布大小。一种方法是在动画函数中进行。
如果画布大小与页面大小不匹配,请更改画布大小以使其匹配。
function animate () {
if (ctx.canvas.width !== innerWidth || ctx.canvas.height !== innerHeight) {
ctx.canvas.width = innerWidth;
ctx.canvas.height = innerHeight;
} else {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
}
// ... do stuff
requestAnimationFrame(animate);
}
请注意,更改画布的大小也会清除画布,这就是else
子句中留有清除空间的原因。
代码中有很多坏处。您可以将下面的代码段复制粘贴到代码笔中,或使用上面的信息以您的样式修改代码。
const canvas = document.querySelector('#responsive-canvas')
canvas.width = innerWidth;
canvas.height = innerHeight;
// Set constants in one place so you can make changes quickly and easily
const DEFAULT_RADIUS = 50;
const MAX_SPEED = 5;
const CIRCLE_COUNT = 100;
Math.TAU = Math.PI * 2
// Use function to do repetitive code
Math.rand = (min, max) => Math.random() * (max - min) + min; //
function randomHexColor() {
return "#" + ((Math.random() * 0xFFFFFF | 0).toString(16).padStart(6,"0"));
}
// pulral names for arrays and variables that do not change should be constants
const circles = [];
const ctx = canvas.getContext('2d');
requestAnimationFrame(animate); // start frame renderer with a request, dont call it directly
function Circle( // using default params to set random values
radius = Math.rand(DEFAULT_RADIUS/4, DEFAULT_RADIUS), // radius must be first argument as its used to set random x, and y
x = Math.rand(radius, ctx.canvas.width - radius),
y = Math.rand(radius, ctx.canvas.height - radius),
dx = Math.rand(-MAX_SPEED, MAX_SPEED),
dy = Math.rand(-MAX_SPEED, MAX_SPEED),
colour = randomHexColor()
) {
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.radius = radius;
this.colour = colour;
}
// Define Circle functions as prototype outside the function Circle (runs faster)
Circle.prototype = {
draw() {
ctx.strokeStyle = ctx.fillStyle = this.colour;
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.TAU);
ctx.stroke();
},
update() {
this.x += this.dx;
this.y += this.dy;
if (this.x < this.radius) {
this.x = this.radius;
this.dx = Math.abs(this.dx);
}
if (this.y < this.radius) {
this.y = this.radius;
this.dy = Math.abs(this.dy);
}
if (this.x > ctx.canvas.width - this.radius) {
this.x = ctx.canvas.width - this.radius;
this.dx = -Math.abs(this.dx);
}
if (this.y > ctx.canvas.height - this.radius) {
this.y = ctx.canvas.height - this.radius;
this.dy = -Math.abs(this.dy);
}
}
};
for (let i = 0; i < CIRCLE_COUNT; i++) { circles.push(new Circle()) }
function animate () {
if (ctx.canvas.width !== innerWidth || ctx.canvas.height !== innerHeight) {
ctx.canvas.width = innerWidth;
ctx.canvas.height = innerHeight;
} else {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
}
// use for of loop (saves having to mess with index)
for (const circle of circles) {
circle.update(); // seperate update and draw
circle.draw()
}
requestAnimationFrame(animate);
}