源码分析之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,一经查实,立即删除!

相关文章

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.如何理解职责链模式 最常见的职责链是直线型,即沿着一条单向的链来传递请求。链上的每一个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并让请求沿着…

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

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

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

一、整数型数据类型 名称大小(字节数)范围(无符号)范围(有符号)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 实现对比》发布之后,收到了大佬的“催稿”,想了解下 Flutter 和 Compose 在 PlatformView 实现上的对比,恰好过去写过不少 Flutter 上对于 PlatformView 的实现,这次恰好…

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

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

暑期实习准备:C语言

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

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

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

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

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

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

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

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

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

5G网络下移动机器人的图像和指令传输用于远程操作

论文标题 **英文标题:**Image and Command Transmission Over the 5G Network for Teleoperation of Mobile Robots **中文标题:**5G网络下移动机器人的图像和指令传输用于远程操作 作者信息 Thiago B. Levin,, Joo Miguel Oliveira,, Ricardo B. Sou…

云计算、AI与国产化浪潮下DBA职业之路风云变幻,如何谋破局启新途?

引言 在近日举办的一场「云和恩墨大讲堂」直播栏目中,云和恩墨联合创始人李轶楠、副总经理熊军和欧冶云商数据库首席薛晓刚共同探讨了DBA的现状与未来发展。三位专家从云计算、人工智能、国产化替代等多个角度进行了深入的分析和探讨,为从业者提供了宝贵…

30天开发操作系统 第 17 天 -- 命令行窗口

前言 今天一开始,请大家先回忆一下任务A的情形。在harib13e中,任务A下面的LEVEL中有任务因此FIFO为空时我们可以让任务A进入休眠状态。那么,如果我们并未启动任务B0~ B0~ B2, B2的话,任务A又将会如何呢? 首先&#xf…

R语言学习笔记之开发环境配置

一、概要 整个安装过程及遇到的问题记录 操作步骤备注(包含遇到的问题)1下载安装R语言2下载安装RStudio3离线安装pacman提示需要安装Rtools4安装Rtoolspacman、tidyfst均离线安装完成5加载tidyfst报错 提示需要安装依赖,试错逐步下载并安装…

数据结构 链表2

目录 前言: 一,反转一个链表(迭代) 二,打印一个链表(递归) 三,反转一个链表(递归) 四,双向链表 总结 前言: 我们根据 [文章 链表1] 可以知道链表相比较于数组的优缺点和计算机…