参考文章:
1.国内主要地图瓦片坐标系定义及计算原理 | CntChen Blog
2.Unity LBS地图(瓦片地图,不接入任何SDK)_099_F11的博客-CSDN博客_unity离线地图
瓦片:高德等地图厂商把 世界地图分成了 好多张图片,每张图片就是一个瓦片
实现思路,根据 https 连接 请求对应 经纬度的瓦片,然后把他们拼接起来
代码实现:此代码只是一个demo,只有平移,没有缩放(效果太差)
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class Location
{
public static LatLng mLatLng = null;
public static IEnumerator SetMap(int x,int y, Image image,int zoom)
{
string _path = string.Format("http://webrd01.is.autonavi.com/appmaptile?x={0}&y={1}&z={2}&lang=zh_cn&size=1&scale=1&style=8", x, y, zoom);
//string.Format("http://online1.map.bdimg.com/onlinelabel/?qt=tile&x={0}&y={1}&z=18", x, y);
//string.Format("https://wprd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={0}&y={1}&z=16&scl=1<ype=1", x, y);
WWW www = new WWW(_path);
while (!www.isDone)
{
yield return null;
}
image.sprite = Sprite.Create(www.texture, new Rect(0, 0, LocationMap.TileWidthAndHeigth, LocationMap.TileWidthAndHeigth), new Vector2(0.5f, 0.5f));//www.texture;SpriteRenderer.sprite.pivot
}
public static IEnumerator InitLocationPos()
{
#if !UNITY_EDITOR
if (!Input.location.isEnabledByUser)
{
Debug.LogError("Location is not enabled");
yield break;
}
#endif
Input.location.Start(1,1);
int maxWait = 30;
while (Input.location.status == LocationServiceStatus.Initializing && maxWait > 0)
{
yield return new WaitForSeconds(1);
maxWait--;
}
if (maxWait < 1)
{
Debug.LogError("Location time out");
yield break;
}
if (Input.location.status == LocationServiceStatus.Failed)
{
yield break;
}
else
{
mLatLng = new LatLng(Input.location.lastData.longitude, Input.location.lastData.latitude);
Input.location.Stop();
}
}
/// <summary>
/// 将tile(瓦片)坐标系转换为LatLngt(地理)坐标系,pixelX,pixelY为图片偏移像素坐标
/// </summary>
/// <param name="tileX"></param>
/// <param name="tileY"></param>
/// <param name="zoom"></param>
/// <param name="pixelX"></param>
/// <param name="pixelY"></param>
/// <returns></returns>
public static LatLng TileXYToLatLng(int tileX, int tileY, int zoom, int pixelX = 0, int pixelY = 0)
{
double size = Math.Pow(2, zoom);
double pixelXToTileAddition = pixelX / LocationMap.TileWidthAndHeigth;
double lng = (tileX + pixelXToTileAddition) / size * 360.0 - 180.0;
double pixelYToTileAddition = pixelY / LocationMap.TileWidthAndHeigth;
double lat = Math.Atan(Math.Sinh(Math.PI * (1 - 2 * (tileY + pixelYToTileAddition) / size))) * 180.0 / Math.PI;
return new LatLng(lng, lat);
}
/// <summary>
/// 将LatLngt地理坐标系转换为tile瓦片坐标系,pixelX,pixelY为图片偏移像素坐标
/// </summary>
/// <param name="latlng"></param>
/// <param name="zoom"></param>
/// <param name="tileX"></param>
/// <param name="tileY"></param>
/// <param name="pixelX"></param>
/// <param name="pixelY"></param>
public static TileInfo LatLngToTileXY(LatLng latlng, int zoom)
{
double size = Math.Pow(2, zoom);
double x = ((latlng.Longitude + 180) / 360) * size;
double lat_rad = latlng.Latitude * Math.PI / 180;
double y = (1 - Math.Log(Math.Tan(lat_rad) + 1 / Math.Cos(lat_rad)) / Math.PI) / 2;
y = y * size;
int tileX = (int)x;
int tileY = (int)y;
return new TileInfo(tileX, tileY, (int)((x - tileX) * LocationMap.TileWidthAndHeigth), (int)((y - tileY) * LocationMap.TileWidthAndHeigth));
}
}
public class LatLng
{
public double Longitude;
public double Latitude;
public LatLng(double longitude, double latitude)
{
Longitude = longitude;
Latitude = latitude;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 滑动方向枚举
/// </summary>
public enum Direction
{
up,
down,
left,
right
}
/// <summary>
/// 瓦片信息类
/// </summary>
public class TileInfo
{
public int TileX { get; set; }
public int TileY { get; set; }
public int PixelX { get; set; }
public int PixelY { get; set; }
public TileInfo(int tileX, int tileY, int pixelX, int pixelY)
{
TileX = tileX;
TileY = tileY;
PixelX = pixelX;
PixelY = pixelY;
}
}
public class TileImageInfo
{
public int TileX { get; set; }
public int TileY { get; set; }
public GameObject Go { get; set; }
public TileImageInfo(int tileX, int tileY,GameObject go)
{
TileX = tileX;
TileY = tileY;
Go = go;
}
}
/// <summary>
/// 此类中 有两个坐标系,
/// 一个是瓦片地图 的坐标
/// 一个是实例化prefab 把瓦片地图 负值的gameobject 坐标
/// </summary>
public class LocationMap : MonoBehaviour
{
//为什么设置成256*256,因为高的返回的图就是256的,还有一种类型是512*512
public static float TileWidthAndHeigth = 256;
public int TileZoom = 16;
//加载的Image 的缩放
public static float TileScale = 1;
[SerializeField]
private GameObject TileMap;
private List<TileImageInfo> TileMaps = null;
//中心 瓦片信息类
private TileInfo m_centerTileInfo = null;
//最好是正方形,容易计算,目前没处理 非正方形
//瓦片行数
public readonly int TileRow = 7;
//瓦片列数
public readonly int TileColumn = 5;
private void Awake()
{
TileScale = TileMap.transform.localScale.x;
}
private void Start()
{
StartCoroutine(InitTileInfo());
}
private IEnumerator InitTileInfo()
{
yield return Location.InitLocationPos();
if (Location.mLatLng != null)
{
LatLng latLng = Location.mLatLng;
#if UNITY_EDITOR
//测试数据
latLng = new LatLng(116.483988, 39.990255);
#endif
if (latLng == null) yield break;
m_centerTileInfo = Location.LatLngToTileXY(latLng, TileZoom);
InitAllTile();
}
}
private void InitAllTile()
{
//求的 左上角的 x 和 y的 瓦片值
int x = m_centerTileInfo.TileX - (TileColumn - 1) / 2;
int y = m_centerTileInfo.TileY - (TileRow - 1) / 2;
//左上角Image 图片的坐标
Vector3 sour = new Vector3(0 - TileWidthAndHeigth * (TileColumn - 1)/2 * TileScale, 0 + TileWidthAndHeigth * (TileRow - 1)/2 * TileScale, 0);
TileMaps = new List<TileImageInfo>(TileRow * TileColumn);
TileImageInfo[] gameObjects = new TileImageInfo[TileRow * TileColumn];
for (int i = 0; i < TileRow; i++)
{
for (int j = 0; j < TileColumn; j++)
{
GameObject g = Instantiate(TileMap, transform);
g.transform.localPosition = sour + new Vector3(j * TileWidthAndHeigth * TileScale, 0, 0);
//求取瓦片地图横向坐标
int _x = x + j;
//加载瓦片地图
StartCoroutine(Location.SetMap(_x, y, g.GetComponent<Image>(), TileZoom));
//瓦片Image 存入数组
gameObjects[j + i * TileColumn] = new TileImageInfo(_x, y, g);
g.SetActive(true);
}
//
y += 1;
//
sour -= new Vector3(0, TileWidthAndHeigth * TileScale, 0);
}
TileMaps.AddRange(gameObjects);
}
/// <summary>
/// 更新瓦片位置
/// </summary>
/// <param name="direction"></param>
public void MapUpdate(Direction direction = Direction.up)
{
int x;
int y;
switch (direction)
{
case Direction.up:
//下向上更新
x = m_centerTileInfo.TileX - (TileColumn - 1) / 2;
y = m_centerTileInfo.TileY - (TileRow - 1) / 2 - 1;
for (int i = 0; i < TileColumn; i++)
{
//把最后一排搬到第一排
TileImageInfo info = TileMaps[i + TileColumn * (TileRow - 1)];
info.Go.transform.localPosition += new Vector3(0, TileWidthAndHeigth * TileRow * TileScale, 0);
info.TileX = x;
info.TileX = y;
StartCoroutine(Location.SetMap(x, y, info.Go.GetComponent<Image>(), TileZoom));
x++;
//冒泡
for (int j = 1; j <= TileRow - 1; j++)
{
int index1 = i + TileColumn * (TileRow - j);
int index2 = i + TileColumn * (TileRow - j - 1);
TileImageInfo temp = TileMaps[index1];
TileMaps[index1] = TileMaps[index2];
TileMaps[index2] = temp;
}
}
m_centerTileInfo.TileY--;
break;
case Direction.down:
x = m_centerTileInfo.TileX - (TileColumn - 1) / 2;
y = m_centerTileInfo.TileY + (TileRow - 1) / 2 + 1;
for (int i = 0; i < TileColumn; i++)
{
//把第一排搬到最后一排
TileImageInfo info = TileMaps[i];
info.Go.transform.localPosition -= new Vector3(0, TileWidthAndHeigth * TileRow * TileScale, 0);
info.TileX = x;
info.TileX = y;
StartCoroutine(Location.SetMap(x, y, info.Go.GetComponent<Image>(), TileZoom));
x++;
//冒泡
for (int j = 0; j < TileRow - 1; j++)
{
int index1 = i + TileColumn * j;
int index2 = i + TileColumn * (j + 1);
TileImageInfo temp = TileMaps[index1];
TileMaps[index1] = TileMaps[index2];
TileMaps[index2] = temp;
}
}
m_centerTileInfo.TileY++;
break;
case Direction.left:
x = m_centerTileInfo.TileX - (TileColumn - 1) / 2 - 1;
y = m_centerTileInfo.TileY - (TileRow - 1) / 2;
for (int i = 0; i < TileRow; i++)
{
//把最右列移到最左列
TileImageInfo info = TileMaps[i * TileColumn + (TileColumn - 1)];
info.Go.transform.localPosition -= new Vector3(TileWidthAndHeigth * TileColumn * TileScale, 0, 0);
info.TileX = x;
info.TileX = y;
StartCoroutine(Location.SetMap(x, y, info.Go.GetComponent<Image>(), TileZoom));
y++;
//冒泡
for (int j = 1; j <= TileColumn - 1; j++)
{
int index1 = i * TileColumn + (TileColumn - j);
int index2 = i * TileColumn + (TileColumn - j - 1);
TileImageInfo temp = TileMaps[index1];
TileMaps[index1] = TileMaps[index2];
TileMaps[index2] = temp;
}
}
m_centerTileInfo.TileX--;
break;
case Direction.right:
x = m_centerTileInfo.TileX + (TileColumn - 1) / 2 + 1;
y = m_centerTileInfo.TileY - (TileRow - 1) / 2;
for (int i = 0; i < TileRow; i++)
{
//把最左列移到最右列
TileImageInfo info = TileMaps[i * TileColumn];
info.Go.transform.localPosition += new Vector3(TileWidthAndHeigth * TileColumn * TileScale, 0, 0);
info.TileX = x;
info.TileX = y;
StartCoroutine(Location.SetMap(x, y, info.Go.GetComponent<Image>(), TileZoom));
y++;
//冒泡
for (int j = 0; j < TileColumn - 1; j++)
{
int index1 = i * TileColumn + j;
int index2 = i * TileColumn + (j + 1);
TileImageInfo temp = TileMaps[index1];
TileMaps[index1] = TileMaps[index2];
TileMaps[index2] = temp;
}
}
m_centerTileInfo.TileX++;
break;
}
//每次修改 释放资源
Resources.UnloadUnusedAssets();
}
}
using UnityEngine;
using UnityEngine.EventSystems;
public class MapPosManager : MonoBehaviour,IDragHandler,IBeginDragHandler,IEndDragHandler
{
[SerializeField]
private GameObject Map;
//上次拖拽的位置
Vector2 DragPos;
private bool isDrag = false;
//更新 地图的 位置边界
private float lx;
private float rx;
private float ty;
private float by;
//每次位置变化大小
private float changeSzie;
//是否移动
private float DragFlag = 50f;
//地图
private LocationMap map;
private void Start()
{
map = Map.GetComponent<LocationMap>();
changeSzie = LocationMap.TileWidthAndHeigth * LocationMap.TileScale;
//初始化 边界
lx = changeSzie;
rx = -changeSzie;
ty = -changeSzie;
by = changeSzie;
}
void Update()
{
//注意 没有滑动时 不计算
if (!isDrag) return;
if (Map.transform.localPosition.x > lx)
{
map.MapUpdate(Direction.left);
lx += changeSzie;
rx += changeSzie;
}
if (Map.transform.localPosition.x < rx)
{
map.MapUpdate(Direction.right);
rx -= changeSzie;
lx -= changeSzie;
}
if (Map.transform.localPosition.y < ty)
{
map.MapUpdate(Direction.up);
ty -= changeSzie;
by -= changeSzie;
}
if (Map.transform.localPosition.y > by)
{
map.MapUpdate(Direction.down);
by += changeSzie;
ty += changeSzie;
}
}
public void OnBeginDrag(PointerEventData eventData)
{
DragPos = eventData.position;
}
public void OnDrag(PointerEventData eventData)
{
if (Input.touchCount == 2) return;
Vector2 offset = (eventData.position - DragPos).normalized;
Map.transform.position += new Vector3(offset.x, offset.y , 0) * DragFlag;
DragPos = eventData.position;
isDrag = true;
}
public void OnEndDrag(PointerEventData eventData)
{
isDrag = false;
}
}
创建ui面板,挂上脚本, 其中tileMap 为Image文章来源:https://www.toymoban.com/news/detail-631528.html
文章来源地址https://www.toymoban.com/news/detail-631528.html
到了这里,关于基于高德地图 瓦片 实现 unity lbs的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!