【发布时间】:2020-08-24 17:30:21
【问题描述】:
我有一个读取地图图块图像的函数。我想跟踪某个图像是否已经被缓存。我正在使用来自this thread的这个功能:
function is_cached(src) {
var image = new Image();
image.src = src;
return image.complete;
}
这工作得很好。但后来我需要做一些图像处理。为了将图像数据复制到画布并逐像素处理,我需要使用CanvasRenderingContext2D.drawImage(image, 0, 0)。但它让我感到困扰的是一个跨域错误。所以我可以添加一个image.crossOrigin = "*",它解决了这个问题,我可以写到画布上并进行我需要的图像处理。那一点看起来像这样:
imageOutput.crossOrigin = "*"
var demCtx;
imageOutput.onload = function(){
var c = document.createElement('canvas')
c.width = c.height = 256
demCtx = c.getContext('2d')
demCtx.drawImage(imageOutput, 0, 0)
var imageData = demCtx.getImageData(0, 0, 256, 256)
}
出现的问题是,每次我运行包含这两位代码的较大函数时,is_cached 函数每次都返回 false,除了第一次。但我知道,即使 is_cached 返回 false,图像也确实被缓存了,因为它们以 0 延迟加载(而不是在调用新图像时需要一些时间从服务器获取它)。
为什么.crossOrigin = "*" 会干扰图像的.complete 状态?
这发生在 ObservableHQ 笔记本中。这可能与它有关吗? ObservaleHQ 有时会变得很奇怪。
ObservableHQ Notebook with the problem
您可以在底部的getTileUrl 单元格中找到此代码。这个笔记本还没写完。点击提交更改到输入的地图后,您可以在Tile Previously Cached 行看到缓存状态。
感谢阅读。
【问题讨论】:
-
is_cached 函数被破解。获取图像是异步的,即使在缓存时也是如此。你最好把它扔掉。为什么你需要知道你的图片是否被缓存了?
-
诚实的问题:为什么它是 hack?
is_cached函数在另一个问题中是一个广受欢迎的答案,它为我提供了我需要的确切/预期行为,直到我引入crossOrigin = "*"行。回答您的 Q - 简短回答:更好地了解缓存的工作原理。长答案:我想在我正在编写的应用程序中使用磁贴图像作为数据源,并且我正在尝试找到预加载磁贴的最佳方法,并将它们的数据待机以提高性能。我不确定缓存是否足够,或者我是否应该使用另一种临时的浏览器内存储方法 -
查看该答案下的 cmets。它不会告诉您图像是否被缓存,但它是否已经被当前文档加载。现在规范还要求在微任务中完成获取操作系统,以便在没有同步触发任何内容的情况下无法设置 srcset 和 crossorigin。而且您可能还没有足够的特权来查看它,但是这个答案也几乎没有应得的反对票。对于您想要的,在应用程序的开头预加载所有资产,并存储由这些图像制成的 ImageBitmap,这是最高效的方式。
-
感谢您的解释。我有一种感觉,依赖缓存可能不是跟踪我的图块的最佳方法,我想手动进行。我修改了我的笔记本,如果它们尚未保存,则将它们以
ImageBitaps 的形式保存到对象中。然后我只需要获取以前未保存的图块。我知道如何使用ImageBitMap写入画布并从那里获取像素数据。考虑到我想稍后逐个像素地访问像素数据,您认为保存ImageBitmaps或保存画布ImageDataUint8ClampedArray会更高效吗? -
;-) ImageBitmap 对象本身非常小,它只有自己的
width和height,这就是你所有的sizeof度量(以及它可以度量的所有)。然而,这个对象只是我们作为作者可以获得的冰山一角。在底层,它链接到浏览器将存储在内存中的实际图像位图。要检查这个位图的大小,你需要使用浏览器的开发工具,甚至你的操作系统内存管理工具,但是 256*256 的位图肯定会高于 40 字节 ;-)
标签: javascript image-processing caching canvas observablehq