我们缺的不是技术,而是创意...

2010-11-15 00:33

我们缺的不是技术,而是创意...

by 岑安

at 2010-11-14 16:33:00

original http://www.cnblogs.com/hongru/archive/2010/11/14/1876990.html

  周末闲在家确实无聊。宅的不成样子了。偶然发现国外一个web设计的网站上有一个3D时钟。顿时来了兴趣。其实一看代码,不是svg,也不是canvas,而是简单的利用层级关系,大小关系作了一个视觉差。看起来会有立体运动的感觉。

  于是,借着源码,我稍微把它整理一下,利用闭包规避了它大量的全局变量,稍微封装了一下,增加了几项可配置性。觉得好玩,分享给大家。
  这个效果主要有两个核心的变换,一个是时钟整体圆周的变化,一个是组成时钟的小元素的位置和层级的变化。
核心变换代码主要有两段:

mainloop: function () {
// rotations
_dir == 'left' ? A-=0.1 : A+=0.1;
rx
+=px;
ry
+=py;
crx
=Math.cos(rx);
srx
=Math.sin(rx);
cry
=Math.cos(ry+Math.PI/2);
sry=Math.sin(ry+Math.PI/2);
// return to the horizontale
rx*=.9; ry*=.9; px*=.9; py*=.9;
// refresh time
.
.
.
// call animation
for(var i in O){
for(var j in O[i].O){
O[i].O[j].anim();
}
}
setTimeout(arguments.callee,
32);
}

然后结合anim(),可以造出圆环的效果。

// main 3D function
CObj.prototype.anim=function() {
// z axis rotation
var x=Math.sin(A+this.a)*100;
var y=Math.cos(A+this.a)*100;
// simple 3D
var x1=y*crx-this.z*srx;
var zz=y*srx+this.z*crx;
var y1=x*cry-zz*sry;
zz
=x*sry+zz*cry;
// 2D projection
var r=400/(400+zz);
x=Math.round(150-x1/r);
y=Math.round(100-y1/r);
var w=Math.round(2+Math.max(4,zz*.07));
// leds lighting
this.alpha(zz);
// html positioning
var css = this.o.style;
css.left
=x+"px";
css.top
=y+"px";
css.width
=css.height=w+"px";
css.zIndex
=Math.round(1000+zz);
}

里面嵌杂了一些亮灰度的变化和层级大小的变化就不细说了。大概思路是这样。

不仅3D的处理有创意,时间的组成也有创意,用了一个数组模拟了1~9的数字:

var digits = [
"##### # ########### ########################## ",
"# # # # ## ## # ## ## # ",
"# # # # ## ## # ## ## # # ",
"# # # ##### ################### ########### ",
"# # # # # # ## # ## # # # ",
"# # # # # # ## # ## # # ",
"##### # ########## ########### ########### "
]

 

然后可以把组成数字的#号替换成想要的元素,可以是小图片,也可以是其他。然后每次循环的时候根据时间的数字让数组里的#拼凑成当前所需的数字。

