如何在 Mapbox GL 中修复画布大小?

Posted

技术标签:

【中文标题】如何在 Mapbox GL 中修复画布大小?【英文标题】:How to fix canvas size in Mapbox GL? 【发布时间】:2017-06-28 06:28:00 【问题描述】:

我正在使用 Mapbox GL 显示地图并从其中心裁剪固定大小的图像。它适用于我设计的特定分辨率(1920x1080),但是当我开始使页面响应时,地图样式widthheight 发生变化,画布大小也开始发生变化!

因此,当我裁剪图像时,尺寸应该始终不同,因为 900 像素画布上的 300 像素与 2000 像素画布上的 300 像素不同的地图区域。如果我在 Chrome 中将设备类型从桌面更改为移动设备,画布大小甚至会发生巨大变化。

有什么方法可以在使用 CSS 属性缩放整个地图时固定画布 DOM 大小,就像在普通的 canvas 上所做的那样?我尝试做trackResize: false 并且画布 DOM 大小保持固定,但地图也没有缩放以适应容器。

【问题讨论】:

谢谢你问这个家伙,让我免于脱发哈哈哈 【参考方案1】:

我不知道这是否会对某人有所帮助,但由于某种原因,桌面中窗口的设备像素比为 1,而在移动设备中则不同。

如果您试图让您的地图具有响应性,并且当您更改为移动设备时它会出现问题,那是因为您的设备像素比率因一个平台与另一个平台不同。

尝试使用以下方法获取您的设备像素比:

window.devicePixelRatio

并使用它。

在我的例子中,我正在使用片段着色器尝试使用地图上的位置和缩放的组合来绘制圆圈。但是,由于片段着色器使用 canvas.width(而不是 canvas.clientWidth)工作,当我切换到移动设备时,代表 100 米的像素数量发生了变化,我使用设备像素比,然后使用设备像素将更大数量的像素转换为米比...

如果有人在 MapboxGL-JS 片段着色器和像素到米的转换方面遇到问题:

uniform float u_dpr; // the window.devicePixelRatio

//v_rad is radius in meters
//40075017.0 circunference of earth
//cos(-0.296) is based on my latitude
//etc.. 
//multiply the final value by the pixel ratio to get responsiveness working 

float maxDist = (v_rad / (40075017.0*cos(-0.296)/pow(2.0, (u_zoom+9.0)))*u_dpr);

【讨论】:

【参考方案2】:
map.on('idle',function()
map.resize()
)

试试这个。它对我来说很好用。(仅适用于 mapbox 用户)

【讨论】:

【参考方案3】:

我正在使用 angular 9,这对我有用: ngAfterViewInit() setTimeout(() => this.buildMap(), 2000);

【讨论】:

【参考方案4】:

根据@davejoem 的回答,通过在buildMap() 函数之外放置一个setTimeout,我能够在不拉伸的情况下显示完整的地图高度。我不必使用invalidateSize(),因为它会引发此错误:

错误 TS2339:“地图”类型上不存在属性“invalidateSize”。

但是,我不得不将buildMap()setTimeout 放在ngAfterViewInit() 函数中,并将2000 放在setTimeout 的第二个参数上,因为有时硬刷新时,地图不是全高。

希望这有助于彻底解决问题。

【讨论】:

【参考方案5】:

我最好的方法是在加载之前使地图的大小无效,强制它自行调整大小。

在角度/离子中

import  AfterViewInit, Component, OnInit  from '@angular/core'
import * as  mapboxgl from 'mapbox-gl'

@Component(
  selector: 'app-map',
  templateUrl: 'map.page.html',
  styleUrls: ['map.page.scss']
)
export class MapPage implements AfterViewInit, OnInit 
  private map: mapboxgl.Map  

  constructor() 
    mapboxgl.accessToken = "<YOUR_TOKEN>"
  

  ngOnInit() 
    setTimeout(() => this.buildMap(), 0);
  

  ngAfterViewInit() 
    setTimeout(() => this.map.invalidateSize(), 0);
  

  buildMap() 
    let conf = 
      container: 'map',
      style: '<YOUR_CUSTOM_STYLE>'
      zoom: 13,
      center: [lng, lat]
    
    this.map = new mapboxgl.Map(conf)  
    // Add map controls
    this.map.addControl(new mapboxgl.NavigationControl())
  

【讨论】:

发现此选项有效,但用户仍然可以注意到地图大小的突然增加(尤其是在速度较慢的设备上。最简单和最全面的方法是将 css 添加到基本索引中。如 mapbox-gl 文档中所示,head 部分中的 html 文件 您可以链接到您提到的文档中的部分吗?还有,你为什么用setTimeout?为什么不立即运行?这是我不熟悉的 Angular 模式吗? 老兄,我不明白为什么,但这是有效的,即使不使用 map.invalidateSize (属性 invalidateSize 在“地图”类型上不存在)。我认为关键是setTimeout,但我不明白为什么。【参考方案6】:

解决办法

<div
    ref=el => this.mapContainer = el
    style=
            position: 'absolute',
            top: 0,
            bottom: 0,
            width: '100%',
            height: '100vh',
     
 />

【讨论】:

这是一个特定角度的解决方案吗? 不,仅适用于 React js,但您可以实现。神奇的是宽度和高度 这没有回答问题,这是关于显示的地图区域的问题。另外我不确定您为什么要混合%vh的单位,这与解决方案无关【参考方案7】:

对于版本:“mapbox-gl”:“^1.2.1”,为画布地图容器类设置高度:

.mapboxgl-canvas-container 

    height: 100vh;


然后在地图加载事件上:

onMapLoaded(event) 

    event.map.resize();


【讨论】:

虽然它确实调整了地图的大小,但它发生在用户的眼前【参考方案8】:

如果我理解正确,您希望地图始终显示地理区域,无论地图容器有多大或多小?这与大多数 web 地图的标准行为相反,后者保持比例不变,并扩大或缩小覆盖区域。

如果这是您想要的,您可以通过在调整窗口大小时调用map.fitBounds() 来实现它。

【讨论】:

他们在问如何设置画布相对于 DOM 的高度和宽度,而不是在地图内。

以上是关于如何在 Mapbox GL 中修复画布大小?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Mapbox GL JS动画中为LineString分段着色不同

如何将 mapbox-gl-draw 导入 Angular 2/4?

如何在 mapbox-gl-js 中以某些缩放级别隐藏点标签?

如何在 Angular 8 项目中导入 Mapbox GL Draw

如何在 mapbox-gl-js 中为源指定授权标头?

如何在 mapbox-gl 中为图层文本字段添加背景颜色