第一次在博客园发文,有些小激动……
现在的公司使用css3和HTML5做项目,作为刚来的必须要走的路就是:折!腾!CSS3!HTML5!烦闷的是最近没捞着写后台cs。闲暇时间为了巩固之前的学习成果决定写个小功能,之前看过别人写的metro效果,跟wp上的真是相差甚远,只是简单的移动位置。前段时间还看过微软的在线体验windows phone功能,曾经想把这的功能抠下来,但一看他那js,顿时悲从中来,完全没有信心。要是能看懂,估计我就不用在国内受这虐了。自己动手,丰衣足食,恰好对老赵的jscex用了几天,用上,jquery,用上。所以网页版的windows phone metro来了,不过跟微软的真是没法比,微软的还有图片切割效果,动画也运行的非常流畅。我写的这个,诶,先看图吧:
由于截图上用的宽度远比wp手机宽,显示效果不如手机上好,当每行tile个数调整为2个时,效果蛮好。
先分析wp的动画效果,当触摸一个tile后,其他的tile按照顺序依次“溜走”,当前tile在兄弟们完全撤离后才撤离。
完成这个功能只要有了css3,一切都好办,主要用到的css的-webkit-transform属性rotateY(deg)和translate3d(x,y,z),分别代表“按Y轴旋转一定角度”、”在三维空间中变换xyz坐标三个数值”。其中rotateY的值是角度值deg是单位度,可以为负值,同样还有rotateX(deg)和rotateZ(deg)。在旋转的同时还要保证隐藏,隐藏属性opacity,此属性取值(0,1),只要在程序中保证从1递减到0就可以实现透明度过渡隐藏效果。
所以核心代码为:
tile.style.opacity = opacity;
tile.style.webkitTransform = "rotateY(-" + i + "deg) translate3d(-" + i * j + "px,0px," + i + "0px)";
tile为要操作的元素对象,只要将其两句放在for循环中根据循环变量计算相应数值即可。
可是for循环是转瞬就可以执行完的,怎么有过渡动画?这时老赵的jscex(https://github.com/JeffreyZhao/jscex)就派上了用场,间隔一段时间执行一次for就有了动态效果,$await(Jscex.Async.sleep(30));是主线程暂停30毫秒再继续运行。此外,本句应该放在jscex的变量(函数)中:var rotateFun = eval(Jscex.compile("async", function () {for(;;)}));此处Jscex.compile把内部编码编译成一个string的function,所以需要用eval执行会得到一个function,rotateFun 也就是一个函数了。现在只学会jscex的sleep-run这一招,如果不用jscex自己写setTimeout和setInterval……
有三维坐标过敏者见下图:(请注意用户的桌面所在的区域。apple的教程小加工了下,更容易理解)
apple的css3教程:http://developer.apple.com/library/safari/navigation/
此外,body属性必须加上-webkit-perspective: 1080px;和-webkit-transform-style: preserve-3d;-webkit-perspective通俗说就是“摄像机”和tile之间的距离。-webkit-transform-style: preserve-3d;表示应用3d变换,默认值是flat,表示平面。-webkit-perspective-origin: 0px -100px;表示变换的原点,我把它调整到了左上角屏幕之外,改动此属性,可以让tile藏到右边,藏到上边……
其实动画的关键就是一直修改每个tile的rotateY和translate3d属性
附上代码:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="scripts/uglifyjs-parser.js" type="text/javascript"></script>
<script src="scripts/jscex.js" type="text/javascript"></script>
<script src="scripts/jscex.builderBase.js" type="text/javascript"></script>
<script src="scripts/jscex.async.js" type="text/javascript"></script>
<script>
$(function () {
var colors = ["blue", "red", "green", "yellow", "navy", "violet", "pink", "black", "cyan", "greenyellow"];
$("div").css({ "background-color": "blue"});
var tiles = $("div");
$("div").click(function () {
var that = $(this), thisI = tiles.index(that), offset = [];
$(this).css("z-index", "-900");
$("div").each(function (i) {
$(this).attr({ "offsetLeft": $(this).offset().left, "offsetTop": $(this).offset().top });
});
var rotateFun = eval(Jscex.compile("async", function () {
for (var j = 0; j < tiles.length; j++) {
if (j == thisI) { continue; }
if (j == tiles.length - 1) {
rotateThis().start();
}
for (var i = 0; i <= 90; i += 5) {
var opacity = (100 - (i / 10) * 11.2) / 100;
var tile = tiles[j];
var tileLeft = tile.offsetLeft;
var tileTop = tile.offsetTop;
tile.style.opacity = opacity;
tile.style.webkitTransform = "rotateY(-" + i / 2 + "deg) translate3d(-" + ((i + 10) * (tileLeft / 100)) + "px,0px,100px)";
if (opacity < 0) { break; }
$await(Jscex.Async.sleep(5));
}
}
}));
var rotateThis = eval(Jscex.compile("async", function () {
for (var i = 0; i <= 90; i += 5) {
var opacity = (100 - (i / 10) * 11.2) / 100;
var thisTile = tiles[thisI];
var tileLeft = thisTile.offsetLeft;
var tileTop = thisTile.offsetTop;
thisTile.style.opacity = opacity;
thisTile.style.webkitTransform = "rotateY(-" + i / 2 + "deg) translate3d(-" + ((i + 10) * (tileLeft / 100)) + "px,0px,100px)";
if (opacity < 0) { break; }
$await(Jscex.Async.sleep(20));
}
}));
rotateFun().start();
});
});
</script>
<style>
@font-face
{
font-family: "babyface";
src: url("imgs/华康娃娃体.TTF");
}
body
{
-webkit-perspective: 900px;
-webkit-transform-style: preserve-3d;
-webkit-perspective-origin: 0px -100px;
}
div
{
font-family: "babyface" , serif;
vertical-align: bottom;
float: left;
width: 100px;
height: 100px;
text-align: center;
font-size: 90px;
color: white;
margin: 2px 2px 2px 2px;
cursor: hand;
}
div span
{
font-size: 32px;
}
</style>
</head>
<body>
<div style="font-size: 30px;">
windows</div>
<div style="font-size: 30px;">
phone</div>
<div style="font-size: 30px;">
metro</div>
<div style="font-size: 30px;">
showing</div>
<div>
☎</div>
<div style=" 204px;">
☺ <span>smile</span></div>
<div>
☼</div>
<div>
☞</div>
<div>
☻</div>
<div>
♠</div>
<div>
♪</div>
<div style=" 204px;">
♬ <span>music</span></div>
<div>
♀</div>
<div>
♂</div>
<div>
♢</div>
<div style=" 204px;">
♨ <span>coffee</span></div>
<div>
♣</div>
<div>
☜</div>
<div>
♤</div>
<div style=" 204px;">
♧ <span>WTF!</span></div>
<div>
♥</div>
<div>
♦</div>
<div>
♩</div>
<div>
♫</div>
</body>
</html>