function Cdigit(N,d){
// digit prototype
this.O = [];
for(var i=0;i<7;i++){
for(var j=0;j<5;j++){
if(digits[i].charAt(5*d+j)!=" "){
this.O.push(
new CObj((
...
)
);
}
}
}
}

 

基本思路就是这样子,然后在主循环里每次刷新时间的时候移除上一次的元素,重新拼凑就可以了。没有实例上面的话都是白说,还是给大家看看实例吧。(我只是做了稍微的封装,核心代码并没有改动原作者的),代码运行有问题的同学请自行拷到本地运行。(使用chrome的需拷到本地运行)

<!DOCTYPE HTML> <html> <head> <title>clock3D</title> <style type="text/css" _mce_bogus="1"><!-- html { overflow: hidden; } body { margin: 0px; padding: 0px; background: #222; } #clock3D { position:absolute; left: 50%; top: 50%; border:#444 solid 1px; margin-left: -150px; margin-top: -100px; width:300px; height:200px; background:#000; } #clock3D span { position: absolute; width: 4px; height: 4px; -webkit-border-radius: 2px; -moz-border-radius: 2px; } --></style> <script type="text/javascript"><!-- (function () { var digits = [ "##### # ########### ########################## ", "# # # # ## ## # ## ## # ", "# # # # ## ## # ## ## # # ", "# # # ##### ################### ########### ", "# # # # # # ## # ## # # # ", "# # # # # # ## # ## # # ", "##### # ########## ########### ########### " ],O = [], px = 0, py = 0, rx = 0, ry = 0, TM = [], Tm = [], A = 2000, crx, srx, cry, sry, _id, _dir; var Class = { create : function () { return function () { this.init.apply(this, arguments); } } } var $ = function (i) {return document.getElementById(i)} window.clock3D = Class.create(); clock3D.prototype = { init: function (o) { this.time(); this.resize(); _dir = o.direction ? o.direction : 'left'; _id = o.id; var k=0; for(var i=0;i<6;i++){ O[k] = new Cdigit(k++, TM[i]); if(i==1 || i==3) O[k] = new Cdigit(k++, 10); } this.mainloop(); }, time : function () { T = new Date(); h = T.getHours(); m = T.getMinutes(); s = T.getSeconds(); TM = [ Math.floor(h/10), h%10, Math.floor(m/10), m%10, Math.floor(s/10), s%10 ]; setTimeout(arguments.callee ,1000); }, resize: function () { nx = document.documentElement.clientWidth/2; ny = document.documentElement.clientHeight/2; if(ny==0)ny = document.body.clientHeight/2; }, mainloop: function () { // rotations _dir == 'left' ? A-=0.1 : A+=0.1; rx+=px; ry+=py; crx=Math.cos(rx); srx=Math.sin(rx); cry=Math.cos(ry+Math.PI/2); sry=Math.sin(ry+Math.PI/2); // return to the horizontale rx*=.9; ry*=.9; px*=.9; py*=.9; // refresh time k=0; for(var i=0;i<6;i++){ if(TM[i]!=Tm[i]){ Tm[i]=TM[i]; // destroy objects for(var j in O[k].O) $(_id).removeChild(O[k].O[j].o); delete O[k]; // create new digit O[k] = new Cdigit(k, TM[i]); } k+=(i==1 || i==3)?2:1; } // call animation for(var i in O){ for(var j in O[i].O){ O[i].O[j].anim(); } } setTimeout(arguments.callee,32); } } function Cdigit(N,d){ // digit prototype this.O = []; for(var i=0;i<7;i++){ for(var j=0;j<5;j++){ if(digits[i].charAt(5*d+j)!=" "){ this.O.push( new CObj(( (32*N)+(j*5))/50, -42+i*12 ) ); } } } } function CObj(a,z){ // create led element this.o=document.createElement("span"); this.o.style.background = '#fff'; $(_id).appendChild(this.o); this.a=a; this.z=z; this.plot=true; } // leds lighting CObj.prototype.alpha=function(opacity){ if(opacity>0){ if(!this.plot){ this.plot=true; this.o.style.background = '#fff'; } } else { if(this.plot){ this.plot=false; this.o.style.background = '#333'; } } } document.onmousemove = function(e){ if(window.event) e=window.event; xm=(e.x || e.clientX); ym=(e.y || e.clientY); px=(xm-nx)/(nx*5); py=(ym-ny)/(ny*5); } // main 3D function CObj.prototype.anim=function() { // z axis rotation var x=Math.sin(A+this.a)*100; var y=Math.cos(A+this.a)*100; // simple 3D var x1=y*crx-this.z*srx; var zz=y*srx+this.z*crx; var y1=x*cry-zz*sry; zz=x*sry+zz*cry; // 2D projection var r=400/(400+zz); x=Math.round(150-x1/r); y=Math.round(100-y1/r); var w=Math.round(2+Math.max(4,zz*.07)); // leds lighting this.alpha(zz); // html positioning var css = this.o.style; css.left=x+"px"; css.top=y+"px"; css.width=css.height=w+"px"; css.zIndex=Math.round(1000+zz); } })(); // --></script> </head> <body> <div id="clock3D"></div> <script type="text/javascript"><!-- onload = function () { new clock3D({ id: 'clock3D', direction: 'right' }); } //window.onresize = new clock3D.resize; // --></script> </body> </html>

调用方式:

<div id="clock3D"></div>
<script type="text/javascript"><!--
new clock3D({
id:
'clock3D',
direction:
'right' // or 'left'
});
// --></script>

 

 

【附赠】

另外,附赠一个昨晚上随便写的一个仿twitter/新浪微博首页的 自动无缝滚动效果。

<!doctype html> <html> <head> <title>tweets-slide</title> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <style type="text/css" _mce_bogus="1"><!-- ul, li {margin:0; padding:0;list-style:none} body { margin: 0; height: 100%; background: #333; } .wp { position: relative; width: 800px; height: 400px; overflow: hidden; margin: 20px auto; border: 4px solid #121212; background: #fff; } .slider { position: absolute; width: 760px; padding: 0 20px; left:0; top: 0; } .fl {float:left} .slider img {display:block; padding: 2px; border: 1px solid #ccc} .slider li {padding: 20px 0; border-bottom: 1px dashed #ccc;overflow:hidden;width:100%} .slider p {font-size: 12px;margin:0;padding-left:68px;color:#333;line-height:20px;} --></style> <script type="text/javascript"><!-- function H$(i) {return document.getElementById(i)} function H$$(c, p) {return p.getElementsByTagName(c)} var slider = function () { function init (o) { this.id = o.id; this.at = o.auto ? o.auto : 3; this.o = 0; this.pos(); } init.prototype = { pos : function () { clearInterval(this.__b); this.o = 0; var el = H$(this.id), li = H$$('li', el), l = li.length; var _t = li[l-1].offsetHeight; var cl = li[l-1].cloneNode(true); cl.style.opacity = 0; cl.style.filter = 'alpha(opacity=0)'; el.insertBefore(cl, el.firstChild); el.style.top = -_t + 'px'; this.anim(); }, anim : function () { var _this = this; this.__a = setInterval(function(){_this.animH()}, 20); }, animH : function () { var _t = parseInt(H$(this.id).style.top), _this = this; if (_t >= -1) { clearInterval(this.__a); H$(this.id).style.top = 0; var list = H$$('li',H$(this.id)); H$(this.id).removeChild(list[list.length-1]); this.__c = setInterval(function(){_this.animO()}, 20); //this.auto(); }else { var __t = Math.abs(_t) - Math.ceil(Math.abs(_t)*.07); H$(this.id).style.top = -__t + 'px'; } }, animO : function () { this.o += 2; if (this.o == 100) { clearInterval(this.__c); H$$('li',H$(this.id))[0].style.opacity = 1; H$$('li',H$(this.id))[0].style.filter = 'alpha(opacity=100)'; this.auto(); }else { H$$('li',H$(this.id))[0].style.opacity = this.o/100; H$$('li',H$(this.id))[0].style.filter = 'alpha(opacity='+this.o+')'; } }, auto : function () { var _this = this; this.__b = setInterval(function(){_this.pos()}, this.at*1000); } } return init; }(); // --></script> </head> <body> <div class="wp"> <ul id="slider" class="slider"> <li><a class="fl" href="javascript:;" _mce_href="http://javascript:;"><img src="http://pic.cnblogs.com/face/u160412.jpg" _mce_src="http://pic.cnblogs.com/face/u160412.jpg" alt="" /></a> <p>曾虑多情损梵行    入山又恐别倾城    世间安得双全法    不负如来不负卿</p> </li> <li><a class="fl" href="javascript:;" _mce_href="http://javascript:;"><img src="http://pic.cnblogs.com/face/u160412.jpg" _mce_src="http://pic.cnblogs.com/face/u160412.jpg" alt="" /></a> <p>第一最好不相见,如此便可不相恋。 第二最好不相知,如此便可不相思。<br/> 第三最好不相伴,如此便可不相欠。 第四最好不相惜,如此便可不相忆。<br/> 第五最好不相爱,如此便可不相弃。 第六最好不相对,如此便可不相会。 <br/> 第七最好不相误,如此便可不相负。 第八最好不相许,如此便可不相续。<br/> 第九最好不相依,如此便可不相偎。 第十最好不相遇,如此便可不相聚。<br/> 但曾相见便相知,相见何如不见时。 安得与君相诀绝,免教生死作相思。</p> </li> <li><a class="fl" href="javascript:;" _mce_href="http://javascript:;"><img src="http://pic.cnblogs.com/face/u160412.jpg" _mce_src="http://pic.cnblogs.com/face/u160412.jpg" alt="" /></a> <p>那一天 闭目在经殿香雾中 蓦然听见你颂经中的真言 那一月 我摇动所有的转经筒 不为超度 只为触摸你的指尖 那一年 磕长头匍匐在山路 不为觐见 只为贴着你的温暖 那一世 转山转水转佛塔啊 不为修来生 只为途中与你相见 只是 就在那一夜 我忘却了所有 抛却了信仰 舍弃了轮回 只为那 曾在佛前哭泣的玫瑰 早已失去旧日的光泽 </p> </li> <li><a class="fl" href="javascript:;" _mce_href="http://javascript:;"><img src="http://pic.cnblogs.com/face/u160412.jpg" _mce_src="http://pic.cnblogs.com/face/u160412.jpg" alt="" /></a> <p>班扎古鲁白玛的沉默      你见 或者不见我      我就在那里      不悲不喜           你念 或者不念我      情就在那里      不来不去           你爱 或者不爱我      爱就在那里      不增不减           你跟 或者不跟我      我的手就在你手里      不舍不弃           来我的怀里      或者      让我住进你的心间      默然 相爱      寂静 欢喜 </p> </li> </ul> </div> <script type="text/javascript"><!-- new slider({id:'slider'}) // --></script> </body> </html>


调用方式:

<script type="text/javascript">
new slider({
id:
'slider', //必选:滚动ul的id
auto:4 //可选,滚动间隙,默认3秒
})
</script>

 

 

作者: 岑安 发表于 2010-11-14 16:33 原文链接

评论: 20 查看评论 发表评论


最新新闻:
· 必应 Bing 推出 Windows Phone 7 应用可视化搜索(2010-11-15 01:14)
· 6.001 的变迁(2010-11-15 00:29)
· 百度日文版文库测试版上线(2010-11-15 00:19)
· 解剖CPU(2010-11-15 00:08)
· 怎样设计一个简洁的手机网站 - 第1部分(2010-11-14 23:44)

编辑推荐:风雨20年:我所积累的20条编程经验

网站导航:博客园首页  我的园子  新闻  闪存  小组  博问  知识库