画布无限滚动贴图对象位置

时间:2018-12-19 17:31:27

标签: javascript html5 canvas html5-canvas konvajs

试图使无限循环滚动在KonvaJS中起作用,因此将有一个由24个项目组成的网格,这些网格将不断滚动。

由于@lavrton,基本网格可以正常工作,但是添加项目意味着它们不会在重绘上停留在原位。我想这与以下内容有关:

 fill: grid[indexX][indexY], 

有什么想法可以将文本映射到块上吗?

 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']
    ];

    const blocks = [
        { w: 150, h: 150 , background: "white" , image: "/img/test2.png" , fullImage: false, title: "" , text: "" },
        { w: 150, h: 150 , background: "white" , image: "/img/person-icon.png" ,  fullImage: false ,title: "" , text: "" },
        { w: 150, h: 150 , background: "#575756" , image: "" ,  fullImage: false, title: "Title" , text: "" },
        { w: 300, h: 300 , background: "white" , image: "/img/test.png", fullImage: true, title: "" , text: "" }

    ];

        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;



        var i = 0;
        for(var x = startX; x < endX; x += WIDTH) {
            for(var y = startY; y < endY; y += HEIGHT) {

                if(i === 4)
                {
                    i = 0;
                }

                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],
                    stroke: 'black',
                    strokeWidth: 4
                }))

                if(blocks[i].title != ""){

                    var complexText = new Konva.Text({
                        x,
                        y,
                        text: "TEST TEXT",
                        fontSize: 14,
                        fontFamily: 'Calibri',
                        fill: 'white',
                        width: WIDTH,
                        height: HEIGHT,
                        verticalAlign: 'middle',
                        align : "center"
                    });

                    layer.add(complexText);

                }



            }
            i++
        }

    }

    checkShapes();
    layer.draw();

    stage.on('dragend', () => {
        layer.destroyChildren();
        checkShapes();
        layer.draw();
    })

https://jsfiddle.net/kiksy/jqo2h3dx/2/

1 个答案:

答案 0 :(得分:2)

说明:

问题是 i 的计算。它必须基于indexXindexY的值

类似这样的东西:

//maps from 0 to 3
const i = indexX * 2 + indexY;

观察块数组时,只有一个具有标题,并且在2的索引处(取决于您的角度)与绿色相对应。

const i = 1 * 2 + 0; //index 2

为什么* 2?它只是硬编码,但对应于内部网格数组的长度为2。

(Ex: grid[0].length)

完整解决方案:

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']
];

const blocks = [{
    w: 150,
    h: 150,
    background: "white",
    image: "/img/test2.png",
    fullImage: false,
    title: "",
    text: ""
  },
  {
    w: 150,
    h: 150,
    background: "white",
    image: "/img/person-icon.png",
    fullImage: false,
    title: "",
    text: ""
  },
  {
    w: 150,
    h: 150,
    background: "#575756",
    image: "",
    fullImage: false,
    title: "Title",
    text: ""
  },
  {
    w: 300,
    h: 300,
    background: "white",
    image: "/img/test.png",
    fullImage: true,
    title: "",
    text: ""
  }

];

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 = ((x / WIDTH) + grid.length * WIDTH) % grid.length;
      const indexY = ((y / HEIGHT) + grid[0].length * HEIGHT) % grid[0].length;

      //maps from 0 to 3
      const i = indexX * 2 + indexY;

      layer.add(new Konva.Rect({
        x,
        y,
        width: WIDTH,
        height: HEIGHT,
        fill: grid[indexX][indexY],
        stroke: 'black',
        strokeWidth: 4
      }))

      if (blocks[i].title != "") {

        var complexText = new Konva.Text({
          x,
          y,
          text: "TEST TEXT",
          fontSize: 14,
          fontFamily: 'Calibri',
          fill: 'white',
          width: WIDTH,
          height: HEIGHT,
          verticalAlign: 'middle',
          align: "center"
        });

        layer.add(complexText);

      }
    }
  }

}

checkShapes();
layer.draw();

stage.on('dragend', () => {
  layer.destroyChildren();
  checkShapes();
  layer.draw();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.6.0/konva.min.js"></script>
<div id="container"></div>

具有标题的红色和蓝色的完整解决方案:

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']
];

const blocks = [{
    w: 150,
    h: 150,
    background: "white",
    image: "/img/test2.png",
    fullImage: false,
    title: "Title",
    text: ""
  },
  {
    w: 150,
    h: 150,
    background: "white",
    image: "/img/person-icon.png",
    fullImage: false,
    title: "",
    text: ""
  },
  {
    w: 150,
    h: 150,
    background: "#575756",
    image: "",
    fullImage: false,
    title: "",
    text: ""
  },
  {
    w: 300,
    h: 300,
    background: "white",
    image: "/img/test.png",
    fullImage: true,
    title: "Title",
    text: ""
  }

];

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 = ((x / WIDTH) + grid.length * WIDTH) % grid.length;
      const indexY = ((y / HEIGHT) + grid[0].length * HEIGHT) % grid[0].length;
      //maps from 0 to 3
      const i = indexX * 2 + indexY;

      layer.add(new Konva.Rect({
        x,
        y,
        width: WIDTH,
        height: HEIGHT,
        fill: grid[indexX][indexY],
        stroke: 'black',
        strokeWidth: 4
      }))

      if (blocks[i].title != "") {

        var complexText = new Konva.Text({
          x,
          y,
          text: "TEST TEXT",
          fontSize: 14,
          fontFamily: 'Calibri',
          fill: 'white',
          width: WIDTH,
          height: HEIGHT,
          verticalAlign: 'middle',
          align: "center"
        });

        layer.add(complexText);

      }
    }
  }

}

checkShapes();
layer.draw();

stage.on('dragend', () => {
  layer.destroyChildren();
  checkShapes();
  layer.draw();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.6.0/konva.min.js"></script>
<div id="container"></div>

镜像问题解决方案:

这是由于以下计算直接导致的:

const indexX = Math.abs(x / WIDTH) % grid.length;
const indexY = Math.abs(y / HEIGHT) % grid[0].length;

并解决:

const indexX = ((x/WIDTH) + grid.length * WIDTH )  % grid.length;
const indexY = ((y/HEIGHT) + grid.length * HEIGHT) % grid[0].length;

计算颜色时,将其基于网格数组:

  ['red', 'yellow', 'pink' ]
  ['green', 'blue' , 'gray' ]
  ['orange', 'blue' , 'black']

并且当您在逻辑上向下或向右(正值)前进时,没有问题,当您向上或向左(负值)前进时,一切都变了,因为使用Math.abs计算indexX和indexY。

例如,位于[-1,-1]的红色框与网格中的任何颜色都不匹配。根据您的公式,实际上它应该是“黑色”,而只是选择“蓝色”。