Preface
上次的预告这次到来,今天就来扒一扒Iconista的页面。本文篇幅不长,精力投入不多,权当水贴一篇,内容简短,适合饭后阅读。
http://urinx.github.io/app/iconista/ ,地址放出,欢迎来踩。
Dock
由于Iconista的性质决定了其不过是一个简单的Mac美化主题工具,所以页面必须要一眼就能突出其特性。
于是乎,最后决定了选择这个Launchpad样式,既能展现给大家其作用,又能直观的演示出最后的效果,并且给人一种耳目一新的感觉。
当方案拍定后,立马就开干。既然是百分百将launchpad复制到浏览器中,总不能直接全部弄张图片就了事,这是绝不能马虎,哥要的就是逼真,高仿。
第一步,就是高仿最具有象征性的Dock。
Finder
...
这里用的是一个jQuery插件
$('.dock').Fisheye(
{
maxWidth: 50,
items: 'a',
itemsText: 'span',
container: '.dock-container',
itemWidth: 60,
proximity: 80,
alignment : 'left',
valign: 'bottom',
halign : 'center'
}
);
然后修改其样式,使之成为Yosemite
风格——白色磨砂透明的Dock栏。
.dock{
width: 100%;
height: 10%;
position: absolute;
bottom: 0;
opacity: 0;
-webkit-transition: all 3s ease;
-moz-transition: all 3s ease;
-ms-transition: all 3s ease;
-o-transition: all 3s ease;
transition: all 3s ease;
}
.dock-container {
position: absolute;
height: 100%;
background: rgba(255,255,255,0.3);
padding-left: 20px;
border-radius: 8px 8px 0 0;
-moz-transform: translateX(-10px);
-webkit-transform: translateX(-10px);
-o-transform: translateX(-10px);
-ms-transform: translateX(-10px);
transform: translateX(-10px);
}
a.dock-item {
display: block;
font: 12px Arial, Helvetica, sans-serif;
width: 60px;
bottom: 0px;
position: absolute;
text-align: center;
text-decoration: none;
}
.dock-item span {
display: none;
margin-left: 20px;
color: black;
}
.dock-item img {
border: none;
margin: 5px 10px 0px;
width: 100%;
}
.bubble{
display: block;
background: rgba(255,255,255,0.8);
border-radius: 3px;
padding: 5px;
}
.bubble:before{
content: ' ';
position: absolute;
top: 24px;
left: 55px;
width: 0;
height: 0;
border: 10px solid;
border-color: rgba(255,255,255,0.8) transparent transparent transparent;
}
就连小气泡我们也要加上,绝不含糊,有图有真相!
Loading
由于页面上的图标太多,再加上一个炫酷的大背景,在网络情况不好的时候的确很尴尬。本来不想搞个什么鬼loading动画,只想让每个icon 图标依次加载然后慢慢坠落下来,就像iPhone解锁屏幕后App坠落的那个动画效果。奈何嫌麻烦,于是就干脆用个loading,等图标全部下载完成后再显示出来。
好吧,我能说连loading画面都不是自己写的,在这里感谢codepen,在codepen上随手一搜找了个——Battlefield 3 Loading Indicator。
一个纯CSS3写的Loading,直接塞进去就行了。
...
...
loading
tehran highway
我们用js在后面加载图片,这个是加载图片的函数:
function loadimg(arr,funLoading,funOnLoad,funOnError){
var numLoaded=0,
numError=0,
isObject=Object.prototype.toString.call(arr)==="[object Object]" ? true : false;
var arr=isObject ? arr.get() : arr;
for(a in arr){
var src=isObject ? $(arr[a]).attr("data-src") : arr[a];
preload(src,arr[a]);
}
function preload(src,obj){
var img=new Image();
img.onload=function(){
numLoaded++;
funLoading && funLoading(numLoaded,arr.length,src,obj);
funOnLoad && numLoaded==arr.length && funOnLoad(numError);
};
img.onerror=function(){
numLoaded++;
numError++;
funOnError && funOnError(numLoaded,arr.length,src,obj);
}
img.src=src;
}
}
我们把要加载的图片路径全塞进一个数组里,当所有数组里图片全部加载完成后隐藏loading画面,然后给要显示的页面一个淡出的效果(透明度从零到一):
// ==== Preload images =====
var imgSrcArr=[
'res/bg.jpg',
'res/apps/Safari.app.png',
'res/apps/Mail.app.png',
'res/apps/Contacts.app.png',
'res/apps/Calendar.app.png',
'res/apps/Reminders.app.png',
'res/apps/Notes.app.png',
'res/apps/Maps.app.png',
'res/apps/Messages.app.png',
'res/apps/FaceTime.app.png',
'res/apps/Photo Booth.app.png',
'res/apps/iTunes.app.png',
'res/apps/iBooks.app.png',
'res/apps/App Store.app.png',
'res/apps/Game Center.app.png',
'res/apps/Preview.app.png',
'res/apps/Dictionary.app.png',
'res/apps/Calculator.app.png',
'res/apps/Dashboard.app.png',
'res/apps/iPhoto.app.png',
'res/apps/GarageBand.app.png',
'res/apps/iMovie.app.png',
'res/apps/Numbers.app.png',
'res/apps/Keynote.app.png',
'res/apps/Pages.app.png',
'res/apps/Photos.app.png',
'res/apps/Mission Control.app.png',
'res/apps/System Preferences.app.png',
'res/apps/VirtualBox.app.png',
'res/apps/Xcode.app.png',
'res/apps/Evernote.app.png',
'res/apps/Pocket.app.png',
'res/apps/feedly.app.png',
'res/apps/Alfred 2.app.png',
'res/apps/SystemPal.app.png',
'res/apps/BetterTouchTool.app.png',
'res/apps/Pushbullet.app.png',
'res/apps/Tumblr.app.png',
'res/apps/Shazam.app.png',
'res/apps/MPlayerX.app.png',
'res/apps/Sublime Text.app.png',
'res/apps/Microsoft Remote Desktop.app.png',
'res/apps/Google Chrome.app.png',
'res/apps/VMware Fusion.app.png',
'res/apps/OmniFocus.app.png',
'res/apps/7zX.app.png',
];
function setPage(el,a,b){
var html=[];
for (var i = a; i < b; i++) {
var appItem='\
\
'+imgSrcArr[i].replace('res/apps/','').replace('.app.png','')+'\
';
html.push(appItem);
}
el.innerHTML=html.join('');
}
loadimg(imgSrcArr,null,function(){
setPage($('.app-list')[0],1,28);
setPage($('.app-list')[1],28,imgSrcArr.length);
$('.wrap').css('display','none');
$('body').css('background','url(res/bg.jpg) no-repeat');
$('body').css('background-size','100% 100%');
$('.app').css('opacity','1');
$('.dock').css('opacity','1');
},null);
至此,loading部分结束。
Download
话说最后这个简介的部分也是构思了好久,如何用最少的字最大限度的表达出效果的确不容易。在追求简洁这一点上,我们绝不妥协,这一点也让我们十分痛苦,不过最终我们还是做到了。
最后的效果就是下图,我们删繁就简,追求极致。
总共就只有两个按钮,一个提供下载,直截了当,不留任何余地,直接戳中一部分人的痛点(老子就是过来下这个的,那么多文字给谁看啊);剩下的另一部分人更多的则是对细节或是代码感兴趣,一个Github
按钮足矣。详细的使用说明都在README.md
文档写的很清楚,主页上写那么多干嘛,他们更愿意看的是这个。
Mobile
对于移动端我没什么好说的,前面那些高仿Mac的效果本来就不是给你用手机看的,所以说也管不了那么多兼不兼容的问题。
但是话又说回来,总不能让手机不能看吧,那多么尴尬啊,但又不能太麻烦,一切从简出发。所以最后简单粗暴的就直接加了一段:
然后在css里用一个简单的媒体查询对是否是移动端做了一个判断:
body::before {
content: 'mobile';
display: none;
}
@media only screen and (min-width: 770px) {
body::before {
content: 'desktop';
}
}
...
并且为mobile
类单独写了一套样式:
.mobile{
display: none
}
@media only screen and (max-width: 770px) {
.dock, .search, .app{
display: none;
}
.mobile{
display: block;
opacity: 0;
width: 300px;
height: 100%;
margin: auto;
-webkit-transition: all 3s ease;
-moz-transition: all 3s ease;
-ms-transition: all 3s ease;
-o-transition: all 3s ease;
transition: all 3s ease;
}
}
.mobile a{
...
}
...
最后在js里也进行了一个判断,那些加载图片的操作之类的在移动端就可以不用进行了(loading这个时候就没有意义了,不过还是留下来了):
var MQ = window.getComputedStyle(document.querySelector('body'), '::before').getPropertyValue('content').replace(/["']/g, "");
if (MQ == 'mobile') {
setTimeout(function(){
$('.wrap').css('display','none');
$('.mobile').css('opacity','1');
},5000);
}
else {
...
}
最后效果如图:
Icon Vibratiton
最后这个纯属无聊蛋疼之举,当然也是为了尽量逼真一下嘛——当你鼠标滑过icon图标时,加了一个抖动的效果,就是那个熟悉的每次你要删除App时出现的抖动。
...
@-webkit-keyframes vibrate {
0% {
-moz-transform: translate(2px,1px) rotate(5deg);
-webkit-transform: translate(2px,1px) rotate(5deg);
transform: translate(2px,1px) rotate(5deg);
}
25% {
-moz-transform: translate(-2px,-1px) rotate(-5deg);
-webkit-transform: translate(-2px,-1px) rotate(-5deg);
transform: translate(-2px,-1px) rotate(-5deg);
}
50% {
-moz-transform: translate(2px,1px) rotate(5deg);
-webkit-transform: translate(2px,1px) rotate(5deg);
transform: translate(2px,1px) rotate(5deg);
}
75% {
-moz-transform: translate(-2px,-1px) rotate(-5deg);
-webkit-transform: translate(-2px,-1px) rotate(-5deg);
transform: translate(-2px,-1px) rotate(-5deg);
}
100% {
-moz-transform: translate(2px,1px) rotate(5deg);
-webkit-transform: translate(2px,1px) rotate(5deg);
transform: translate(2px,1px) rotate(5deg);
}
}
...
Last
最后的最后,欢迎大家关注我的微信公众号(urinx),满满的干货
如果你有什么建议和想法想和我交流,各种bug想要反馈,或者纯属想要交朋友,这是我的微信(google-2)