javascript - HTML5 Canvas Javascript - 如何使用 'translate3d' 制作带有瓷砖的可移动 Canvas ?

标签 javascript html canvas translate3d

我在使用可移动 Canvas 时遇到问题,该 Canvas 会随着“玩家”在 map 上的移动而调整。由于绘制 600 个图 block ,每秒 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();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id=canvas></canvas>

最佳答案

有几件事正在发生:
立即调用 drawMap而不是使用requestAnimationFrame正如 ggorlen 在评论中提到的那样,使用 requestAnimationFrame在一个更新周期中多次是一种不寻常的做法。当您使用 requestAnimationFrame ,您将在下一帧更新时调用该函数,这意味着会有一帧 map 未重绘,导致轻微闪烁。相反,如果您立即调用它,它将重新绘制该帧的 map 。此外,将所有绘画和更新合并到一次调用 requestAnimationFrame 是一个好主意。 ,因为它可以更清楚地更新事物的顺序。
所以你应该改变requestAnimationFrame(drawMap);drawMap();使用非整数求余数
模算术(即 % 运算符)通常适用于整数。如果您有 MAIN.position.x % tileSize ,它经常出现故障,因为 tileSize不是整数 (200/6)。要使用非整数求余数,我们可以使用自定义函数:

function remainder(a, b) {
  return a - Math.floor(a / b) * b;
}
并用我们的新函数替换模算术实例(例如,将 MAIN.position.x % tileSize 更改为 remainder(MAIN.position.x, tileSize) )Math.round对比 Math.floor最后,您可能想使用 Math.floor而不是 Math.round , 因为 Math.round对于 (-1, 0) 和 (0, 1) 之间的范围,返回 0,而 Math.floor返回 -1 和 0。
使用容器和 css 隐藏 Canvas 的移动部分
您可能希望使用包含 div 和相应的 css 来隐藏正在重绘的 Canvas 边缘:
在 HTML 中:
<div class="container">
<canvas id=canvas></canvas>
</div>
在 CSS 中:
.container {
  width: 560px;
  height: 160px;
  overflow: hidden;
}
全部一起
总而言之,它看起来像这样:

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 remainder(a, b) {
  return a - Math.floor(a / b) * b;
}
function moveMap(){
    const sector = {
        x: Math.floor(-remainder(MAIN.position.x, tileSize)),
        y: Math.floor(-remainder(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;
        drawMap();
    }
    $('#canvas').css({
        transform: "translate3d(" + sector.x + "px, " + sector.y + "px, 0)"
    });
}
update();
.container {
  width: 560px;
  height: 160px;
  overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<canvas id=canvas></canvas>
</div>

关于javascript - HTML5 Canvas Javascript - 如何使用 'translate3d' 制作带有瓷砖的可移动 Canvas ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66232113/

相关文章:

javascript - JQuery - 选择选项不会附加在更改事件上

html - 在默认模板中覆盖样式

html - 如何在向导模式中设置宽度自动

javascript - 如何通过多次点击在 Canvas 上显示多个箭头

javascript - Web套接字性能

Javascript正则表达式 - 匹配单词中间的大写/大写字母(在句子中)?

html 元素与 float 对齐 :left and float:right

jquery - jQuery 中类似 Safari 主页的效果

javascript - Canvas 混合不起作用

Javascript 错误 : set audio object controls attribute True = = False