代码之家  ›  专栏  ›  技术社区  ›  Waleed Amjad

HTML5 iPhone动态图像缓存

  •  8
  • Waleed Amjad  · 技术社区  · 14 年前

    我们正在为离线工作的iPhone构建Web应用程序。但是我们在缓存动态图像时遇到了困难。请继续读下去,我将举例说明我的意思和迄今为止我们所做的工作。

    例如,我们正在构建一个只有一页的简单列表应用程序。应用程序的唯一目的是列出5个项目,每个项目包含一些文本和1个图像。

    该应用程序有一个简单的徽标和一些单独的JavaScript和CSS代码。这些 静态资源 使用缓存清单文件缓存。

    有两种情况:

    场景1:我在线并打开Web应用程序

    当我在Safari中加载列表应用程序时,它将从包含1000个项目的数据库中提取5个新的随机项目。这些都是由简单的后端通过Ajax调用(JSON格式)提供的。

    包含5个项目的整个JSON对象立即存储在HTML5本地存储中,并缓存以供脱机使用。

    JSON对象的结构有点像这样:

    {
        "0" : {
            id: "3",
            text: "Some text about item #3",
            image_url: "http://www.domain.com/image22341.png"
        },
        "1" : {
            id: "23",
            text: "Some text about item #23",
            image_url: "http://www.domain.com/image442321.png"
        },
        "2" : {
            id: "4",
            text: "Some text about item #4",
            image_url: "http://www.domain.com/image2321.png"
        },
        "3" : {
            id: "432",
            text: "Some text about item #432",
            image_url: "http://www.domain.com/image2441.png"
        },
        "4" : {
            id: "43",
            text: "Some text about item #43",
            image_url: "http://www.domain.com/image221.png"
        }
    }
    

    如您所见,非常简单(可能是那个JSON中的一些错误),整个JSON对象存储在本地存储中。

    现在这5个项目是用JavaScript注入的HTML(用CSS设计样式)呈现的,没有什么特别之处。创建包含文本和指向图像资源的图像标记的范围标记等。

    在在线模式下,一切都很好。

    场景2:我处于脱机状态,打开Web应用程序

    页面加载(显示徽标是因为使用缓存清单将其缓存为静态资源),一些javascript检测到我们确实处于脱机状态,因此应用程序不会尝试联系后端。相反,它从本地存储中读取先前存储的JSON对象,并开始呈现5个项目。一切如预期。

    文本显示得很好,但这次图像不显示,原因很简单,图像标记指向的是不可用的图像资源。所以它会显示那个小图像不可用的图标。


    现在我的问题是,有没有办法以某种方式缓存这些图像资源?所以下次我们需要它们时,它们是从缓存中提取的。

    这就是我所尝试的:

    • base64对图像进行编码并通过json提供它们。这是有效的,但是它显著地增加了获取和渲染时间(我们说的是增加30秒,非常慢)
    • 一些缓存清单黑客/试用和错误..找不到任何有效的内容(理想情况下需要一个策略,该策略执行“按请求缓存域中的所有资源”,但据我所知,这不存在)

    我已经花了好几个小时在这个问题上,找不到解决办法…有人有线索吗?我知道这是可能的,因为如果你看看iPhone的GoogleMail HTML5应用程序,它们可以以某种方式缓存附件,你甚至可以在离线时检索它们。

    我们没有尝试过的一件事是使用Safari支持的sqlite数据库…也许我可以将图像存储为一个斑点(仍然意味着从提要中获取图像,因此速度很慢?)然后神奇地将其转换成屏幕上的图像…但我不知道怎么做。

    感谢您的帮助。

    2 回复  |  直到 6 年前
        1
  •  1
  •   Cœur N0mi    6 年前

    我建议你看一看是否可以使用画布来保存你的图像,因为它们具有某些属性来获取/插入图像像素数据,例如像素值的csv(0-255)。

    来源: https://developer.apple.com/library/content/documentation/AudioVideo/Conceptual/HTML-canvas-guide/PixelManipulation/PixelManipulation.html

    我不确定您是否可以动态地将图像源使用到画布中,但是如果可以,您应该能够将CSVV数据从图像传输到数据库,反之亦然。

    引用

    Safari 4.0及更高版本支持直接操作画布像素。您可以使用getImageData()函数获取画布的原始像素数据,并使用createImageData()函数为被操作的像素创建新的缓冲区。

    ( source on archive.org )


    更新:

    我发现这个链接你也可能感兴趣。

    http://wecreategames.com/blog/?p=210

    http://wecreategames.com/blog/?p=219 //还要注意画布序列化的想法:)

        2
  •  2
  •   Community paulsm4    7 年前

    下面是一个从Ajax下载图像并将其转换为base64字符串的代码。使用此字符串,您可以将其保存到localstorage,并在脱机时将其分配给img的src属性。

    function _arrayBufferToBase64( buffer ) {
        var binary = '';
        var bytes = new Uint8Array( buffer );
        var len = bytes.byteLength;
        for (var i = 0; i < len; i++) {
            binary += String.fromCharCode( bytes[ i ] );
        }
        return window.btoa( binary );
    }
    
    
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'an_image.png', true);
    xhr.responseType = 'arraybuffer';
    
    xhr.onload = function(e) {
            if (this.status == 200) {
              var string_with_bas64_image = _arrayBufferToBase64(this.response);
    
              // You can save this string to local storag or set it to an img elemment this way
    
              document.getElementById("img").src = "data:image/png;base64," + string_with_bas64_image;
            }
    };
    
    xhr.send();
    

    您可以在这里测试它: http://jsbin.com/ivifiy/1/edit

    使用这种技术,您可以编写一个本地存储缓存。

    ou arraybuffertobase64从这里提取: ArrayBuffer to base64 encoded string