0%

Next主题背景图片,使用unsplash.com随机图片

unsplash.com提供随机图片,都非常漂亮,用来作为网页背景图很合适。source.unsplash.com提供了很多访问随机图片的方式,比如从user, user’s likes, collection, search term中提供随机图片。我是自己创建了一个collection,从中获取随机图片,作为页面背景图。

背景图css:

/source/_data/styles.styl
1
2
3
4
5
6
7
8
9
10
11
12
/* 页面背景图 */
body {
//background:url(https://source.unsplash.com/random/1600x900/?sunset-glow,starry-sky,sea);
//background:url(https://source.unsplash.com/collection/collectionid/1600x900);
background:url(https://source.unsplash.com/collection/collectionid/2000x1000);
background-repeat: no-repeat;
background-attachment:fixed;
background-position:50% 50%;
@media (min-width: 768px) {
background-size: cover;
}
}

问题出现了,每刷新一次页面,从https://source.unsplash.com/collection/collectionid/2000x1000 返回的图片就换成了新的,图片又比较大,页面加载缓慢。所以想每过几分钟,才切换图片。

定时切换图片

由于图片服务器不在自己手里,所以只能js了。基本思路是,刷新页面,查看localStorage中保存的时间戳,和现在的时间差,超过固定时间,就去unsplash.com下载新的图片。不用cookie的原因是cookie每次都会传回服务器,对于这个功能并不合适。

https://source.unsplash.com/collection/collectionid/2000x1000 返回302和location,进行了重定向,返回的location是一个图片的地址,比如:https://images.unsplash.com/photo-1547578273-12d07a9d0b19?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=1000&ixid=eyJhcHBfaWQiOjF9&ixlib=rb-1.2.1&q=80&w=2000。

需要得到302的location,ajax无法办到,即使ajax发出HEAD请求。浏览器重定向之后,才去处理ajax回调,这个302对ajax是透明的。执行流程:ajax –> browser –> server –> 302 –> browser(redirect) –> server –> browser –> ajax callback。不过还是有办法的,原始的XMLHttpRequest可以得到302重定向的url

把下面的代码放到body-end.swig的script标签中即可。

/source/_data/body-end.swig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
bgrefresh ={
refreshtime: 5,
init: function () {
var that = this;
// checktime 执行完并没有刷新localStorage中的lastvisitedtime。
// 放到render函数中,记录的是上一次刷新的时间。
// 放到getnewimgurl函数中,记录的是上一次获取新图片的时间。也就是每隔refreshtime分钟就刷新背景。
if(this.checktime()) {
this.getnewimgurl('https://source.unsplash.com/collection/collectionid/2000x1000');
}else{
this.render();
}
},
checktime: function(){
if(!localStorage.hasOwnProperty('lastvisitedtime')){ // 第一次访问网站,需要刷新图片
return true;
}else{
var lastvisitedtime = localStorage.getItem("lastvisitedtime"); // 超过了refreshtime,需要刷新图片
if(Math.floor((new Date().getTime()-lastvisitedtime)/(60*1000))>=this.refreshtime){
return true;
}else{
return false;
}
}
},
getnewimgurl: function(url){
var that = this;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(e) {
if(xhr.readyState==4) { //2 HEADERS_RECEIVED 3 loading 4 down
if (xhr.status == 200 ) {
//console.log(xhr.responseURL);
localStorage.setItem("imgurl", xhr.responseURL);
localStorage.setItem("lastvisitedtime", new Date().getTime());
that.render();
}
}
};
xhr.open("GET", url, true);//不用HEAD,直接拿到图片,相当于预加载图片了,图片不会一层层显示,而是一下就显示出来。
xhr.send();
},
render: function () {
document.body.style.backgroundImage='url('+ localStorage.getItem("imgurl") +')';
}
};
bgrefresh.init();

加入缓存

上面的代码能做到每隔5分钟,再次刷新页面才会切换背景。可是切换背景仍然需要从source.unsplash.com加载。如果加入缓存,到了切换背景的时候,背景图片已经缓存下来,那就不会有从source.unsplash.com加载图片时间了,页面刷新速度就会很快了。

/source/_data/body-end.swig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// 缓存的编程模型,就是三个指针 localStorage记录点 cache() getnewimgurl()
// cache()函数轮询,到了加载时间就去加载图片,更新localStorage记录点
// 用户刷新后,时间间隔如果没有超过新一轮的refreshtime时间,就去加载cache缓存的图片,超过了执行getnewimgurl(),加载新图片,cache重新开始计时。
// getnewimgurl()会在缓存过期或失败后加载图片

// localStorage记录点 cache() getnewimgurl()
// cache() getnewimgurl() 这个时间段中打开着网页,就能成功cache

// cache不起作用,到8分钟必然换背景。cache起作用,到4分钟,就下载新图片,更新ocalStorage记录点,使用新图片。
bgrefresh ={
refreshtime: 8,//分钟
url: 'https://source.unsplash.com/collection/collectionid/2000x1000',
cacheinterval: null,
init: function () {
if(!localStorage.hasOwnProperty('lastvisitedtime')){// 第一次访问网站,需要刷新图片
this.getnewimgurl(this.url,false);
}else if(this.checktime(this.refreshtime)) {// 时间超过了refreshtime
this.getnewimgurl(this.url,false);
}else{// 时间没有超过refreshtime
this.cache();
this.render();
}
},
// checktime 执行完并没有刷新localStorage中的lastvisitedtime。
// 放到render函数中,记录的是上一次刷新的时间。
// 放到getnewimgurl函数中,记录的是上一次获取新图片的时间。也就是每隔refreshtime分钟就刷新背景。
checktime: function(interval){
var lastvisitedtime = localStorage.getItem("lastvisitedtime"); // 超过了refreshtime,需要刷新图片
if(Math.floor((new Date().getTime()-lastvisitedtime)/(60*1000))>=interval){
return true;
}else{
return false;
}
},
getnewimgurl: function(url,cache){ //cache 表示是否是缓存函数调用
if(cache==true){
clearInterval(this.cacheinterval);
//console.log('cache success');
}
var that = this;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(e) {
if(xhr.readyState==4) { //2 HEADERS_RECEIVED 4 done
if (xhr.status == 200 ) {
//console.log(xhr.responseURL);
localStorage.setItem("imgurl", xhr.responseURL);
localStorage.setItem("lastvisitedtime", new Date().getTime());//刷新lastvisitedtime
if(!cache) { // 不是缓存调用
that.render();
that.cache();
}
}
}
};
xhr.open("GET", url, true);//不用HEAD,直接拿到图片,相当于预加载图片了,图片不会一层层显示,而是一下就显示出来。
xhr.send();
},
render: function () {
document.body.style.backgroundImage='url('+ localStorage.getItem("imgurl") +')';
},
cache : function () {
var that = this;
//console.log('cache');
this.cacheinterval = setInterval(function() {
if(that.checktime(that.refreshtime-4)){
that.getnewimgurl(that.url,true);
}
}, 15000);
//15s循环一次,时间越短越好,但不要影响页面性能。
//同时,如果时间到了该cache的时候,此时刷新页面,
//就会下载cache图片,如果时间太小,cache就会立即加载新图片,影响页面加载速度。
}
};
bgrefresh.init();

同时,修改页面背景css,即使第一次加载背景,或者缓存过期,背景也比较美观。

/source/_data/styles.styl
1
2
3
4
5
6
7
8
9
10
11
12
13
/* 页面背景图 */
body {
//background:url(https://source.unsplash.com/random/1600x900/?sunset-glow,starry-sky,sea);
//background:url(https://source.unsplash.com/collection/collectionid/1600x900);
//background:url(https://source.unsplash.com/collection/collectionid/2000x1000);
background-color: #EADEC7;
background-repeat: no-repeat;
background-attachment:fixed;
background-position:50% 50%;
@media (min-width: 768px) {
background-size: cover;
}
}