@wy
2018-09-27T15:31:23.000000Z
字数 2245
阅读 541
javascript
在前端这边经常做 img 的懒加载,会在 onload 事件触发后拿到图片的宽高,onload 的意思是在图片全部加载后会触发的事件,如果图片没加载之前是不会触发的。这样如果图片比较大,加载的时间过长,会导致本来显示图片的位置没有图片的实际宽高,只有等图片加载完成后才能确定显示图片区域的宽高。这样在做一些瀑布流时候,显得不那么的友好。
因为本地测试加载图片太快,所以使用后端控制图片的响应速度,基于 node 的框架 express 实现:
const express = require('express')
const app = express();
const path = require('path');
const fs = require('fs');
app.use((req,res,next) => {
let url = req.url;
let extname = path.extname(url);
if(extname === '.jpg'){
let d = fs.createReadStream(__dirname+'/img/'+url);
let chunks = [];
var size = 0;
let list = []
res.set({
'Content-type':'image/jpg'
});
d.on("data", function (chunk){
chunks.push(chunk);
size += chunk.length;
list.push(function (){
return new Promise((resolve) => {
setTimeout(() => {
res.write(chunk);
resolve();
},500)
});
})
});
d.on("end", async function () {
var buf = Buffer.concat(chunks, size);
for( var i = 0; i < list.length; i++ ){
await list[i]();
}
res.end()
});
}
})
app.listen(3000,() => {
console.log('服务启动成功');
})
整体的意思是当访问图片时候,不是一次性全部响应到前端,而是根据 fs 模块读流的方式一点点发给前端,这样的目的就是为了测试在图片没加载完成之前,可以获取到图片的宽高。
前端代码:
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<style>
.ketang {
width:0px;
height:0px;
background: red;
}
.hello {
background: blue;
margin: 10px;
float: left;
}
.hello img {
width: 100%;
height: 100%;
}
</style>
<script src="./img_load.js"></script>
<script>
window.onload = function(){
let arr = (new Array(9)).fill('').map((item,index) => {
return 'http://localhost:3000/'+(index + 1) + '.jpg'
});
let hello = document.getElementsByClassName('hello')
arr.forEach((url,index) => {
imgReady(url,function(){
console.log(url,this.width);
hello[index].style.width = this.width / 5 + 'px';
hello[index].style.height = this.height / 5 + 'px';
},function (){
console.log('loaded')
hello[index].innerHTML = '<img src="'+url+'" alt="" />'
})
})
};
</script>
</head>
<body>
<div class ="ketang" id="ketang">
<img src="" id="test">
</div>
<div class="hello"></div>
<div class="hello"></div>
<div class="hello"></div>
<div class="hello"></div>
<div class="hello"></div>
<div class="hello"></div>
<div class="hello"></div>
<div class="hello"></div>
<div class="hello"></div>
<div class="hello"></div>
</body>
</html>
这里用到了一个 img_load.js 库,参考:https://gist.github.com/southill/7149306
以上的原理很简单,当第一次读到图片的部分信息后,就把它发送到了前端,里面包含了图片的信息,这样不等图片全部加载好就可以拿到图片的地址。
在前端这边开启定时器,不断的访问加载的图片,一旦第一次加载的信息拿到后,立马就能得到图片的宽高。这时候你的图片可能还没有加载完,还没有出发onload事件。