原生js实现淘宝FED照片墙

前言

一次在看淘宝FED的一篇博客,完了又浏览了该站其他其他一些相关页面。点开关于我们页面发现文章头部有个照片墙,效果很炫(原谅我没见过世面),起初我以为应该是canvas实现的,知道我查看源文件后发现使用jquery实现的。


看了看源码发现原理就是:
1、画一个18*7的网格,并固定宽度
2、数组存储在网格上选取字母FED占位的下标
3、生成存储照片地址的数组
4、对占位下标数组和照片数组进行洗牌重排序
5、setTimeout
明白了了这些后我就用原生js重写了一下,

demo

我在CodePen上敲了个demo

See the Pen facebook by Hugh Dai (@HughDai) on CodePen.

代码

没什么好解释的,直接上代码

html

1
<div id="facebook"></div>

css

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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#facebook {
line-height: 0;
padding-bottom: 1px;
height: 288px;
margin-left: 6px;
transform-origin: left top;
-ms-transform-origin: left top;
-moz-transform-origin: left top;
-webkit-transform-origin: left top;
}

#facebook span {
width: 38px;
display: inline-block;
border: 1px solid transparent;
height: 38px;
margin-left: -1px;
margin-bottom: -1px;
overflow: hidden;
position: relative;
background-color: #FFF;
transition: all 0.3s;
}

#facebook span img {
height: 40px;
display: none;
width: 100%;
object-fit: cover;
max-width: none;
position: relative;
transition: fadeIn .3s;
}

#facebook span i {
position: absolute;
left: -100%;
top: 0;
width: 100%;
height: 100%;
transform: skewx(-25deg);
-o-transform: skewx(-25deg);
-moz-transform: skewx(-25deg);
-webkit-transform: skewx(-25deg);
background-image: -webkit-linear-gradient(0deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .5), rgba(255, 255, 255, 0));
z-index: 10;
}

#facebook span:hover i {
left: 100%;
transition: .5s;
-o-transition: .5s;
-moz-transition: .5s;
-webkit-transition: .5s;
}

/*.facebook_on {*/
/*background-color: transparent;*/
/*}*/

.facebook_you::after {
content: "YOU";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: #F40;
line-height: 38px;
font-size: 14px;
color: #FFF;
text-align: center;
}
@keyframes fadeIn {
from{
opacity: 0;
}
to{
opacity: 1;
}
}
@-webkit-keyframes fadeIn {
from{
opacity: 0;
}
to{
opacity: 1;
}
}
@-moz-keyframes fadeIn {
from{
opacity: 0;
}
to{
opacity: 1;
}
}
@-ms-keyframes fadeIn {
from{
opacity: 0;
}
to{
opacity: 1;
}
}

