JS:调整大小 canvas + 在 canvas 上重绘元素
JS: Resizing canvas + redrawing elements on canvas
我的问题:调整 canvas 及其所有绘制元素的最佳方法是什么?
我有 2 个例子,我试图实现这个。
第一个有效,但缺乏功能,因为如果我要添加更多要绘制的元素,它会变得非常混乱。在我的第二个示例中,我尝试将所有内容放入一个数组并循环遍历它,但它不再正确调整大小,因为它不再重新计算 x、y 宽度和高度。基本上我想知道一种方法,在绘制之前不必再次调用计算元素 x、y、宽度和高度的函数。我想把数学放到数组中,当它被绘制时,
它会重新计算,所以我只需要确保 canvas.width/height 已更新,我该怎么做?
第一个例子
class Canvas {
constructor() {
this.canvas = document.createElement('canvas');
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.ctx = this.canvas.getContext('2d');
document.body.appendChild(this.canvas);
this.resize();
}
initAreas() {
this.firstArea = { "x": 0, "y": 0, "w": this.canvas.width, "h": this.canvas.height / 2 }
this.secondArea = { "x": 0, "y": this.firstArea.h, "w": this.canvas.width, "h": this.canvas.height / 2 }
}
resize() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.initAreas();
this.ctx.fillStyle = "green";
this.ctx.fillRect(this.firstArea.x, this.firstArea.y, this.firstArea.w, this.firstArea.h);
this.ctx.fillStyle = "red";
this.ctx.fillRect(this.secondArea.x, this.secondArea.y, this.secondArea.w, this.secondArea.h);
}
}
const canvas = new Canvas();
window.onresize = function() { canvas.resize(); }
body {
padding: 0;
margin: 0;
}
canvas {
display: block;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<script src="script.js"></script>
</body>
</html>
第二个例子
class Canvas {
constructor() {
this.canvas = document.createElement('canvas');
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.ctx = this.canvas.getContext('2d');
document.body.appendChild(this.canvas);
this.areasToDraw = [];
this.initAreas();
this.resize();
}
initAreas() {
this.firstArea = { "x": 0, "y": 0, "w": this.canvas.width, "h": this.canvas.height / 2, "color": "green" }
this.areasToDraw.push(this.firstArea);
this.secondArea = { "x": 0, "y": this.firstArea.h, "w": this.canvas.width, "h": this.canvas.height / 2, "color": "red" }
this.areasToDraw.push(this.secondArea);
}
resize() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
for(this.areas in this.areasToDraw) {
this.ctx.fillStyle = this.areasToDraw[this.areas].color;
this.ctx.fillRect(this.areasToDraw[this.areas].x, this.areasToDraw[this.areas].y, this.areasToDraw[this.areas].w, this.areasToDraw[this.areas].h);
}
}
观察 1:“由于调整大小事件可以高速触发,因此事件处理程序不应执行计算量大的操作,例如 DOM 修改。相反,建议使用 requestAnimationFrame、setTimeout 或 customEvent 来限制事件”
这是来自MDN resize
观察 2:在调整大小时你需要绑定 canvas,否则你会得到 canvas 未定义。
观察3:当你调整canvas的大小时,你需要清空元素数组:this.areasToDraw
在这种情况下,并重新填充数组有新元素。
我会这样做:
class Canvas {
constructor() {
this.canvas = document.createElement('canvas');
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.ctx = this.canvas.getContext('2d');
document.body.appendChild(this.canvas);
this.areasToDraw = [];
//this.initAreas();
//this.resize();
}
initAreas() {
this.firstArea = { "x": 0, "y": 0, "w": this.canvas.width, "h": this.canvas.height / 2, "color": "green" }
this.areasToDraw.push(this.firstArea);
this.secondArea = { "x": 0, "y": this.firstArea.h, "w": this.canvas.width, "h": this.canvas.height / 2, "color": "red" }
this.areasToDraw.push(this.secondArea);
}
resize() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
// empty the array
this.areasToDraw.length = 0;
// repopulate the array
this.initAreas();
for(this.areas in this.areasToDraw) {
this.ctx.fillStyle = this.areasToDraw[this.areas].color;
this.ctx.fillRect(this.areasToDraw[this.areas].x, this.areasToDraw[this.areas].y, this.areasToDraw[this.areas].w, this.areasToDraw[this.areas].h);
}
}
}
let canvas = new Canvas()
setTimeout(function() {
canvas.resize()
addEventListener('resize', canvas.resize.bind(canvas), false);
}, 15);
body {
padding: 0;
margin: 0;
}
canvas {
display: block;
}
我的问题:调整 canvas 及其所有绘制元素的最佳方法是什么?
我有 2 个例子,我试图实现这个。
第一个有效,但缺乏功能,因为如果我要添加更多要绘制的元素,它会变得非常混乱。在我的第二个示例中,我尝试将所有内容放入一个数组并循环遍历它,但它不再正确调整大小,因为它不再重新计算 x、y 宽度和高度。基本上我想知道一种方法,在绘制之前不必再次调用计算元素 x、y、宽度和高度的函数。我想把数学放到数组中,当它被绘制时, 它会重新计算,所以我只需要确保 canvas.width/height 已更新,我该怎么做?
第一个例子
class Canvas {
constructor() {
this.canvas = document.createElement('canvas');
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.ctx = this.canvas.getContext('2d');
document.body.appendChild(this.canvas);
this.resize();
}
initAreas() {
this.firstArea = { "x": 0, "y": 0, "w": this.canvas.width, "h": this.canvas.height / 2 }
this.secondArea = { "x": 0, "y": this.firstArea.h, "w": this.canvas.width, "h": this.canvas.height / 2 }
}
resize() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.initAreas();
this.ctx.fillStyle = "green";
this.ctx.fillRect(this.firstArea.x, this.firstArea.y, this.firstArea.w, this.firstArea.h);
this.ctx.fillStyle = "red";
this.ctx.fillRect(this.secondArea.x, this.secondArea.y, this.secondArea.w, this.secondArea.h);
}
}
const canvas = new Canvas();
window.onresize = function() { canvas.resize(); }
body {
padding: 0;
margin: 0;
}
canvas {
display: block;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<script src="script.js"></script>
</body>
</html>
第二个例子
class Canvas {
constructor() {
this.canvas = document.createElement('canvas');
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.ctx = this.canvas.getContext('2d');
document.body.appendChild(this.canvas);
this.areasToDraw = [];
this.initAreas();
this.resize();
}
initAreas() {
this.firstArea = { "x": 0, "y": 0, "w": this.canvas.width, "h": this.canvas.height / 2, "color": "green" }
this.areasToDraw.push(this.firstArea);
this.secondArea = { "x": 0, "y": this.firstArea.h, "w": this.canvas.width, "h": this.canvas.height / 2, "color": "red" }
this.areasToDraw.push(this.secondArea);
}
resize() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
for(this.areas in this.areasToDraw) {
this.ctx.fillStyle = this.areasToDraw[this.areas].color;
this.ctx.fillRect(this.areasToDraw[this.areas].x, this.areasToDraw[this.areas].y, this.areasToDraw[this.areas].w, this.areasToDraw[this.areas].h);
}
}
观察 1:“由于调整大小事件可以高速触发,因此事件处理程序不应执行计算量大的操作,例如 DOM 修改。相反,建议使用 requestAnimationFrame、setTimeout 或 customEvent 来限制事件” 这是来自MDN resize
观察 2:在调整大小时你需要绑定 canvas,否则你会得到 canvas 未定义。
观察3:当你调整canvas的大小时,你需要清空元素数组:this.areasToDraw
在这种情况下,并重新填充数组有新元素。
我会这样做:
class Canvas {
constructor() {
this.canvas = document.createElement('canvas');
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.ctx = this.canvas.getContext('2d');
document.body.appendChild(this.canvas);
this.areasToDraw = [];
//this.initAreas();
//this.resize();
}
initAreas() {
this.firstArea = { "x": 0, "y": 0, "w": this.canvas.width, "h": this.canvas.height / 2, "color": "green" }
this.areasToDraw.push(this.firstArea);
this.secondArea = { "x": 0, "y": this.firstArea.h, "w": this.canvas.width, "h": this.canvas.height / 2, "color": "red" }
this.areasToDraw.push(this.secondArea);
}
resize() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
// empty the array
this.areasToDraw.length = 0;
// repopulate the array
this.initAreas();
for(this.areas in this.areasToDraw) {
this.ctx.fillStyle = this.areasToDraw[this.areas].color;
this.ctx.fillRect(this.areasToDraw[this.areas].x, this.areasToDraw[this.areas].y, this.areasToDraw[this.areas].w, this.areasToDraw[this.areas].h);
}
}
}
let canvas = new Canvas()
setTimeout(function() {
canvas.resize()
addEventListener('resize', canvas.resize.bind(canvas), false);
}, 15);
body {
padding: 0;
margin: 0;
}
canvas {
display: block;
}