根据坐标为某些网格切片上色

Color certain grid tiles based on coordinates(根据坐标为某些网格切片上色)
本文介绍了根据坐标为某些网格切片上色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想根据某些网格磁贴的坐标为其上色。

我创建了以下网格: 数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">

<!DOCTYPE html>
<html>

<head>
    <title>Color Tiles</title>
    <meta charset="utf-8" />
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css" />

    <style>
        body {
            padding: 0;
            margin: 0;
        }

        html,
        body,
        #map {
            height: 100%;
            width: 100%;
        }
    </style>
</head>

<body>

  <div id="map"></div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
    <script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet.js"></script>

    <!-- Make sure you put this AFtER leaflet.js, when using with leaflet 
    <script src="https://unpkg.com/leaflet-geosearch@3.0.0/dist/geosearch.umd.js"></script>
    -->

    <script>
        var map = new L.Map('map', { center: [10, 0], zoom: 2 });

        let zoomLevel = map.getZoom()
        console.log("zoomLevel " + zoomLevel)

        // if(zoomLevel === 1) {
            var tiles = new L.GridLayer();
            tiles.createTile = function (coords) {
                var tile = L.DomUtil.create('canvas', 'leaflet-tile');
                var ctx = tile.getContext('2d');
                var size = this.getTileSize()
                // console.log("size: " + size.toString())
                tile.width = size.x
                tile.height = size.y

                // calculate projection coordinates of top left tile pixel
                var nwPoint = coords.scaleBy(size)

                // calculate geographic coordinates of top left tile pixel
                var nw = map.unproject(nwPoint, coords.z)

                ctx.fillStyle = 'white';
                ctx.fillRect(0, 0, size.x, 50);
                ctx.fillStyle = 'black';
                ctx.fillText('x: ' + coords.x + ', y: ' + coords.y + ', zoom: ' + coords.z, 20, 20);
                ctx.fillText('lat: ' + nw.lat + ', lon: ' + nw.lng, 20, 40);
                ctx.strokeStyle = 'black';
                ctx.beginPath();
                ctx.moveTo(0, 0);
                ctx.lineTo(size.x - 1, 0);
                ctx.lineTo(size.x - 1, size.y - 1);
                ctx.lineTo(0, size.y - 1);
                ctx.closePath();
                ctx.stroke();
                return tile;
            }

            L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                attribution: 'Map data &copy; <a href="http://www.osm.org">OpenStreetMap</a>',
            }).addTo(map)

            tiles.addTo(map)
    
    </script>
</body>

</html>

我想要以下物品:

我尝试通过css直接设置样式,这似乎很管用。但是,我想根据提供的坐标设置样式。

有什么建议如何做到这一点吗?

推荐答案

什么类型的坐标?

查看您在回合游戏中使用地图的另一个问题,对于坐标的含义可能有些模棱两可。您可能指的是地理坐标(即纬度和经度),表示地图或地球仪上的。另一方面,您可能表示表示地图或地球上某个区域的磁贴(例如,第4行、第5列,位于特定磁贴集的缩放级别3)的坐标。我会仔细检查两种情况下的处理方法。

地理坐标

let内置了通过使用LatLngBounds.contains method检测特定LatLng coordinates是否在范围内的方法。

首先您可以定义一个按键坐标数组,然后根据它们创建传单LatLng objects:

var keyCoordinates = [
  [ -5.9, -123.9 ],
  [ -12, -28.5 ]
];
var leafletKeyCoordinates = keyCoordinates.map(function (c) {
  return new L.LatLng(c[0], c[1]);
});

要确定特定瓷砖的边界,可以计算瓷砖的西南角。此部分:

// calculate projection coordinates of top left tile pixel
var nwPoint = coords.scaleBy(size)
// calculate geographic coordinates of top left tile pixel
var nw = map.unproject(nwPoint, coords.z);

添加:

// calculate projection coordinates of bottom right tile pixel
var sePoint = nwPoint.add(size);
// calculate geographic coordinates of bottom right tile pixel
var se = map.unproject(sePoint, coords.z);
var bounds = new L.LatLngBounds(nw, se);

从那里,您可以使用每个平铺的边界来确定是否应该对其进行着色。您可以通过在画布上绘制或将类应用于平铺来完成此操作。对于使用画布的示例,在createTile的底部添加:

