KonvaJS / HTML5画布无限循环tilemap。设定相机位置

Kik*_*ksy 4 javascript html5 canvas konvajs

我试图基于主“网格”创建无限循环的画布。在此处按比例缩小小提琴,使网格位于视口的中心。

JS小提琴在这里

在小提琴中,我的中心有彩色正方形的主网格,我希望它们在各个方向上都无限地平铺。显然,这实际上是不可能的,因此我想通过基于滚动方向重新绘制网格来给出无限的错觉。

我找到了一些不错的文章:https : //developer.mozilla.org/en-US/docs/Games/Techniques/Tilemaps/Square_tilemaps_implementation : _Scrolling_maps

https://gamedev.stackexchange.com/questions/71583/html5-dynamic-canvas-grid-for-scrolling-a-big-map

最好的方法似乎是获取拖动方向,然后将摄影机重置到该点,以便图层在主画布视口下滚动,这意味着摄影机永远无法到达主视口画布的边缘。

我一直在为鼠标拖动添加一些事件侦听器:

摆弄鼠标事件

 var bMouseDown = false;
    var oPreviousCoords = {
        'x': 0,
        'y': 0
    }
    var oDelta;
    var oEndCoords;
    var newLayerTop;


    $(document).on('mousedown', function (oEvent) {
        bMouseDown = true;
        oPreviousCoords = {
            'x': oEvent.pageX,
            'y': oEvent.pageY
        }
    });

    $(document).on('mouseup', function (oEvent) {
        bMouseDown = false;

        oPreviousCoords = {
            'x': oEvent.pageX,
            'y': oEvent.pageY
        }


        oEndCoords = oDelta


        if(oEndCoords.y < -300){


            if(newLayerTop){
                newLayerTop.destroy();
            }

            layerCurentPosition = layer.position();

            newLayerTop = layer.clone();
            newLayerTop.position({
                x:  layerCurentPosition.x,
                y:  layerCurentPosition.y -1960
            });


            stage.add(newLayerTop)

            stage.batchDraw();



        }

    });

    $(document).on('mousemove', function (oEvent) {


        if (!bMouseDown) {
            return;
        }

        oDelta = {
            'x': oPreviousCoords.x - oEvent.pageX,
            'y': oPreviousCoords.y - oEvent.pageY
        }


    });
Run Code Online (Sandbox Code Playgroud)

但是我无法可靠地算出每个方向的坐标,然后再算出如何重置相机位置。

lav*_*ton 7

当您需要“无限”画布时,我建议不要使用滚动并使画布与用户视口一样大。然后,您可以模拟相机,并且在每次移动时都需要在画布上绘制一个新的网格。您只需要仔细计算网格的位置即可。

const stage = new Konva.Stage({
  container: 'container',
  width: window.innerWidth,
  height: window.innerHeight,
  draggable: true
});

const layer = new Konva.Layer();
stage.add(layer);


const WIDTH = 100;
const HEIGHT = 100;

const grid = [
  ['red', 'yellow'],
  ['green', 'blue']
];

function checkShapes() {
  const startX = Math.floor((-stage.x() - stage.width()) / WIDTH) * WIDTH;
  const endX = Math.floor((-stage.x() + stage.width() * 2) / WIDTH) * WIDTH;
  
  const startY = Math.floor((-stage.y() - stage.height()) / HEIGHT) * HEIGHT;
  const endY = Math.floor((-stage.y() + stage.height() * 2) / HEIGHT) * HEIGHT;
 
  
  for(var x = startX; x < endX; x += WIDTH) {
    for(var y = startY; y < endY; y += HEIGHT) {
      const indexX = Math.abs(x / WIDTH) % grid.length;
      const indexY = Math.abs(y / HEIGHT) % grid[0].length;
      layer.add(new Konva.Rect({
        x,
        y,
        width: WIDTH,
        height: HEIGHT,
        fill: grid[indexX][indexY]
      }))
    }
  }
}


checkShapes();
layer.draw();

stage.on('dragend', () => {
  layer.destroyChildren();
  checkShapes();
  layer.draw();
})
Run Code Online (Sandbox Code Playgroud)
  <script src="https://unpkg.com/konva@^2/konva.min.js"></script>
  <div id="container"></div>
Run Code Online (Sandbox Code Playgroud)

如果您需要滚动,则可以wheel在舞台上收听事件并移至所需的方向。