源码分析之Openlayers样式篇IconImage类

访问Openlayers网站(https://jinuss.github.io/Openlayers_map_pages/,网站是基于Vue3 + Openlayers,里面有大量的实践和案例。觉得还不错,可以在这里插入图片描述 给个小星星Star,鼓励一波 https://github.com/Jinuss/OpenlayersMap哦~

概述

在 Openlayers 中,IconImage类主要用于表示一个图标图像对象,它包含了图像的各种信息,如图像本身、尺寸、源 URL、跨域访问设置、颜色、状态等。它继承自 EventTarget类,意味着 IconImage 实例可以作为事件目标,允许事件监听和触发。

关于EventTarget类,可以参考这篇文章源码分析之Openlayers的核心EventTarget类的实现

源码分析

IconImage类的源码实现

IconImage类的源码实现如下:

class IconImage extends EventTarget {constructor(image, src, crossOrigin, imageState, color) {super();this.hitDetectionImage_ = null;this.image_ = image;this.crossOrigin_ = crossOrigin;this.canvas_ = {};this.color_ = color;this.imageState_ = imageState === undefined ? ImageState.IDLE : imageState;this.size_ =image && image.width && image.height ? [image.width, image.height] : null;this.src_ = src;this.tainted_;this.ready_ = null;}initializeImage_() {this.image_ = new Image();if (this.crossOrigin_ !== null) {this.image_.crossOrigin = this.crossOrigin_;}}isTainted_() {if (this.tainted_ === undefined && this.imageState_ === ImageState.LOADED) {if (!taintedTestContext) {taintedTestContext = createCanvasContext2D(1, 1, undefined, {willReadFrequently: true,});}taintedTestContext.drawImage(this.image_, 0, 0);try {taintedTestContext.getImageData(0, 0, 1, 1);this.tainted_ = false;} catch (e) {taintedTestContext = null;this.tainted_ = true;}}return this.tainted_ === true;}dispatchChangeEvent_() {this.dispatchEvent(EventType.CHANGE);}handleImageError_() {this.imageState_ = ImageState.ERROR;this.dispatchChangeEvent_();}handleImageLoad_() {this.imageState_ = ImageState.LOADED;this.size_ = [this.image_.width, this.image_.height];this.dispatchChangeEvent_();}getImage(pixelRatio) {if (!this.image_) {this.initializeImage_();}this.replaceColor_(pixelRatio);return this.canvas_[pixelRatio] ? this.canvas_[pixelRatio] : this.image_;}getPixelRatio(pixelRatio) {this.replaceColor_(pixelRatio);return this.canvas_[pixelRatio] ? pixelRatio : 1;}getImageState() {return this.imageState_;}getHitDetectionImage() {if (!this.image_) {this.initializeImage_();}if (!this.hitDetectionImage_) {if (this.isTainted_()) {const width = this.size_[0];const height = this.size_[1];const context = createCanvasContext2D(width, height);context.fillRect(0, 0, width, height);this.hitDetectionImage_ = context.canvas;} else {this.hitDetectionImage_ = this.image_;}}return this.hitDetectionImage_;}getSize() {return this.size_;}getSrc() {return this.src_;}load() {if (this.imageState_ !== ImageState.IDLE) {return;}if (!this.image_) {this.initializeImage_();}this.imageState_ = ImageState.LOADING;try {if (this.src_ !== undefined) {this.image_.src = this.src_;}} catch (e) {this.handleImageError_();}if (this.image_ instanceof HTMLImageElement) {decodeFallback(this.image_, this.src_).then((image) => {this.image_ = image;this.handleImageLoad_();}).catch(this.handleImageError_.bind(this));}}replaceColor_(pixelRatio) {if (!this.color_ ||this.canvas_[pixelRatio] ||this.imageState_ !== ImageState.LOADED) {return;}const image = this.image_;const ctx = createCanvasContext2D(Math.ceil(image.width * pixelRatio),Math.ceil(image.height * pixelRatio));const canvas = ctx.canvas;ctx.scale(pixelRatio, pixelRatio);ctx.drawImage(image, 0, 0);ctx.globalCompositeOperation = "multiply";ctx.fillStyle = asString(this.color_);ctx.fillRect(0, 0, canvas.width / pixelRatio, canvas.height / pixelRatio);ctx.globalCompositeOperation = "destination-in";ctx.drawImage(image, 0, 0);this.canvas_[pixelRatio] = canvas;}ready() {if (!this.ready_) {this.ready_ = new Promise((resolve) => {if (this.imageState_ === ImageState.LOADED ||this.imageState_ === ImageState.ERROR) {resolve();} else {const onChange = () => {if (this.imageState_ === ImageState.LOADED ||this.imageState_ === ImageState.ERROR) {this.removeEventListener(EventType.CHANGE, onChange);resolve();}};this.addEventListener(EventType.CHANGE, onChange);}});}return this.ready_;}
}export function get(image, cacheKey, crossOrigin, imageState, color, pattern) {let iconImage =cacheKey === undefined? undefined: iconImageCache.get(cacheKey, crossOrigin, color);if (!iconImage) {iconImage = new IconImage(image,image && "src" in image ? image.src || undefined : cacheKey,crossOrigin,imageState,color);iconImageCache.set(cacheKey, crossOrigin, color, iconImage, pattern);}if (pattern &&iconImage &&!iconImageCache.getPattern(cacheKey, crossOrigin, color)) {iconImageCache.set(cacheKey, crossOrigin, color, iconImage, pattern);}return iconImage;
}

IconImage类的构造函数

IconImage类的构造函数内部就是初始化了一些属性,如下:

  • this.hitDetectionImage_:用于在进行图像点击检测时使用备用图像,默认为null

  • this.image_:设置 image_ 为传入的图像对象,用于存储图标的实际图像

  • this.crossOrigin_:设置 crossOrigin_ 为传入的跨域访问设置,用于处理图像加载时的跨域问题

  • this.canvas:初始化一个空的 canvas_ 对象,可能用于后续图像的绘制或缓存

  • this.color:设置图标的颜色属性,通常用于为图标添加颜色或修改现有颜色

  • this.imageState_:设置 imageState_ 为图像的当前状态,若没有提供 imageState,则默认为 ImageState.IDLE,表示图像处于待机状态。

  • this.size_:如果传入的 image 对象具有 widthheight 属性,则 size_ 被设置为图像的宽高数组 [width, height],否则设置为 null,表示图像没有明确的尺寸信息。

  • this.src_:设置 src_ 为传入的图像源 URL,用于指向图标图像的位置。

  • this.tainted_:初始化 tainted_ 属性,但未赋值。这个属性可能用于标记图像是否“污染”,通常与跨域图像加载有关,当图像的跨域访问被限制时,可能会被标记为污染。

  • this.ready:初始化 ready_null,该属性可能用于标识图像是否准备好,可以用于图像加载状态的判断.

IconImage类的主要方法

  • initializeImage_()方法:初始化图像,就是实例化一个Image对象,然后判断,若this.crossOrigin不为null,则将它设置成Image对象实例也就是属性this.image_crossOrigin的属性值。

  • isTainted_()方法:用于检测图像是否由于跨域问题或安全策略而被污染。如果图像污染了,开发者就不能读取它的像素数据,这通常会影响一些图像处理或绘制操作。检测原理就是将其绘制到画布上,然后通过getImageData方法获取元素,若可以获取,则说明没有被污染;最后返回一个布尔值。

  • dispatchChangeEvent_()方法:内部就是调用父类的this.dispatchEvent方法

  • handleImageError_()方法:处理图片加载错误会调用该方法,会将this.imageState_标识为错误状态,然后调用this.dispatchChangeEvent_方法

  • handleImageLoad_()方法:图片加载完成会被调用,会将this.imageState_标识为已加载状态以及设置this.size图片的大小,然后调用this.dispatchChangeEvent_方法

  • getImage(pixelRatio)方法:根据像素比获取图片,先判断,若this.image_不存在,则调用this.initializeImage_进行初始化,然后调用this.replaceColor_方法,进行创建该像素比下的图像canvas,若该图像存在则返回,否则返回this.image_

  • getPixelRatio(pixelRatio)方法:类似getImage(pixelRatio)方法,返回的是像素比,若this.canvas中不存在该像素比的图片,就返回1

  • getImageState()方法:获取图像的状态

  • getHitDetectionImage()方法:如果图像未被污染,则返回原始图像;如果图像被污染,则返回一个替代的命中检测图像,这个替代图像的主要作用是用来进行交互检测。

  • getSize()方法:获取图像的大小,即this.size_

  • getSrc()方法:获取图像源

  • load()方法:负责加载图像,设置图像源,并处理加载过程中的成功或失败。该方法负责加载图像。它检查图像的当前状态,并在图像尚未加载时开始加载过程。经过一系列检查后,使用 decodeFallback 方法尝试解码图像。如果成功,调用 handleImageLoad_() 处理图像加载成功的逻辑。如果失败,调用 handleImageError_() 处理错误

  • replaceColor_(pixelRatio)方法:在图像上应用颜色,并处理高分辨率屏幕上的显示

  • ready()方法:返回一个 Promise,该 Promise 在图像加载完成后解决(或者在加载失败时解决)。它用于确保图像加载完成后执行某些操作

get函数

get函数通过使用一个图标图像缓存(iconImageCache),高效地管理图标图像的创建和获取。

  • 如果图标图像已经缓存,则直接返回缓存中的图标图像。

  • 如果图标图像未缓存,则创建新的 IconImage 对象并将其存入缓存。

  • 该函数还会根据提供的参数(如颜色和图案)对图标图像进行处理,并确保图案的正确缓存。

通过这种方式,图标图像能够避免重复创建,提高性能,同时还支持跨域、颜色替换、图案应用等特性

总结

本文主要介绍了IconImage类的核心逻辑,涉及到图像的加载,以及错误处理、状态变更等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/67863.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【mptcp】ubuntu18.04和MT7981搭建mptcp测试环境操作说明

目录 安装ubuntu18.04,可以使用虚拟机安装... 2 点击安装VMware Tool 2 更新ubuntu18.04源... 4 安装ifconfig指令工具包... 5 安装vim工具包... 5

MySQL数据库入门到大蛇尚硅谷宋红康老师笔记 基础篇 part 6

第06章_多表查询 多表查询,也称为关联查询,指两个或更多个表一起完成查询操作。 这些一起查询的表之间是有关系的(一对一、一对多),它们之间一定是有关联字段,这个 关联字段可能建立了外键,也…

FANUC机器人系统镜像备份与恢复的具体步骤(图文)

FANUC机器人系统镜像备份与恢复的具体步骤(图文) 镜像备份: 如下图所示,进入文件—工具—切换设备,找到插入的U盘UT1, 如下图所示,进入U盘目录后,创建目录,这里目录名称为11, 如下图所示࿰

根除埃博拉病毒(2015MCM美赛A)

题目 要求: 现实、合理、可用要求考虑到: a. 疾病传播 b.药物数量 c. 传送系统 d.传送位置 e. 药物或者疫苗的生产速度一个非技术性文件 论文 参考论文 概述 两个模型,stochastic和deterministic。 分析思路:基于现实的数据建立…

多线程之旅:开启多线程安全之门的钥匙

上次,小编分享到了多线程出现了安全问题。 那么接下来小编来分享下是如何解决这个多线程安全问题的。 上次分享到,多线程安全问题的“罪魁祸首”:线程调度的不确定性。 就是说呢,A、B、C三个线程,然后,A…

Docker 单机快速部署大数据各组件

文章目录 一、Spark1.1 NetWork 网络1.2 安装 Java81.3 安装 Python 环境1.4 Spark 安装部署 二、Kafka三、StarRocks四、Redis五、Rabbitmq六、Emqx6.1 前言6.2 安装部署 七、Flink八、Nacos九、Nginx 一、Spark 1.1 NetWork 网络 docker network lsdocker network create -…

设计模式的艺术-职责链模式

行为型模式的名称、定义、学习难度和使用频率如下表所示: 1.如何理解职责链模式 最常见的职责链是直线型,即沿着一条单向的链来传递请求。链上的每一个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并让请求沿着…

代码工艺:实践 Spring Boot TDD 测试驱动开发

TDD 的核心理念是 “先写测试,再写功能”,其过程遵循一个严格的循环,即 Red-Green-Refactor: TDD 的流程 1. Red(编写失败的测试) 根据需求,先编写一个测试用例,描述期望的行为。…

面试-二维数组

应用 快递业务有N个站点&#xff0c;1<N<10000&#xff1b;站点0、站点1可达&#xff0c;记作0-1&#xff1b;如果0-1、1-2&#xff0c;则站点0、站点2可达&#xff0c;记作0-2&#xff1b;s[i][j]1表示i-j可达&#xff0c;反之s[i][j]0表示i-j不可达&#xff1b;s[i][j…

CSDN 博客之星 2024:默语的技术进阶与社区耕耘之旅

CSDN 博客之星 2024&#xff1a;默语的技术进阶与社区耕耘之旅 &#x1f31f; 默语&#xff0c;是一位在技术分享与社区建设中坚持深耕的博客作者。今年&#xff0c;我有幸再次入围成为 CSDN 博客之星TOP300 的一员&#xff0c;这既是对过往努力的肯定&#xff0c;也是对未来探…

k8s namespace绑定节点

k8s namespace绑定节点 1. apiserver 启用准入控制 PodNodeSelector2. namespace 添加注解 scheduler.alpha.kubernetes.io/node-selector3. label node 1. apiserver 启用准入控制 PodNodeSelector vim /etc/kubernetes/manifests/kube-apiserver.yaml spec:containers:- co…

Mysql的数据类型(学习自用)

一、整数型数据类型 名称大小&#xff08;字节数&#xff09;范围(无符号&#xff09;范围&#xff08;有符号&#xff09;TINYINT10-255-2^8~2^8-1SMALLINT20-65535-2^16~2^16-1MEDIUMINT30-2^24-1-2^24~2^24-1INT40-2^32-1-2^32~2^32-1BIGINT80-2^64-1-2^64~2^64-1 二、浮点…

深入 Flutter 和 Compose 的 PlatformView 实现对比,它们是如何接入平台控件

在上一篇《深入 Flutter 和 Compose 在 UI 渲染刷新时 Diff 实现对比》发布之后&#xff0c;收到了大佬的“催稿”&#xff0c;想了解下 Flutter 和 Compose 在 PlatformView 实现上的对比&#xff0c;恰好过去写过不少 Flutter 上对于 PlatformView 的实现&#xff0c;这次恰好…

winfrom项目,引用EPPlus.dll实现将DataTable 中的数据保存到Excel文件

最近研究不安装office也可以保存Excel文件&#xff0c;在网上查询资料找到这个方法。 第一步&#xff1a;下载EPPlus.dll文件&#xff08;自行去网上搜索下载&#xff09; 第二步&#xff1a;引用到需要用的项目中&#xff0c;如图所示&#xff1a; 第三步&#xff1a;写代码…

暑期实习准备:C语言

1.局部变量和全局变量 局部变量的作用域是在变量所在的局部范围&#xff0c;全局变量的作用域是整个工程&#xff1b;局部变量的生命周期是作用域内&#xff0c;全局变量的生命周期是整个程序的生命周期&#xff0c;当两者命名冲突时&#xff0c;优先使用的是局部变量。 2.C语言…

OGG 19C 集成模式启用DDL复制

接Oracle19C PDB 环境下 OGG 搭建&#xff08;PDB to PDB&#xff09;_cdb架构 配置ogg-CSDN博客&#xff0c;给 pdb 环境 ogg 配置 DDL 功能。 一个报错 SYShfdb1> ddl_setup.sqlOracle GoldenGate DDL Replication setup scriptVerifying that current user has privile…

大数据学习(36)- Hive和YARN

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博主哦&#x1f91…

【动态规划】落花人独立,微雨燕双飞 - 8. 01背包问题

本篇博客给大家带来的是01背包问题之动态规划解法技巧. &#x1f40e;文章专栏: 动态规划 &#x1f680;若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅&#x1f680; 要开心要快乐顺便…

FluentCMS:基于 ASP.NET Core 和 Blazor 技术构建的开源CMS内容管理系统

推荐一个基于 ASP.NET Core 和 Blazor 技术构建的、功能完善的开源CMS内容管理系统。 01 项目简介 FluentCMS 是一个基于强大的 ASP.NET Core 和创新的 Blazor 技术构建的现代内容管理系统&#xff08;CMS&#xff09;。 FluentCMS 设计为快速、灵活且用户友好&#xff0c;它…

[创业之路-262]:《向流程设计要效率》-2-职能型组织、项目型组织、流程型组织的异同比较

目录 一、职能型组织与流程化组织的比较 1.1、定义与结构 1.2、关注焦点与运作方式 1.3、优势与局限性 1.4、转型与发展 二、职能型组织、项目型组织、流程型组织的比较 2.1、定义与特点 2.2、优势与局限性 2.3、适用场景与选择建议 三、项目型组织、流程型组织的异同…