Advertisement

How to pin zoom at location

Started by July 30, 2015 02:28 PM
0 comments, last by Alberth 9 years, 6 months ago

I have a map that I can scroll (drag with mouse) and zoom.

Im trying to implement this function:


static void PinScrollZoomAtMapPos(Vector2 mapPos_p, ScrollRect scroll_p)
    {
        // this is to make a point on the map always in the same place on the
        // screen, regardless of current zoom

        Vector2 scrolledMapPos = new Vector2(
               mapPos_p.x + scroll_p.content.localPosition.x,
               mapPos_p.y + scroll_p.content.localPosition.y
               );

        Vector2 scrolledZoomedMapPos = new Vector2(
               mapPos_p.x * scroll_p.content.localScale.x + scroll_p.content.localPosition.x,
               mapPos_p.y * scroll_p.content.localScale.y + scroll_p.content.localPosition.y
               );

        Vector2 diff = scrolledMapPos - scrolledZoomedMapPos;

        Debug.Log("diff: " + diff);

        Vector2 offseted = new Vector2(
            scroll_p.content.localPosition.x + diff.x,
            scroll_p.content.localPosition.y + diff.y
            );

        scroll_p.content.localPosition = offseted;
    }

(The scroll_p.content is the map.)

Although I think my logic makes sense at first, I see how it will never work, the 'diff' var should return 0 after subsequent calls to this function, but since I move the map pos, it will never happen. I dont know what I have to do..

Now doing this:


static void PinScrollZoomAtMapPos(Vector2 mapPos_p, ScrollRect scroll_p)
    {
        // this is to make a point on the map always in the same place on the
        // screen, regardless of current zoom

        //Vector2 scrolledMapPos = new Vector2(
        //       mapPos_p.x + scroll_p.content.localPosition.x,
        //       mapPos_p.y + scroll_p.content.localPosition.y
        //       );

        Vector2 scrolledZoomedMapPos = new Vector2(
               mapPos_p.x * scroll_p.content.localScale.x + scroll_p.content.localPosition.x,
               mapPos_p.y * scroll_p.content.localScale.y + scroll_p.content.localPosition.y
               );

        Vector2 diff = mapPos_p - scrolledZoomedMapPos;

        Debug.Log("diff: " + diff);

        Vector2 offseted = new Vector2(
            scroll_p.content.localPosition.x + diff.x,
            scroll_p.content.localPosition.y + diff.y
            );

        scroll_p.content.localPosition = offseted;
    }

Works, but the map becomes un-scrollable. I want to account only for zoom, like ignore the displace caused by the zoom (since it enlarges the map from the center).

Note this is different from centralizing the map at pos. The pin can be at any place, for example at 80% bottom right of the screen, say theres a city there, I want the city to keep at the exact same place on the screen, while I zoom in/out.

I feel is such a simple thing to do,yet Im struggling with this since yesterday.

Indeed, it should be quite trivial.

Have you tried fractions?

Zoom only changes how much of the map is displayed at the screen. Imagine one dimension (eg horizontal), from the left of the displayed area to the point has length X1, and from the point to the right edge of the displayed has length Y1. When you change zoom, the distances change to X2 and Y2 respectively, where X1 + Y1 != X2 + Y2 (otherwise you have the same area displayed, ie zoom didn't change).

I think the trick here is to keep the fractions X1 / (X1 + Y1) and X2 / (X2 + Y2) the same. The total length of X1 + Y1 is different from X2 + Y2, but both sides of the point change 'at the same relative rate', so the point in the middle stays at the same position, relative to the start (or in 2D, relative to the top-left edge of the display).

This topic is closed to new replies.

Advertisement