KonvaJS / HTML5 canvas 无限循环 tilemap。设置相机位置
KonvaJS / HTML5 canvas infinite looping tilemap. Setting camera position
我正在尝试创建一个基于主 'grid' 的无限循环 canvas。此处按比例缩小 fiddle,网格位于视口的中心。
在 fiddle 中,我的主要彩色方块网格位于中心,我希望它们在各个方向上无限平铺。显然这在现实中是不可能的,所以我想通过根据滚动方向重新绘制网格来给人一种无限的错觉。
https://gamedev.stackexchange.com/questions/71583/html5-dynamic-canvas-grid-for-scrolling-a-big-map
最好的方法似乎是获取拖动方向,然后将相机重置到该点,这样图层在主 canvas 视口下滚动,这意味着相机永远无法到达边缘主视口 canvas。
我一直致力于为鼠标拖动添加一些事件侦听器:
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
}
});
但我不能可靠地算出每个方向的坐标,然后如何重置相机位置。
根据需要 "infinite" canvas 我建议不要使用滚动并使 canvas 与用户视口一样大。然后你可以模拟相机并且在每次移动时,你需要在 canvas 上绘制一个新的网格。你只需要仔细计算网格的位置即可。
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.com/konva@^2/konva.min.js"></script>
<div id="container"></div>
如果您需要滚动,您可以在舞台上收听 wheel
事件并向所需方向移动。
我正在尝试创建一个基于主 'grid' 的无限循环 canvas。此处按比例缩小 fiddle,网格位于视口的中心。
在 fiddle 中,我的主要彩色方块网格位于中心,我希望它们在各个方向上无限平铺。显然这在现实中是不可能的,所以我想通过根据滚动方向重新绘制网格来给人一种无限的错觉。
https://gamedev.stackexchange.com/questions/71583/html5-dynamic-canvas-grid-for-scrolling-a-big-map
最好的方法似乎是获取拖动方向,然后将相机重置到该点,这样图层在主 canvas 视口下滚动,这意味着相机永远无法到达边缘主视口 canvas。
我一直致力于为鼠标拖动添加一些事件侦听器:
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
}
});
但我不能可靠地算出每个方向的坐标,然后如何重置相机位置。
根据需要 "infinite" canvas 我建议不要使用滚动并使 canvas 与用户视口一样大。然后你可以模拟相机并且在每次移动时,你需要在 canvas 上绘制一个新的网格。你只需要仔细计算网格的位置即可。
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.com/konva@^2/konva.min.js"></script>
<div id="container"></div>
如果您需要滚动,您可以在舞台上收听 wheel
事件并向所需方向移动。