flauwekeul / honeycomb

Create hex grids easily, in node or the browser.
https://abbekeultjes.nl/honeycomb
MIT License
638 stars 59 forks source link

pointToHex returns hex below the point when point is above the grid #45

Closed tracymedcalf closed 4 years ago

tracymedcalf commented 4 years ago

When I click the blank space above the hex grid, I would expect Grid.pointToHex to return a hex not in the grid, but instead it returns the hex below it.

Below is an adaptation of one of the documentation's JSFiddle examples that demonstrates what I mean.

const app = new PIXI.Application({ transparent: true, antialias: true })
const graphics = new PIXI.Graphics()

const Hex = Honeycomb.extendHex({ size: 5 })
const Grid = Honeycomb.defineGrid(Hex)

document.body.appendChild(app.view)
// set a line style of 1px wide and color #999
graphics.lineStyle(1, 0x999999)

// render 10,000 hexes
const grid = Grid.rectangle({ width: 100, height: 100 });
grid.forEach(hex => {
    const point = hex.toPoint()
    // add the hex's position to each of its corner points
    const corners = hex.corners().map(corner => corner.add(point))
    // separate the first from the other corners
    const [firstCorner, ...otherCorners] = corners

    // move the "pencil" to the first corner
    graphics.moveTo(firstCorner.x, firstCorner.y)
    // draw lines to the other corners
    otherCorners.forEach(({ x, y }) => graphics.lineTo(x, y))
    // finish at the first corner
    graphics.lineTo(firstCorner.x, firstCorner.y)

    app.stage.addChild(graphics)
})

document.addEventListener('click', ({offsetX, offsetY}) =>
       // should output undefined when I click the blank space above the grid
    console.log(grid.get(Grid.pointToHex(offsetX, offsetY)))
)

I appreciate your library, by the way.

flauwekeul commented 4 years ago

That's weird behavior indeed. However, when I make the hexes larger (with a radius of about 10 or greater), the problem seems to disappear. I'll spend some more time later.

tracymedcalf commented 4 years ago

The simple workaround for me was to simply change document.addEventListener to container.addEventListener, where container is a div holding the grid. That way clicking outside of the div won't trigger the weird behavior.

As for changing the size, it depends on what hex you click above. In the below code, clicking above the 7th hex allows me to reproduce the problem, whereas clicking above the 8th will output "undefined" to the console.

const app = new PIXI.Application({ transparent: true, antialias: true })
const graphics = new PIXI.Graphics()

const Hex = Honeycomb.extendHex({ size: 15 })
const Grid = Honeycomb.defineGrid(Hex)

document.body.appendChild(app.view)
// set a line style of 1px wide and color #999
graphics.lineStyle(1, 0x999999)

// render 10,000 hexes
const grid = Grid.rectangle({ width: 10, height: 10 });
grid.forEach(hex => {
    const point = hex.toPoint()
    // add the hex's position to each of its corner points
    const corners = hex.corners().map(corner => corner.add(point))
    // separate the first from the other corners
    const [firstCorner, ...otherCorners] = corners

    // move the "pencil" to the first corner
    graphics.moveTo(firstCorner.x, firstCorner.y)
    // draw lines to the other corners
    otherCorners.forEach(({ x, y }) => graphics.lineTo(x, y))
    // finish at the first corner
    graphics.lineTo(firstCorner.x, firstCorner.y)

    app.stage.addChild(graphics)
})

document.addEventListener('click', ({offsetX, offsetY}) =>
       // should output undefined when I click the blank space above the grid
    console.log(grid.get(Grid.pointToHex(offsetX, offsetY)))
)
flauwekeul commented 4 years ago

Ah, that makes sense. If you add the event listener to the document and the container has an offset relative to the document (there's a default 8px margin on the <body> tag), your clicks are going to be 8px off.

So, I guess this solves your issue?

tracymedcalf commented 4 years ago

Yep. Thanks!