js

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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
;(function(){
var Facebook = function(){
this.pWidth = 720;
this.width = 708;
this.pHeight = 288;
// 表格中高亮坐标
this.dots = [20, 21, 22, 23, 38, 56, 74, 92, 57, 58, 25, 26, 27, 28, 43, 61, 79, 97, 98, 99, 100, 62, 63, 59, 30, 48, 66, 84, 102, 31, 32, 103, 104, 51, 69, 87, 64];
// 头像
this.keys = [
'TB1KIkQKXXXXXaOXpXXXXXXXXXX-450-300.png',
'TB1T7oPKXXXXXaUXpXXXXXXXXXX-450-300.png',
'TB104ZSKXXXXXX2XpXXXXXXXXXX-450-300.png',
'TB1DlArKXXXXXXiaXXXXXXXXXXX-450-300.jpg',
'TB1mMZOKXXXXXbpXpXXXXXXXXXX-450-300.png',
'TB16plLSFXXXXbBapXXXXXXXXXX-200-200.png',
'TB1F3AxKXXXXXX2XVXXXXXXXXXX-450-300.png',
'TB1WRIEKXXXXXaPXFXXXXXXXXXX-450-300.png',
'TB1A0ZtKXXXXXccXVXXXXXXXXXX-450-300.png',
'TB1RvE1KXXXXXaiXXXXXXXXXXXX-450-300.png',
'TB15ysvKXXXXXayXVXXXXXXXXXX-450-300.png',
'TB1aegRKXXXXXXZXpXXXXXXXXXX-450-300.png',
'TB113QCKXXXXXb2XFXXXXXXXXXX-450-300.png',
'TB1z2ovKXXXXXaVXVXXXXXXXXXX-450-300.jpg',
'TB1b0sRKXXXXXaAXpXXXXXXXXXX-450-300.png',
'TB1H4.ZKXXXXXa3XXXXXXXXXXXX-450-300.png',
'TB1fE.FKXXXXXX7XFXXXXXXXXXX-450-300.png',
'TB1_0ZDKXXXXXboXFXXXXXXXXXX-450-300.png',
'TB1JXAZKXXXXXa2XXXXXXXXXXXX-450-300.png',
'TB16.A1KXXXXXXuXXXXXXXXXXXX-450-300.png',
'TB1oXcPKXXXXXbmXpXXXXXXXXXX-450-300.png',
'TB1uc7KKXXXXXXbXFXXXXXXXXXX-450-300.png',
'TB1IioWKXXXXXb_XXXXXXXXXXXX-450-300.png',
'TB13FU0KXXXXXaLXXXXXXXXXXXX-450-300.png',
'TB14kcOKXXXXXbtXpXXXXXXXXXX-450-300.png',
'TB1gyw1KXXXXXXGXXXXXXXXXXXX-450-300.png',
'TB1x6ctKXXXXXbLXVXXXXXXXXXX-450-300.png',
'TB16eMPKXXXXXaYXpXXXXXXXXXX-450-300.png',
'TB1857NKXXXXXbNXpXXXXXXXXXX-450-300.png',
'TB1YisSKXXXXXcCXXXXXXXXXXXX-450-300.png',
'TB1WL3qKXXXXXbBXVXXXXXXXXXX-450-300.png',
'TB1M1QVKXXXXXcIXXXXXXXXXXXX-450-300.png',
'TB1MrcxKXXXXXXCXVXXXXXXXXXX-450-300.png',
'TB1v2ARKXXXXXX8XpXXXXXXXXXX-450-300.png',
'TB1U.3oKXXXXXbRaXXXXXXXXXXX-450-300.png',
'TB1WgIwKXXXXXagXVXXXXXXXXXX-450-300.jpg',
'TB1I8MTKXXXXXXBXpXXXXXXXXXX-450-300.png',
'TB1DZcrKXXXXXcVXVXXXXXXXXXX-450-300.png',
'TB1blaBSFXXXXbqXXXXXXXXXXXX-200-200.png',
'TB1EEUYKXXXXXaLXXXXXXXXXXXX-450-300.png',
'TB1qaEtKXXXXXbMXVXXXXXXXXXX-450-300.png',
'TB1t3oSKXXXXXX3XpXXXXXXXXXX-450-300.png',
'TB1HZEQKXXXXXavXpXXXXXXXXXX-450-300.png',
'TB18gwGKXXXXXawXFXXXXXXXXXX-450-300.png',
'TB11KADKXXXXXaBXFXXXXXXXXXX-450-300.png',
'TB1xusLKXXXXXcmXpXXXXXXXXXX-450-300.png',
'TB1Y.ErKXXXXXcFXVXXXXXXXXXX-450-300.png',
'TB1o3cwKXXXXXapXVXXXXXXXXXX-450-300.png',
'TB1eFoLKXXXXXcAXpXXXXXXXXXX-450-300.png',
'TB1VGMPKXXXXXa.XpXXXXXXXXXX-450-300.png',
'TB17BINKXXXXXbEXpXXXXXXXXXX-450-300.png',
'TB12uEFKXXXXXaPXFXXXXXXXXXX-450-300.png',
'TB1C_svKXXXXXaJXVXXXXXXXXXX-450-300.png',
'TB1zS3JKXXXXXcVXpXXXXXXXXXX-450-300.png',
'TB1rIsuKXXXXXa5XVXXXXXXXXXX-450-300.png',
'TB1XiEUKXXXXXcOXXXXXXXXXXXX-450-300.png',
'TB19hkHKXXXXXXRXFXXXXXXXXXX-450-300.png',
'TB1i97GKXXXXXavXFXXXXXXXXXX-450-300.png',
'TB1OhsBKXXXXXcnXFXXXXXXXXXX-450-300.png',
'TB1NO3OKXXXXXboXpXXXXXXXXXX-450-300.png',
'TB1gPgQKXXXXXacXpXXXXXXXXXX-450-300.png',
'TB1p1.2KXXXXXXJXXXXXXXXXXXX-450-300.png',
'TB1iQ.IKXXXXXXoXFXXXXXXXXXX-450-300.png',
'TB1YscMKXXXXXcdXpXXXXXXXXXX-450-300.png',
'TB1WM.UKXXXXXbGXXXXXXXXXXXX-450-300.png',
'TB1V_IUKXXXXXc8XXXXXXXXXXXX-450-300.png',
'TB1GkkCKXXXXXb5XFXXXXXXXXXX-450-300.png',
'TB1xWZOKXXXXXbtXpXXXXXXXXXX-450-300.png',
'TB1zo7CKXXXXXbBXFXXXXXXXXXX-450-300.png',
'TB1RrkYKXXXXXX3XXXXXXXXXXXX-450-300.png',
'TB1.IMKKXXXXXcZXpXXXXXXXXXX-450-300.png',
'TB16KgVKXXXXXcaXXXXXXXXXXXX-450-300.png',
'TB103wwKXXXXXb1XFXXXXXXXXXX-450-300.png',
'TB1WW.KKXXXXXcNXpXXXXXXXXXX-450-300.png',
'TB1hLMtKXXXXXb1XVXXXXXXXXXX-450-300.png',
'TB1JccxKXXXXXXRXVXXXXXXXXXX-450-300.png',
'TB1dEwtKXXXXXbxXVXXXXXXXXXX-450-300.png',
'TB1HLJVPXXXXXXhXVXXXXXXXXXX-864-864.jpg',
'TB1l24QPXXXXXbTXVXXXXXXXXXX-750-750.jpg',
'TB1fIlKPXXXXXalaXXXXXXXXXXX-4912-4912.jpg',
'TB1V9X7PXXXXXcOXpXXXXXXXXXX-340-340.jpg',
'TB15YdrPXXXXXaPaVXXXXXXXXXX-750-750.jpg',
'TB1Y5xWPXXXXXXkXVXXXXXXXXXX-1536-1536.jpg',
'TB1HNRwPXXXXXa7apXXXXXXXXXX-2048-2048.jpg',
'TB1BplEPXXXXXc0aXXXXXXXXXXX-750-750.jpg',
'TB17g4NPXXXXXXoaXXXXXXXXXXX-960-960.jpg',
'TB10d4CPXXXXXX9apXXXXXXXXXX-180-179.jpg',
'TB1tA8TPXXXXXabXVXXXXXXXXXX-600-600.jpg',
'TB15nujPXXXXXXmXXXXXXXXXXXX-518-518.jpg'
];
this.$box = document.querySelector('#facebook');
this.init();
};
/**
* 洗牌,打乱数组顺序
* @param arr
* @returns {Array}
*/
var shuffleFn = function(arr){
if(arr.length === 0) return [];
var reorderArr = [];
while(arr.length){
var rand = Math.floor(Math.random() * arr.length);
reorderArr.push(arr[rand]);
arr.splice(rand,1);
}
return reorderArr;
};
Facebook.prototype.getFaces = function(){
var reorderKeys = shuffleFn(this.keys);
// 对头像进行重排序
return reorderKeys.map((k,i) => {
return 'http://img.alicdn.com/tps/' + k;
});
};
Facebook.prototype.init = function(){
this.$box.style.cssText = `width:${this.width}px;background:none`;
// 生成 7行18列的表格
this.$box.innerHTML = Array.from({length:18 *7 }).join('<span><img src><i></i></span>');
this.bind();
this.run();
};
Facebook.prototype.bind = function(){
// 监听resize事件 调整容器大小
window.addEventListener('resize',() => {
var rate = this.$box.parentNode.clientWidth / this.pWidth;
this.$box.style.transform = `scale(${rate})`;
this.$box.style.webkitTransform = `scale(${rate})`;
this.$box.style.msTransform = `scale(${rate})`;
this.$box.style.mozTransform = `scale(${rate})`;
this.$box.style.marginBottom = `${this.pHeight * (rate -1)}`;
});
};
Facebook.prototype.run = function(){
var faces = this.getFaces();
var $spans = this.$box.querySelectorAll('span');
// 对高亮坐标重排序
var reorderDots = shuffleFn(this.dots);
var isMobile = /ios|android/i.test(navigator.appVersion);
reorderDots.forEach((dot,i) => {
var imgSrc = faces[i];
var $span = $spans[dot];
// 先把所有的给背景颜色
setTimeout(() => {
$span.style.cssText = 'background-color:#ff5f3e';
},i * 30);
// 加载图片
setTimeout(() => {
$span.style.cssText = 'background-color:#fff';
var $img = $span.querySelector('img');
$img.setAttribute('src',`${imgSrc}${isMobile ? "_40x40.jpg️" : "_80x80.jpg"}`);
$img.style.cssText = 'display:block';
},(reorderDots.length * 2 - i) * 30)
});
// 最后随便挑一个网格显示 YOU
setTimeout(() => {
var rand = Math.floor(Math.random() * reorderDots.length);
$spans[reorderDots[rand]].classList.add('facebook_you');
},(reorderDots.length * 2 + 1) * 30);
};
new Facebook();
})()