Var*_*yan 5 html javascript canvas translate3d
我在使用可移动画布时遇到问题,该画布会随着“玩家”在地图上移动而进行调整。由于绘制 600 个瓷砖,每秒 60 次非常低效,我切换到使用translate3d并且只有draw在玩家越过一个完整的瓷砖时 - 但它一直出现故障并且不能平滑地移动。我将如何正确实现这一目标?
const ctx = canvas.getContext('2d');
canvas.height = 200;
canvas.width = 600;
const tileSize = canvas.height/6;
const MAIN = {position:{x: 120, y: 120}};
const canvasRefresh = {x: 0, y: 20};
document.body.onmousemove = e => MAIN.position = {x: e.clientX, y: e.clientY};
const tiles = {x: 20, y: 20}
function update(){
moveMap();
requestAnimationFrame(update);
}
function drawMap(){
for(var i = 0; i < tiles.x; i++){
for(var j = 0; j < tiles.y; j++){
ctx.fillStyle = ['black', 'green','orange'][Math.floor((i+j+canvasRefresh.x1+canvasRefresh.y1)%3)];
ctx.fillRect(tileSize * i, tileSize * j, tileSize, tileSize);
}
}
}
function moveMap(){
const sector = {
x: Math.round(-MAIN.position.x % tileSize),
y: Math.round(-MAIN.position.y % tileSize)
};
const x2 = Math.floor(MAIN.position.x/tileSize);
const y2 = Math.floor(MAIN.position.y/tileSize);
if(canvasRefresh.x1 != x2 || canvasRefresh.y1 != y2){
canvasRefresh.x1 = x2;
canvasRefresh.y1 = y2;
requestAnimationFrame(drawMap);
}
$('#canvas').css({
transform: "translate3d(" + sector.x + "px, " + sector.y + "px, 0)"
});
}
update();Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id=canvas></canvas>Run Code Online (Sandbox Code Playgroud)
有几件事正在发生:
drawMap而不是使用requestAnimationFrame正如 ggorlen 在评论中提到的,requestAnimationFrame在一个更新周期中多次使用是一种不寻常的做法。当您使用 时requestAnimationFrame,您将在下一帧更新时调用该函数,这意味着将有一个帧未重新绘制地图,从而导致轻微闪烁。相反,如果您立即调用它,它将重新绘制该帧的地图。另外,将所有绘画和更新合并到一次调用也是一个好主意requestAnimationFrame,因为这样可以更清楚地更新事物的顺序。
所以你应该requestAnimationFrame(drawMap);改为drawMap();
模算术(即%运算符)通常适用于整数。在您有 的情况下MAIN.position.x % tileSize,它经常会出现故障,因为它tileSize不是整数 (200 / 6)。要使用非整数求余数,我们可以使用自定义函数:
function remainder(a, b) {
return a - Math.floor(a / b) * b;
}
Run Code Online (Sandbox Code Playgroud)
并用我们的新函数替换模算术的实例(例如更改MAIN.position.x % tileSize为remainder(MAIN.position.x, tileSize))
Math.round与Math.floor最后,您可能想使用Math.floor代替Math.round,因为Math.round对于 (-1, 0) 和 (0, 1) 之间的范围都返回 0,而对于 (-1, 0) 和 (0, 1) 之间的范围则Math.floor返回 -1 和 0。
您可能想要使用包含 div 和相应的 css 来隐藏正在重绘的画布边缘:
在 HTML 中:
<div class="container">
<canvas id=canvas></canvas>
</div>
Run Code Online (Sandbox Code Playgroud)
在 CSS 中:
.container {
width: 560px;
height: 160px;
overflow: hidden;
}
Run Code Online (Sandbox Code Playgroud)
总的来说,它看起来像这样:
function remainder(a, b) {
return a - Math.floor(a / b) * b;
}
Run Code Online (Sandbox Code Playgroud)
<div class="container">
<canvas id=canvas></canvas>
</div>
Run Code Online (Sandbox Code Playgroud)
.container {
width: 560px;
height: 160px;
overflow: hidden;
}
Run Code Online (Sandbox Code Playgroud)