// if it contains any coordinates, it should be filled
var shouldShade = leafletKeyCoordinates.some(function (a) {
  return bounds.contains(a);
});
if (shouldShade) {
  ctx.fillStyle = 'rgba(0, 0, 240, 0.3)';
  ctx.fillRect(0, 0, size.x, size.y);
}

全部:

数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
<!DOCTYPE html>
<html>

<head>
    <title>Color Tiles</title>
    <meta charset="utf-8" />
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css" />

    <style>
        body {
            padding: 0;
            margin: 0;
        }

        html,
        body,
        #map {
            height: 100%;
            width: 100%;
        }
    </style>
</head>

<body>

  <div id="map"></div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
    <script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet.js"></script>

    <!-- Make sure you put this AFtER leaflet.js, when using with leaflet 
    <script src="https://unpkg.com/leaflet-geosearch@3.0.0/dist/geosearch.umd.js"></script>
    -->

    <script>
        var map = new L.Map('map', { center: [10, 0], zoom: 2 });

        let zoomLevel = map.getZoom()
        console.log("zoomLevel " + zoomLevel)

        var keyCoordinates = [
          [ -5.9, -123.9 ],
          [ -12, -28.5 ]
        ];
        var leafletKeyCoordinates = keyCoordinates.map(function (c) {
          return new L.LatLng(c[0], c[1]);
        });

        // if(zoomLevel === 1) {
            var tiles = new L.GridLayer();
            tiles.createTile = function (coords) {
                var tile = L.DomUtil.create('canvas', 'leaflet-tile');
                var ctx = tile.getContext('2d');
                var size = this.getTileSize()
                // console.log("size: " + size.toString())
                tile.width = size.x
                tile.height = size.y

                // calculate projection coordinates of top left tile pixel
                var nwPoint = coords.scaleBy(size)

                // calculate geographic coordinates of top left tile pixel
                var nw = map.unproject(nwPoint, coords.z)
                // calculate projection coordinates of bottom right tile pixel
                var sePoint = nwPoint.add(size);
                // calculate geographic coordinates of bottom right tile pixel
                var se = map.unproject(sePoint, coords.z);
                var bounds = new L.LatLngBounds(nw, se);

                ctx.fillStyle = 'white';
                ctx.fillRect(0, 0, size.x, 50);
                ctx.fillStyle = 'black';
                ctx.fillText('x: ' + coords.x + ', y: ' + coords.y + ', zoom: ' + coords.z, 20, 20);
                ctx.fillText('lat: ' + nw.lat + ', lon: ' + nw.lng, 20, 40);
                ctx.strokeStyle = 'black';
                ctx.beginPath();
                ctx.moveTo(0, 0);
                ctx.lineTo(size.x - 1, 0);
                ctx.lineTo(size.x - 1, size.y - 1);
                ctx.lineTo(0, size.y - 1);
                ctx.closePath();
                ctx.stroke();

                // if it contains any coordinates, it should be filled
                var shouldShade = leafletKeyCoordinates.some(function (a) {
                  return bounds.contains(a);
                });
                if (shouldShade) {
                  ctx.fillStyle = 'rgba(0, 0, 240, 0.3)';
                  ctx.fillRect(0, 0, size.x, size.y);
                }
return tile;
            }

            L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                attribution: 'Map data &copy; <a href="http://www.osm.org">OpenStreetMap</a>',
            }).addTo(map)

            tiles.addTo(map)
    
    </script>
</body>

</html>

平铺坐标

对于平铺,您可以直接查看列和行的coords.xcoords.y,以及缩放级别的coords.z。这种情况的棘手之处在于,如果存在不同的缩放级别,您的用户的缩放比例可能与您标识的磁贴的缩放比例不同。

var tileCoordinates = [
  [0, 3, 3], // x, y, and zoom of tile
  [28, 6, 5]
];
要在缩放级别之间进行转换,每个缩放级别会使平铺坐标加倍(例如,缩放级别4的平铺(0,2)由缩放级别5的平铺(0,4)、(0,5)、(1,4)、(1,5)表示))。我们可以使用Math.pow(2, targetZoom - coords.z)Math.pow(2, coords.z - targetZoom)来确定要乘以的因子。

var { x, y, z } = coords;
var shouldShade = tileCoordinates.some(function (c) {
  let [ tx, ty, tz] = c, multiple, sx, sy;
  if (z < tz) {
     // map is zoomed out from the target
     // you may just want to `return false;` here
     multiple = Math.pow(2, tz - z);
     sx = Math.floor(tx / multiple);
     sy = Math.floor(ty / multiple);
     return sx === x && sy === y; 
  } else if (z > tz) {
     // map is zoomed in from the target
     multiple = Math.pow(2, z - tz);
     sx = Math.floor(x / multiple);
     sy = Math.floor(y / multiple);
     return sx === tx && sy === ty; 
  }
  return tx === x && ty === y;
});

