在 Vue2-Leaflet 上反转 L:CRS.Simple 地图的 Y 轴 [英] Invert Y axis of L:CRS.Simple map on Vue2-Leaflet

查看:39
本文介绍了在 Vue2-Leaflet 上反转 L:CRS.Simple 地图的 Y 轴的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Vue2-Leaflet 的 L.CRS.Simple 开发地图应用程序,并且我想按照

...但你希望它看起来像...

(如果 Y 坐标以 L.LatLngs 的简写形式首先列出,请重新阅读

然而,对于计算机程序员来说,Y 坐标会下降,因为

为了解决这个问题,Leaflet 实现了 仿射转换(考虑到缩放级别的传单怪癖),然后 L.CRS.Simple 使用这样的仿射变换来反转 Y 坐标(所以 L.CRS.Simple像笛卡尔平面而不是像素平面一样工作):

L.CRS.Simple = L.Util.extend({}, L.CRS, {投影:L.Projection.LonLat,转换:L.Transformation(1, 0, -1, 0),/* 剪辑 */

这相当于指定一个仿射变换矩阵,如

( 1 0 )( 0 -1 )

因此,考虑到这一点,您的问题的答案就变成了您应该使用自定义仿射变换定义一个新的 CRS,将 1 个单位的 «纬度» 映射到 1 个向下的像素".

此时,您应该阅读关于扩展传单类的传单教程,但 TL;DR 版本是:

var CRSPixel = L.Util.extend(L.CRS.Simple, {转换:新的 L.Transformation(1,0,1,0)});

然后将传递该自定义 CRS 的地图定义为地图的 crs 选项,一切都应该正常工作.这是一个使用 vanilla Leaflet 的工作示例(即 vue-less)

有了这些信息,您应该能够使该技术适应您的 Vue 代码,注意导入所有需要的 Leaflet 位.

I am developing a map application using L.CRS.Simple of Vue2-Leaflet, and I want to invert the y-axis of my map as explained in the Leaflet documentation. I found a similar question here, and it seems my problem is the same, so my question is: how do I integrate the same solution that inverts the y-axis but using the vue2-leaflet package?

This is my code:

<template>
<body>
  <div>
    <li v-for="(message, index) in messageList" :item="message" :key="index">
      {{ message }}
    </li>
  </div>
  <l-map class="map" ref="map" :min-zoom="minZoom" :crs="crs">
    <l-tile-layer :url="url"></l-tile-layer>
    <!-- <l-image-overlay :url="url" :bounds="bounds" /> -->
    <l-grid-layer class="grid" :tile-component="tileComponent"></l-grid-layer>
    <l-marker v-for="star in stars" :key="star.id" :lat-lng="star">
      <l-icon
        :icon-size="[25, 25]"
        icon-url="https://image.flaticon.com/icons/png/512/304/304378.png"
      ></l-icon>
      <!-- <l-icon :icon-size="[32, 37]" icon-url="/images/star.png"></l-icon> -->
      <l-popup class="popup">
        <em class="popup-bold">Name: </em>{{ star.name }}<br>
        <em class="popup-bold">Longitud: </em>{{ star.lng }}<br>
        <em class="popup-bold">Latitud: </em>-{{ star.lat }}<br>
      </l-popup>
    </l-marker>
  </l-map>  
</body>
</template>

<script>
import L from "leaflet";
import { CRS } from "leaflet";
import {
  LMap,
  LTileLayer,
  LMarker,
  LImageOverlay,
  LPopup,
  LPolyline,
  LIcon,
  LGridLayer
} from "vue2-leaflet";

export default {
  name: "Map",
  components: {
    LMap,
    LTileLayer,
    LMarker,
    LImageOverlay,
    LPopup,
    LPolyline,
    LIcon,
    LGridLayer
  },
  props: {
    msg: {
      type: String
    }
  },
  data() {
    return {
      url: "https://wallpaperboat.com/wp-content/uploads/2019/10/high-resolution-black-background-08.jpg",
      bounds: [
        [-2600, -2700],[1000, 3000]
      ],
      minZoom: 0.5,
      crs: L.CRS.Simple,
      stars: [],
      messageList: [],
      tileComponent: {
        name: "tile-component",
        props: {
          coords: {
            type: Object,
            required: true
          }
        },
        template: '<div style="outline:1px solid #38c9d386; height:40rem; width:40rem;"></div>'
      }
    };
  },
  watch: {
    msg: function() {
      this.messageList.push(this.msg);
    }
  },
  mounted() {
    this.$refs.map.mapObject.setView([526, -68], 1);

    this.$http
      .get("https://pyet2m3rzl.execute-api.us-east-1.amazonaws.com/test/outscapebackend")
      .then(response => {
        return response.json();
      })
      .then(data => {
        const resultArray = [];
        for (let key in data) {
          resultArray.push(data[key]);
        }
        this.stars = resultArray;
      });
  },
  methods: {}
};
</script>

<style scoped>
...
</style>

解决方案

If I'm understanding this right, you want to invert the Y coordinate of all L.LatLngs, and not just the tile coordinates (which is the TMS use case), so that Y coordinates grow when going down. In other words, if I have something like...

L.marker([0,0]).addTo(map).bindPopup('y=0,x=0', {autoClose:false}).openPopup();
L.marker([100,50]).addTo(map).bindPopup('y=100,x=50', {autoClose:false}).openPopup();

...the default looks like...

...but you want it to look like...

(If the fact that the Y coordinate is listed first in the shorthand form of L.LatLngs, re-read the Leaflet tutorial on L.CRS.Simple where the issue is explained, as well as lon lat lon lat lon).

A bit of explanation about the Leaflet internals: a Leaflet CRS translates LatLng coordinates into pixel coordinates. e.g. in the default L.CRS.EPSG3857, the screen Y coordinate depends on the cosine of the latitude to get a traverse cylindrical projection.

With L.CRS.Simple this translation also exists, because of a quirky disparity. For mathematicians, the Y coordinate goes up because that's how a cartesian plane works:

However, for computer programmers, the Y coordinate goes down because that's how pixels are indexed on screens (at least, that's been the convention for decades):

In order to get around this quirk, Leaflet implements affine transformations (which take into account the Leaflet quirks for zoom levels), and then L.CRS.Simple uses such an affine transformation to invert the Y coordinate (so L.CRS.Simple works like a cartesian plane instead of a pixel plane):

L.CRS.Simple = L.Util.extend({}, L.CRS, {
    projection: L.Projection.LonLat,
    transformation: L.Transformation(1, 0, -1, 0),
    /* snip */

This is equivalent to specifying an affine transformation matrix like

( 1  0 )
( 0 -1 )

So, with this in mind, the answer to your question becomes "you should define a new CRS with a custom affine transformation that maps 1 unit of «latitude» into 1 downwards pixel".

At this point, you should read the Leaflet tutorial on extending Leaflet classes, but the TL;DR version of that is:

var CRSPixel = L.Util.extend(L.CRS.Simple, {
    transformation: new L.Transformation(1,0,1,0)
});

Then define the map passing that custom CRS as the map's crs option, and everything should work. Here's a working example with vanilla Leaflet (i.e. vue-less)

With this information, you should be able to adapt the technique to your Vue code, taking a bit of care to import all the needed Leaflet bits.

这篇关于在 Vue2-Leaflet 上反转 L:CRS.Simple 地图的 Y 轴的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