一、前言
开发新闻资讯类项目,新闻详情功能是项目的核心,现在基本采用原生+webview的形式来显示新闻内容,怎么给用户更好的阅读体验这是我们需要考虑的问题。
这篇文章主要针对新闻详情中图片的处理:
- 图片加载前的占位图
- 图片懒加载
- 图片的本地下载、缓存、显示
- webview使用本地下载好的图片来展示
二、技术实现
2.1、图片加载前的占位图
这个功能很好实现,使用本地占位图地址替换掉原始标签内
src
的图片地址就可以了。
- 使用正则
匹配出文章内的所有标签以及src中的图片地址。
- 获取到本地占位图在应用内的地址
placeholderPath
来替换掉src
所指的图片地址
2.2、图片懒加载
考虑到功能需求以及包体积的问题,最终选择了echo.js来实现webview内图片懒加载功能。
但是在我们对新闻详情的技术设计中图片的下载需要在native端进行并缓存在本地,echo.js是为web而设计的一个轻量级图片懒加载库。
通过对使用方法的研究,我们发现在初始化echo.js时让我们传入了一个callback的回调函数
echo.init({
offset: 100,
throttle: 500,
debounce: false,
callback: function (element, op) {
}
});
这个回调函数是对当前是否加载图片的回调。
那我们能不能在需要加载图片时通过这个回调函数告诉native端去下载图片呢?接下来对echo.js源码的分析发现callback调用的时机
if (elem.getAttribute('data-echo-background') !== null) {
elem.style.backgroundImage = "url(" + elem.getAttribute('data-echo-background') + ")";
}
else {
// elem.src= elem.getAttribute('data-echo'); 这是源代码
callback(elem, 'native-load-src'); // 自定义一个操作option, 回调到callback
}
if (!unload) {
elem.removeAttribute('data-echo');
elem.removeAttribute('data-echo-background');
}
移除掉直接对src的直接赋值,改为触发callback回调并自定义一个option告诉接收方。
回到初始化echo时定义的回调:
echo.init({
offset: 100,
throttle: 500,
debounce: false,
callback: function (element, op) {
if (op === 'native-load-src'){
// 触发了图片加载操作,与native端通讯做图片下载操作。
var data = {
src: element.getAttribute('data-echo'),
op: op,
eleid: element.getAttribute('id'),
};
/// 这是wkwebview中js与native端通讯的方式,uiwebview可以使用对应的方式. window.webkit.messageHandlers.xxxxx.postMessage({
"eventName": "downImage",
"body": data,
});
}
}
});
2.2.1、echo.js的使用
-
标签需要做一定的处理
data-echo: 正常需要加载的远端图片地址
src: 需要显示的占位图地址
class: 固定填写lazy,是echo.js内部需要
id: 这个随意,为了处理本地图片下载完后替换img的src而存在
- 新闻详情的模板html内需要初始化echo.js
echo.init({
offset: 100,
throttle: 500,
debounce: false,
callback: function (element, op) {
if (op === 'native-load-src') {
var data = {
src: element.getAttribute('data-echo'),
op: op,
eleid: element.getAttribute('id'),
};
window.webkit.messageHandlers.xxxxx.postMessage({
"eventName": "downImage",
"body": data,
});
}
}
});
2.3、图片的本地下载、缓存、显示
前文中提到js侧触发了图片加载时会与native端通讯,告诉native去下载图片。
本人是使用的SDWebImage
来下载的网络图片并缓存,下载的操作就不赘述。
下载完成后获取缓存图片的地址,通知js端替换的src地址。
js端代码:
/// src 为本地图片的地址, id为给设置的id
function renderLocalImage(src, id) {
var ele = document.getElementById(id);
ele.src = src;
}
至此,运行跑一边是不是完美!!
解决WKWebview中无法显示沙盒内图片的问题
等等,怎么在真机上还是显示的占位图??
多方面查找原因,我的项目中是使用的wkwebview来显示新闻内容,缓存在沙盒中的图片无法在 wkwebview中显示。
解决方案:
使用GCDWebServer给wkwebview提供访问沙盒内文件的能力。
2.4、webview使用本地下载好的图片来展示
- 前文已经匹配出
标签和标签内src的内容,通过
SDWebImage
提供的方法来判断这个src是否已经存在本地,如已经存在本地则直接替换成沙盒地址(注意通过GCDWebServer提供的访问服务) - 如果不存在本地,则按照2.2.1中echo.js使用规则对
进行处理
三、总结
这是新闻详情中其中一个功能的实现,涉及了js、图片下载、js与oc交互、html相关的知识。
记录下我实现这个功能的过程,永远保持学习的态度。