如何根据 GMap.NET 中的缩放级别调整自定义标记的大小?

How to resize custom markers depending on zoom level in GMap.NET?

我正在创建 GMap.NET 应用程序并在其上添加了一些自定义标记。是否可以让它们根据地图的缩放级别进行缩放?

您将需要创建自定义 GMapMarker 并使用 OnRender() 中的缩放级别来缩放图像。每个缩放级别都有不同的比例,但幸运的是,我已经对它们进行了测量。不确定该比例是否随不同的地图提供商而变化?

您可以使用单独的线程设置 x/y 比例和航向,它会实时更新。

“defaultZoomLevel”将设置图像具有 1:1 比率的缩放级别。我只尝试过值 16,不确定它是否适用于其他值,您可能需要计算每个值的所有比率或从数据中提取曲线并使用它来缩放比率。

使用它来设置更改时的缩放级别:

private void Gmap_OnMapZoomChanged()
{
    //trackBar_Zoom.Value = (int)Gmap.Zoom;
    //label_Zoom.Text = "Zoom: " + trackBar_Zoom.Value.ToString();
    SelectedOverlay?.SetZoomLevel(Gmap.Zoom);
}

像这样使用它:

SelectedOverlay = new GMapMarkerImageOverlay(Gmap.Position, 0, 1, 1, Gmap.Zoom, Resources.GreySquare);          
Overlay_ImageOverlays.Markers.Add(SelectedOverlay);

这是地图标记:

public class GMapMarkerImageOverlay : GMapMarker
{
    private readonly double deg2rad = 3.14159265 / 180.0;
    private readonly double rad2deg = 180 / 3.14159265;
    private readonly float defaultZoomLevel = 16;
    private float zoomRatio = 1f;

    private float heading = 0;
    private double zoom = 0;
    private float scaleX = 0;
    private float scaleY = 0;

    private Bitmap overlayImage;

    private void SetZoomRatio()
    {
        if (zoom < 12) 
        {
            zoomRatio = 0.045f;
        }
        else if (zoom == 12)
        {
            zoomRatio = 0.08f;
        }
        else if (zoom == 13)
        {
            zoomRatio = 0.155f;
        }
        else if (zoom == 14)
        {
            zoomRatio = 0.285f;
        }
        else if (zoom == 15)
        {
            zoomRatio = 0.53f;
        }
        else if (zoom == 16)
        {
            zoomRatio = 1f;
        }
        else if (zoom == 17)
        {
            zoomRatio = 1.88f;
        }
        else if (zoom == 18)
        {
            zoomRatio = 3.55f;
        }
        else if (zoom == 19)
        {
            zoomRatio = 6.75f;
        }
        else if (zoom == 20)
        {
            zoomRatio = 11.5f;
        }
        else 
        {
            zoomRatio = 11.5f;
        }
    }

    public GMapMarkerImageOverlay(PointLatLng p, float heading, float scaleX, float scaleY, double zoom, Bitmap image)
        : base(p)
    {
        overlayImage = image;
        this.heading = heading;
        this.scaleX = scaleX;
        this.scaleY = scaleY;
        this.zoom = zoom;
        SetZoomRatio();
    }

    internal void SetPosition(PointLatLng position)
    {
        //Position = position;
        //LocalPosition = position;
    }

    public void SetHeading(float h)
    {
        heading = h;
    }

    public void SetZoomLevel(double z)
    {
        zoom = z;
        SetZoomRatio();
        //Util.Log($"Zoom level: {z}");
    }

    public void SetScaleX(float x)
    {
        scaleX = x;
    }

    public void SetScaleY(float y)
    {
        scaleY = y;
    }

    public void SetRatio(float r)
    {
        zoomRatio = r;
    }

    public override void OnRender(Graphics g)
    {
        try
        {                
            var temp = g.Transform;
            g.TranslateTransform(LocalPosition.X, LocalPosition.Y);

            float ratio = (float)zoom / defaultZoomLevel;

            ratio *= zoomRatio;

            g.ScaleTransform(scaleX*ratio, scaleY*ratio);
           
            base.ToolTipMode = MarkerTooltipMode.OnMouseOver;
           
            base.ToolTipText = $"Ratio:{ratio}";

            // anti NaN
            try
            {
                g.RotateTransform(heading);
            }
            catch
            {

            }           
        
            var sIcon = overlayImage;
            sIcon = new Bitmap(sIcon, sIcon.Width / 1, sIcon.Height / 1);
            g.DrawImageUnscaled(sIcon, sIcon.Width / -2, sIcon.Height / -2);   

            g.Transform = temp;
        }
        catch (Exception ex) 
        {
            //Util.Log(ex);
        }
    }
}