最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - KonvaJSHTML5 canvas infinite looping tilemap. Setting camera position - Stack Overflow

programmeradmin1浏览0评论

I'm trying to create an infinite looping canvas based on a main 'grid'. Scaled down fiddle here with the grid in the centre of the viewport.

JS Fiddle here

In the fiddle I have my main grid of coloured squares in the centre, I want them tiled infinitely in all directions. Obviously this isn't realistically possible, so I want to give the illusion of infinite by just redrawing the grids based on the scroll direction.

I found some good articles: :_Scrolling_maps

And the best route seems to be to get the drag direction and then reset camera to that point, so the layers scroll under the main canvas viewport, thus meaning the camera can never reach the edge of the main viewport canvas.

I've worked on adding some event listeners for mouse drags :

Fiddle with mouse events

 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
        }


    });

But I can't reliably work out the co-ordinates for each direction and then how to reset the camera position.

I'm trying to create an infinite looping canvas based on a main 'grid'. Scaled down fiddle here with the grid in the centre of the viewport.

JS Fiddle here

In the fiddle I have my main grid of coloured squares in the centre, I want them tiled infinitely in all directions. Obviously this isn't realistically possible, so I want to give the illusion of infinite by just redrawing the grids based on the scroll direction.

I found some good articles: https://developer.mozilla/en-US/docs/Games/Techniques/Tilemaps/Square_tilemaps_implementation:_Scrolling_maps

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

And the best route seems to be to get the drag direction and then reset camera to that point, so the layers scroll under the main canvas viewport, thus meaning the camera can never reach the edge of the main viewport canvas.

I've worked on adding some event listeners for mouse drags :

Fiddle with mouse events

 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
        }


    });

But I can't reliably work out the co-ordinates for each direction and then how to reset the camera position.

Share Improve this question asked Dec 5, 2018 at 12:07 KiksyKiksy 1,2925 gold badges20 silver badges44 bronze badges 6
  • A few warnings about the initial JS Findle: last_position in line 1 is never used; missing semicolon in lines 24, 37, 43, 187; unnecessary semicolon in line 47. – Tiago Peres Commented Dec 7, 2018 at 19:56
  • Neither fiddle is working for me. Both just show blank pages. Console shows warnings like Konva warning: Can not change width of layer. – Old Pro Commented Dec 7, 2018 at 23:36
  • 1 Neither fiddle is working for me too. I just see a blank page. – AmerllicA Commented Dec 9, 2018 at 21:23
  • 1 Fiddle is not working for me too. I just see a blank page. – Chinmoy Samanta Commented Dec 10, 2018 at 7:29
  • This fiddle: jsfiddle/kiksy/dvn2wyh5/25 is working, you may need to scroll to see the squares however. – Kiksy Commented Dec 12, 2018 at 14:21
 |  Show 1 more ment

1 Answer 1

Reset to default 12 +500

As you need "infinite" canvas I suggest to not use scrolling and make canvas as large as user viewport. Then you can emulate camera and on every move, you need to draw a new grid on the canvas. You just need to carefully calculate the position of the grid.

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();
})
  <script src="https://unpkg./konva@^2/konva.min.js"></script>
  <div id="container"></div>

If you need scrolling you can listen wheel event on stage and move into desired direction.

发布评论

评论列表(0)

  1. 暂无评论