pixi-viewport icon indicating copy to clipboard operation
pixi-viewport copied to clipboard

Force to round values of hitArea when wheel or drag

Open serbol opened this issue 6 years ago • 8 comments

I need to round x, y, worldScreenWidth and worldScreenHeight value on drag and wheel. Are there any opportunities to perform it?

Currently on zoom end or drag end I get something like this : { height: 646.6777064089624, width: 862.2369418786166, x: 6.126561955558547e-14, y: 6.126561955558547e-14, }

But I want this: { height: 647, width: 862, x: 6, y: 6, }

serbol avatar Aug 23 '19 11:08 serbol

Try something like this:

    function round()
    {
        viewport.x = Math.round(viewport.x)
        viewport.y = Math.round(viewport.y)
        viewport.width = Math.round(viewport.width)
        viewport.height = Math.round(viewport.height)
    }

    viewport.on('moved-end', round)
    viewport.on('zoomed-end', round)

davidfig avatar Aug 23 '19 23:08 davidfig

Works fine on moved-end, but not on zoomed-end. Seems like there is no way to round viewport width or/and height.

serbol avatar Aug 25 '19 15:08 serbol

Hmmm...I checked the code, and I think the issue is with Math.round and the precision of rounding floating numbers.

If you add a console.log at the start and end of the round() function, you see that Math.round is being called on the width/height. You can find info and workarounds here: https://stackoverflow.com/questions/1458633/how-to-deal-with-floating-point-number-precision-in-javascript

Good luck!

davidfig avatar Aug 25 '19 23:08 davidfig

Actually, for me viewport.width === worldWidth? Is that ok? I think this parameter - worldScreenWidth need to be rounded.

serbol avatar Aug 26 '19 11:08 serbol

Ah, that may be a problem. worldScreenWidth is calculated, not directly set:

get worldScreenWidth
{
    return this.screenWidth / this.scale.x
}

You can reverse it and solve for this.scale.x to find the right value to round, but that likely will result in a floating point precision problem. Why does it need to be rounded?

davidfig avatar Aug 27 '19 03:08 davidfig

When I render a tiled-map I use container with sprites. One square sprite for each tile. On zoom in or zoom out I always get this net: Screen Shot 2019-08-27 at 10 41 13 AM That's because of float values for viewport width, height, x, y.

serbol avatar Aug 27 '19 07:08 serbol

I'm not sure I follow. The viewport is over the entire map. Why would its float value impact the locations of the sprites within containers within the viewport?

Just a thought: have you tried to extrude your sprite textures? I sometimes saw this issue when working with pixel graphics. I fixed it by extruding my textures (there's usually an option in your sspritesheet generator). Extruding pushes the color past the texture's edges so there's an extra pixel to work with when the scale changes.

davidfig avatar Aug 28 '19 00:08 davidfig

I had this function to create map:

const createMapSprite = mapData => {
    const mapContainer = new PIXI.Container();
    const tileSetImage = PIXI.Texture.from('/map/desert.png');
    let row, col, sprite, texture;
    mapData.layers.forEach(layer => {
        if(layer.type == 'tilelayer') {
            row = 0;
            col = 0;
            layer.data.forEach(index => {
                if(index > 0) {
                    texture = new PIXI.Texture(tileSetImage, new PIXI.Rectangle(getSourceX(index), getSourceY(index), mapData.tilewidth, mapData.tileheight));
                    sprite = new PIXI.Sprite(texture);
                    sprite.x = col * mapData.tilewidth;
                    sprite.y = row * mapData.tileheight;
                    mapContainer.addChild(sprite);
                }
                col++;
                if(col > (mapData.width - 1)) {
                    col = 0;
                    row++;
                }
            });
        }
    });

    return mapContainer;
};

Then I performed:

const mapCanvas = createMapSprite(desertMap);
viewport.addChild(mapCanvas);

I solved this issue by updating this line: sprite = new PIXI.Sprite(texture); -> sprite = new PIXI.TilingSprited(texture, mapData.tilewidth, mapData.tileheight);

But appeared freezes on move :-(

Ok, anyway, will try to play with sprite parameters.

serbol avatar Aug 28 '19 13:08 serbol