源码分析之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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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;支持在头部和尾部进行高效的插入和删除操作。它可以…