加在一起:

<!DOCTYPE html>
<html>

<head>
    <title>Color Tiles</title>
    <meta charset="utf-8" />
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css" />

    <style>
        body {
            padding: 0;
            margin: 0;
        }

        html,
        body,
        #map {
            height: 100%;
            width: 100%;
        }
    </style>
</head>

<body>

  <div id="map"></div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
    <script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet.js"></script>

    <!-- Make sure you put this AFtER leaflet.js, when using with leaflet 
    <script src="https://unpkg.com/leaflet-geosearch@3.0.0/dist/geosearch.umd.js"></script>
    -->

    <script>
        var map = new L.Map('map', { center: [10, 0], zoom: 2 });

        let zoomLevel = map.getZoom()
        console.log("zoomLevel " + zoomLevel)

        var tileCoordinates = [
          [0, 3, 3],
          [28, 6, 5]
        ];

        // if(zoomLevel === 1) {
            var tiles = new L.GridLayer();
            tiles.createTile = function (coords) {
                var tile = L.DomUtil.create('canvas', 'leaflet-tile');
                var ctx = tile.getContext('2d');
                var size = this.getTileSize()
                // console.log("size: " + size.toString())
                tile.width = size.x
                tile.height = size.y

                // calculate projection coordinates of top left tile pixel
                var nwPoint = coords.scaleBy(size)

                // calculate geographic coordinates of top left tile pixel
                var nw = map.unproject(nwPoint, coords.z)
                // calculate projection coordinates of bottom right tile pixel
                var sePoint = nwPoint.add(size);
                // calculate geographic coordinates of bottom right tile pixel
                var se = map.unproject(sePoint, coords.z);
                var bounds = new L.LatLngBounds(nw, se);

                ctx.fillStyle = 'white';
                ctx.fillRect(0, 0, size.x, 50);
                ctx.fillStyle = 'black';
                ctx.fillText('x: ' + coords.x + ', y: ' + coords.y + ', zoom: ' + coords.z, 20, 20);
                ctx.fillText('lat: ' + nw.lat + ', lon: ' + nw.lng, 20, 40);
                ctx.strokeStyle = 'black';
                ctx.beginPath();
                ctx.moveTo(0, 0);
                ctx.lineTo(size.x - 1, 0);
                ctx.lineTo(size.x - 1, size.y - 1);
                ctx.lineTo(0, size.y - 1);
                ctx.closePath();
                ctx.stroke();

                var { x, y, z } = coords;
                var shouldShade = tileCoordinates.some(function (c) {
                  let [ tx, ty, tz] = c, multiple, sx, sy;
                  if (z < tz) {
                    // map is zoomed out from the target
                    // you may just want to `return false;` here
                    multiple = Math.pow(2, tz - z);
                    sx = Math.floor(tx / multiple);
                    sy = Math.floor(ty / multiple);
                    return sx === x && sy === y; 
                  } else if (z > tz) {
                    // map is zoomed in from the target
                    multiple = Math.pow(2, z - tz);
                    sx = Math.floor(x / multiple);
                    sy = Math.floor(y / multiple);
                    return sx === tx && sy === ty; 
                  }
                  return tx === x && ty === y;
                });

                if (shouldShade) {
                  ctx.fillStyle = 'rgba(0, 0, 240, 0.3)';
                  ctx.fillRect(0, 0, size.x, size.y);
                }
return tile;
            }

            L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                attribution: 'Map data &copy; <a href="http://www.osm.org">OpenStreetMap</a>',
            }).addTo(map)

            tiles.addTo(map)
    
    </script>
</body>

</html>

这篇关于根据坐标为某些网格切片上色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Update another component when Formik form changes(当Formik表单更改时更新另一个组件)
Formik validation isSubmitting / isValidating not getting set to true(Formik验证正在提交/isValiating未设置为True)
React Validation Max Range Using Formik(使用Formik的Reaction验证最大范围)
Validation using Yup to check string or number length(使用YUP检查字符串或数字长度的验证)
Updating initialValues prop on Formik Form does not update input value(更新Formik表单上的初始值属性不会更新输入值)
password validation with yup and formik(使用YUP和Formick进行密码验证)