源碼分析之Leaflet中TileLayer

概述

TileLayerLayer 的子類,繼承自GridLayer基類,用于加載和顯示瓦片地圖。它提供了加載和顯示瓦片地圖的功能,支持自定義瓦片的 URL 格式和參數。

源碼分析

源碼實現

TileLayer的源碼實現如下:

export var TileLayer = GridLayer.extend({options: {minZoom: 0, // 最小縮放級別maxZoom: 18, // 最大縮放級別subdomains: "abc", // 子域名,用于分散請求,繞過瀏覽器的并發限制errorTileUrl: "", // 錯誤瓦片的URL,加載失敗時顯示的備用圖片URLzoomOffset: 0, // 縮放偏移量,調整請求中的z值tms: false,// 是否使用TMS格式,y軸反轉zoomReverse: false, // 是否反轉縮放級別detectRetina: false, // 是否檢測視網膜顯示,加載高分辨率瓦片crossOrigin: false, // 控制跨域請求referrerPolicy: false, // 防盜鏈策略},initialize: function (url, options) {this._url = url;options = Util.setOptions(this, options);if (options.detectRetina && Browser.retina && options.maxZoom > 0) {options.tileSize = Math.floor(options.tileSize / 2);if (!options.zoomReverse) {options.zoomOffset++;options.maxZoom = Math.max(options.minZoom, options.maxZoom - 1);} else {options.zoomOffset--;options.minZoom = Math.min(options.maxZoom, options.minZoom + 1);}options.minZoom = Math.max(0, options.minZoom);} else if (!options.zoomReverse) {options.maxZoom = Math.max(options.minZoom, options.maxZoom);} else {options.minZoom = Math.min(options.maxZoom, options.minZoom);}if (typeof options.subdomains === "string") {options.subdomains = options.subdomains.split("");}this.on("tileunload", this._onTileRemove);},setUrl: function (url, noRedraw) {if (this._url === url && noRedraw === undefined) {noRedraw = true;}this._url = url;if (!noRedraw) {this.redraw();}return this;},createTile: function (coords, done) {var tile = document.createElement("img");DomEvent.on(tile, "load", Util.bind(this._tileOnLoad, this, done, tile));DomEvent.on(tile, "error", Util.bind(this._tileOnError, this, done, tile));if (this.options.crossOrigin || this.options.crossOrigin === "") {tile.crossOrigin =this.options.crossOrigin === true ? "" : this.options.crossOrigin;}if (typeof this.options.referrerPolicy === "string") {tile.referrerPolicy = this.options.referrerPolicy;}tile.alt = "";tile.src = this.getTileUrl(coords);return tile;},getTileUrl: function (coords) {var data = {r: Browser.retina ? "@2x" : "",s: this._getSubdomain(coords),x: coords.x,y: coords.y,z: this._getZoomForUrl(),};if (this._map && !this._map.options.crs.infinite) {var invertedY = this._globalTileRange.max.y - coords.y;if (this.options.tms) {data["y"] = invertedY;}data["-y"] = invertedY;}return Util.template(this._url, Util.extend(data, this.options));},_tileOnLoad: function (done, tile) {if (Browser.ielt9) {setTimeout(Util.bind(done, this, null, tile), 0);} else {done(null, tile);}},_tileOnError: function (done, tile, e) {var errorUrl = this.options.errorTileUrl;if (errorUrl && tile.getAttribute("src") !== errorUrl) {tile.src = errorUrl;}done(e, tile);},_onTileRemove: function (e) {e.tile.onload = null;},_getZoomForUrl: function () {var zoom = this._tileZoom,maxZoom = this.options.maxZoom,zoomReverse = this.options.zoomReverse,zoomOffset = this.options.zoomOffset;if (zoomReverse) {zoom = maxZoom - zoom;}return zoom + zoomOffset;},_getSubdomain: function (tilePoint) {var index =Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length;return this.options.subdomains[index];},_abortLoading: function () {var i, tile;for (i in this._tiles) {if (this._tiles[i].coords.z !== this._tileZoom) {tile = this._tiles[i].el;tile.onload = Util.falseFn;tile.onerror = Util.falseFn;if (!tile.complete) {tile.src = Util.emptyImageUrl;var coords = this._tiles[i].coords;DomUtil.remove(tile);delete this._tiles[i];this.fire("tileabort", { tile, coords });}}}},_removeTile: function (key) {var tile = this._tiles[key];tile.el.setAttribute("src", Util.emptyImageUrl);return GridLayer.prototype._removeTile.call(this, key);},_tileReady: function (coords, err, tile) {if (!this._map ||(tile && tile.getAttribute("src") === Util.emptyImageUrl)) {return;}return GridLayer.prototype._tileReady.call(this, coords, err, tile);},
});export function tileLayer(url, options) {return new TileLayer(url, options);
}

源碼解析

initialize方法

initialize方法用于初始化TileLayer對象,設置默認選項和事件監聽器,保存URL末班

  • this._url:存儲瓦片圖層的URL。
  • options:用戶提供的選項,用于覆蓋默認選項。
  • options.detectRetina:如果啟用了視網膜檢測,將瓦片大小減半,并調整縮放級別和偏移量。
  • options.subdomains:如果是字符串,將其拆分為子域名數組。
  • this.on("tileunload", this._onTileRemove):監聽tileunload事件,當瓦片被卸載時調
方法詳解

setUrl(url,noRedraw):

  • 更新URL模版,若URL未變化且noRedrawtrue,則不重繪圖層。
  • 調用redraw()方法強制刷新,重新繪制圖層。

createTile(coords,done):

  • 創建一個新的HTML圖片元素作為瓦片。
  • 設置圖片元素的loaderror事件監聽器,當圖片加載完成或加載失敗時調用done回調函數。
  • 設置圖片元素的crossOrigin屬性,控制跨域請求。
  • 設置圖片元素的referrerPolicy屬性,控制防盜鏈策略。
  • 設置圖片元素的alt屬性為空字符串。
  • 設置圖片元素的src屬性為getTileUrl(coords)方法返回的URL
  • 返回創建的圖片元素。

getTileUrl(coords):

  • 計算并返回URL模版,將URL中的占位符替換為實際的值。
  • 占位符包括:
    • {r}:如果啟用了視網膜檢測,替換為@2x,否則為空字符串。
    • {s}:根據坐標計算子域名。
    • {x}:替換為X坐標。
    • {y}:替換為Y坐標。
    • {z}:替換為縮放級別。
    • {-y}:如果啟用了TMS格式,替換為反轉的Y坐標,否則為空字符串。
  • 返回替換后的URL

_tileOnLoad(done,tile):

  • 當圖片加載完成時調用done回調函數,IE9以下延遲觸發。

_tileOnError(done,tile,e):

  • 當圖片加載失敗時調用done回調函數,并設置錯誤信息。
  • 如果啟用了錯誤瓦片的URL,將圖片元素的src屬性設置為錯誤瓦片的URL,再次嘗試加載。
  • 返回錯誤信息。

_getZoomForUrl():

  • 根據zoomReversezoomOffset選項計算縮放級別。
  • 如果啟用了zoomReverse,將縮放級別反轉。
  • 返回計算后的縮放級別。
    _getSubdomain(tilePoint):
  • 根據XY坐標計算子域名。
  • 使用subdomains選項中的子域名數組,根據XY坐標的絕對值取模計算索引。
  • 返回計算得到的子域名。
瓦片管理

_abortLoading():中止非當前縮放級別的瓦片加載

  • 重置onload/onerror事件監聽器,
  • 將非當前縮放級別的瓦片的src屬性設置為空字符串,并從_tiles對象中移除。

_removeTile(key):

  • _tiles對象中移除指定鍵的瓦片。
  • 將瓦片的src屬性設置為空字符串,取消網絡請求。
  • 調用父類的_removeTile方法,移除瓦片元素。

_tileReady(coords,err,tile):

  • 當瓦片準備就緒時調用。
  • 如果URL為空字符串或_map不存在,返回。
  • 調用父類的_tileReady方法,處理瓦片就緒事件。
關鍵邏輯

??- Retina適配??:通過detectRetina自動調整瓦片尺寸和縮放,加載高分辨率圖片。

  • 子域名輪詢??:分散請求,避免瀏覽器并發限制。
  • ?TMS坐標反轉??:通過tms: true適配不同的瓦片服務標準。
  • 跨域處理??:通過crossOrigin屬性解決CORS問題,訪問像素數據。
  • 錯誤恢復??:加載失敗時顯示errorTileUrl,提升用戶體驗

總結

TileLayerLeaflet中用于加載和顯示瓦片地圖的核心組件,通過繼承GridLayer基類,實現了瓦片的加載和管理,支持自定義URL格式和參數,提供了豐富的功能和選項,適用于各種瓦片地圖服務。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/96751.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/96751.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/96751.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

php學習(第二天)

一.網站基本概念-服務器 1.什么是服務器? 1.1定義 服務器(server),也稱伺服器,是提供計算服務的設備。 供計算服務的設備” 這里的“設備”不僅指物理機器(如一臺配有 CPU、內存、硬盤的計算機),也可以指…

C++(友元和運算符重載)

目錄 友元: 友元函數: 示例: 友元類: 示例: 優點: 注意事項: 運算符重載: 注意: 示例: 友元: C中如果想要外部函數或者類對一個類的pr…

和平精英風格射擊游戲開發指南

本教程將完整講解如何開發一款和平精英風格的HTML射擊游戲,涵蓋核心設計理念、代碼架構與關鍵實現細節。 核心設計架構 游戲機制系統 角色控制系統:通過鍵盤實現玩家移動戰斗系統:子彈發射與碰撞檢測道具系統:武器、彈藥和醫療包收…

21.1 《24GB顯存搞定LLaMA2-7B指令微調:QLoRA+Flash Attention2.0全流程實戰》

24GB顯存搞定LLaMA2-7B指令微調:QLoRA+Flash Attention2.0全流程實戰 實戰 LLaMA2-7B 指令微調 一、指令微調技術背景 指令微調(Instruction Tuning)是大模型訓練中的關鍵技術突破點。與傳統全量微調(Full Fine-Tuning)相比,指令微調通過特定格式的指令-響應數據訓練,…

周志華《機器學習導論》第10章 降維與度量學習

https://www.lamda.nju.edu.cn/aml24fall/slides/Chap10.pptx 目錄 1.MDS (Multiple Dimensional Scaling) 多維縮放方法 2. 主成分分析 (Principal Component Analysis, PCA) 2.1 凸優化證明 2.2 人臉識別降維應用 3. 核化PCA 4. 流行學習 4.1 LLE 局部線性嵌入&#…

Kubernetes 彈性伸縮:深入講解 HPA 和 VPA

1. 介紹 Kubernetes 提供了多種資源管理方式,其中 彈性伸縮(Auto-scaling)是最重要的特性之一。彈性伸縮可以根據應用的負載變化自動調整 Pod 的數量和資源,以確保在高負載下應用能夠正常運行,而在低負載時節省資源。在…

大數據畢業設計選題推薦-基于大數據的家庭能源消耗數據分析與可視化系統-Hadoop-Spark-數據可視化-BigData

?作者主頁:IT畢設夢工廠? 個人簡介:曾從事計算機專業培訓教學,擅長Java、Python、PHP、.NET、Node.js、GO、微信小程序、安卓Android等項目實戰。接項目定制開發、代碼講解、答辯教學、文檔編寫、降重等。 ?文末獲取源碼? 精彩專欄推薦?…

【Spring】原理解析:Spring Boot 自動配置的核心機制與實戰剖析

一、引言在當今的 Java 開發領域,Spring Boot 憑借其快速搭建項目、簡化配置等優勢,成為了眾多開發者的首選框架。而 Spring Boot 自動配置作為其核心特性之一,極大地提升了開發效率,讓開發者能夠更專注于業務邏輯的實現。本文將深…

Java forEach中不能用i++的原因以及代替方案

因為在 Lambda 表達式內部訪問的外部局部變量必須是 final 或 effectively final(事實最終變量),而 i 操作試圖改變這個變量的值,違反了這一規定。下面我們來詳細拆解這個問題,讓你徹底明白。1. 一個具體的例子我們先看…

第十四屆藍橋杯青少組C++選拔賽[2023.1.15]第二部分編程題(2 、尋寶石)

參考程序&#xff1a;#include <bits/stdc.h> using namespace std;int main() {int N;cin >> N; // 讀入盒子數vector<int> a(N);for (int i 0; i < N; i) cin >> a[i]; // 讀入每個盒子的寶石數// N > 3&#xff08;題目保證&#x…

9120 部 TMDb 高分電影數據集 | 7 列全維度指標 (評分 / 熱度 / 劇情)+API 權威源 | 電影趨勢分析 / 推薦系統 / NLP 建模用

一、引言在影視行業分析與數據科學實踐中&#xff0c;高分電影數據的深度挖掘已成為平臺優化內容推薦、制片方研判市場趨勢、影迷發現優質作品的核心支撐 —— 通過上映年份與評分的關聯可捕捉電影質量演變、依托熱度與投票數能定位爆款潛質、結合劇情概述可開展情感與主題分析…

Tomcat PUT方法任意寫文件漏洞學習

1 PUT請求 PUT請求是一種在HTTP協議中常見的請求方法 1.1 基本原理 PUT請求是一種用于向指定資源位置上傳新的實體數據的請求方法&#xff0c;與其他請求方法的區別在于&#xff0c;PUT請求用于創建或者更新只當資源位置的實體數據。它與GET請求不同&#xff0c;PUT請求會替換掉…

【C++基礎】初識模板——一起步入泛型編程的大門

引言在 C 世界里&#xff0c;模板&#xff08;Template&#xff09;就像一把萬能鑰匙。它允許你編寫通用的代碼&#xff0c;讓編譯器在需要的時候為具體類型生成對應的函數或類。換句話說&#xff0c;模板是 C 泛型編程&#xff08;Generic Programming&#xff09; 的基石。 如…

項目管理框架如何影響團隊協作

在項目執行過程中&#xff0c;項目管理框架不僅是一套工具和流程&#xff0c;更是團隊協作方式的基礎。不同的項目管理框架會深刻影響團隊溝通效率、任務分配、決策方式和整體協同效果。 傳統框架通常強調層級與計劃&#xff0c;帶來高度規范化的協作&#xff1b;敏捷框架則強調…

正向代理,反向代理,負載均衡還有nginx

這是一個非常核心且重要的后端/運維知識領域。我會用盡可能清晰易懂的方式&#xff0c;結合生動的比喻&#xff0c;為你詳細梳理這些概念。核心概念一覽我們先從一個宏觀的角度來理解它們之間的關系&#xff1a;代理&#xff08;Proxy&#xff09;&#xff1a; 一個中間人的角色…

WebSocket壓縮傳輸優化:機器視覺高清流在DCS中的低延遲方案

引言在現代工業自動化領域&#xff0c;分布式控制系統&#xff08;DCS&#xff09;正面臨著前所未有的數據挑戰。隨著機器視覺技術的廣泛應用&#xff0c;高清視頻流已成為監控產品質量、檢測設備異常和保障生產安全的重要手段。然而&#xff0c;將720P、1080P甚至4K分辨率的高…

《Linux常見命令》

ls 功能&#xff1a;列出目錄下的子目錄與文件&#xff0c;對于文件&#xff0c;還會列出文件名及其他信息。 語法&#xff1a;ls [選項] [目錄或文件] 1.常用選項及說明選項說明-a列出目錄下的所有文件&#xff0c;包括以 . 開頭的隱含文件-d將目錄象文件一樣顯示&#xff0c;…

Python數據分析:函數定義時的位置參數。

目錄1 代碼示例2 歡迎糾錯3 免費爬蟲4 論文寫作/Python 學習智能體1 代碼示例 直接上代碼。 def pargs1(a, b):"""先看確定數量的位置參數。最簡單的位置參數。a和b都叫而且只能叫“位置參數”。所謂確定數量&#xff0c;很明顯&#xff0c;是兩個就是兩個&…

《沒有架構圖?用 netstat、ss、tcpdump 還原服務連接與數據流向》

&#x1f4e2; 你是否遇到過這些問題&#xff1f; 接手一個老項目&#xff0c;只有服務器賬號&#xff0c;沒有架構圖&#xff1f;服務突然異常&#xff0c;但不知道它依賴哪些外部系統&#xff1f;想畫數據流向圖&#xff0c;卻找不到文檔&#xff1f; 別擔心&#xff01;只要…

Redis列表(List):實現隊列/棧的利器,底層原理與實戰

Redis列表&#xff08;List&#xff09;&#xff1a;實現隊列/棧的利器&#xff0c;底層原理與實戰 1. Redis列表概述 1.1 什么是Redis列表 Redis列表&#xff08;List&#xff09;是一個有序的字符串元素集合&#xff0c;支持在頭部和尾部進行高效的插入和刪除操作。它可以…