Canvas无限滚动映射对象位置
Canvas Infinite Scroll mapping object location
试图让无限循环滚动在 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();
})
解释:
问题是 i
的计算。它需要基于 indexX
和 indexY
的值
像这样:
//maps from 0 to 3
const i = indexX * 2 + indexY;
当观察你的 blocks 数组时,只有一个有标题,它位于 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] 的红色框与网格中的任何颜色都不匹配。根据您的公式,它会简单地选择 'blue' 颜色,而实际上它应该是 'black' 颜色。
试图让无限循环滚动在 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();
})
解释:
问题是 i
的计算。它需要基于 indexX
和 indexY
像这样:
//maps from 0 to 3
const i = indexX * 2 + indexY;
当观察你的 blocks 数组时,只有一个有标题,它位于 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] 的红色框与网格中的任何颜色都不匹配。根据您的公式,它会简单地选择 'blue' 颜色,而实际上它应该是 'black' 颜色。