![服务过美国总统竞选的非传统投票UI [解析及DEMO] 服务过美国总统竞选的非传统投票UI [解析及DEMO]](https://image.shishitao.com:8440/aHR0cHM6Ly9ia3FzaW1nLmlrYWZhbi5jb20vdXBsb2FkL2NoYXRncHQtcy5wbmc%2FIQ%3D%3D.png?!?w=700&webp=1)
![服务过美国总统竞选的非传统投票UI [解析及DEMO] 服务过美国总统竞选的非传统投票UI [解析及DEMO]](https://image.shishitao.com:8440/aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2kvNjM2MDE1LzIwMTQwNi8zMDAwMDExMDg1MTY2OTAuanBn.jpg?w=700&webp=1)
这种非常规的UI,在底层还是由常规的元素组成,在实现上,需要前端开发者想办法,创造(没错,是创造,在现在常规资源的基础上进行组合创造)出非常规的效果。
接下来,我们切入正题。
看到效果图后,我分析了一下,打算这样搭元素结构。最外面一个div,作为这个ui的最外层,里面再来三个div,两个用来放置左右直角梯形(里面再放图片和文字元素),余下的一个做成中间的faceoff图标。
html代码结构是这个样子。
<div id="faceoff">
<div id="person1" class="pic_wrap">
<div class="pic">
<div class="desc">
<div class="content">
Raised in Bloomfield Hills, Michigan, by his parents George and Lenore Romney, Mitt Romney spent two and a half years in France as a Mormon missionary starting in 1966. In 1969 he married Ann Davies, with whom he has had five sons. By 1971, Romney had participated in the political campaigns of both of his parents. He earned a Bachelor of Arts at Brigham Young and in 1975.
</div>
<div class="title">Mitt Romney</div>
</div>
</div>
</div>
<div id="faceoffIcon">FACEOFF</div>
<div id="person2" class="pic_wrap">
<div class="pic">
<div class="desc">
<div class="title">Barack Obama</div>
<div class="content">
Born in Honolulu, Hawaii, Obama is a graduate of Columbia University and Harvard Law School, where he served as president of the Harvard Law Review. He was a community organizer in Chicago before earning his law degree. He worked as a civil rights attorney and taught constitutional law at the University of Chicago Law School from 1992 to 2004.
</div>
</div>
</div>
</div>
</div>
![服务过美国总统竞选的非传统投票UI [解析及DEMO] 服务过美国总统竞选的非传统投票UI [解析及DEMO]](https://image.shishitao.com:8440/aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2kvNjM2MDE1LzIwMTQwNy8wMzE1NTkzNDk5NjkyMjkucG5n.png?w=700&webp=1)
这个好办,我们把图像再扭回来就是了。来,反向扯一下。OK!现在正常了。
![服务过美国总统竞选的非传统投票UI [解析及DEMO] 服务过美国总统竞选的非传统投票UI [解析及DEMO]](https://image.shishitao.com:8440/aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2kvNjM2MDE1LzIwMTQwNy8wMzE2MDA1MjE2ODM3NzMucG5n.png?w=700&webp=1)
![服务过美国总统竞选的非传统投票UI [解析及DEMO] 服务过美国总统竞选的非传统投票UI [解析及DEMO]](https://image.shishitao.com:8440/aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2kvNjM2MDE1LzIwMTQwNy8wODE1NTYyMjA5ODcwNDcuanBn.jpg?w=700&webp=1)
补充一句,这种做法还可以做这种非常规ui
![服务过美国总统竞选的非传统投票UI [解析及DEMO] 服务过美国总统竞选的非传统投票UI [解析及DEMO]](https://image.shishitao.com:8440/aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2kvNjM2MDE1LzIwMTQwNy8wMzE1NDUzOTk2NTc5MjQuanBn.jpg?w=700&webp=1)
做好了形状,接着来完成文字部分,这种非常规排版方式,adobe有过提议(CSS Shape),但目前CSS Shape只能在Webkit Nightly和Chrome Canary浏览器中实现,等以后等普及后,我们可以做出类似于这种效果。
![服务过美国总统竞选的非传统投票UI [解析及DEMO] 服务过美国总统竞选的非传统投票UI [解析及DEMO]](https://image.shishitao.com:8440/aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2kvNjM2MDE1LzIwMTQwNy8wMzE1NDQ1NDAxMjgwMTguanBn.jpg?w=700&webp=1)
因为浏览器支持度不够,我们要实现非常规的UI,还是得用别的办法。plusice同学提出,我们可以在文字中插入一些 (空格)达到这个效果,这种方法可行,但难点是,需要找到插入点和应插入的空格数量。
我用另一种办法达到了这个效果,给大家看三张图,大家就能理解了:
![服务过美国总统竞选的非传统投票UI [解析及DEMO] 服务过美国总统竞选的非传统投票UI [解析及DEMO]](https://image.shishitao.com:8440/aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2kvNjM2MDE1LzIwMTQwNy8wODE1MzM0OTE3NjQzNTYuanBn.jpg?w=700&webp=1)
![服务过美国总统竞选的非传统投票UI [解析及DEMO] 服务过美国总统竞选的非传统投票UI [解析及DEMO]](https://image.shishitao.com:8440/aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2kvNjM2MDE1LzIwMTQwNy8wODE1MzQwNjYxNDM4ODIuanBn.jpg?w=700&webp=1)
![服务过美国总统竞选的非传统投票UI [解析及DEMO] 服务过美国总统竞选的非传统投票UI [解析及DEMO]](https://image.shishitao.com:8440/aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2kvNjM2MDE1LzIwMTQwNy8wODE1MzQ0MDUzNTIxODEuanBn.jpg?w=700&webp=1)
这种做法需要解决的是,这些占位元素的宽度各是多少?这里我们借助程序来实现。
//依据角的邻边算对边长度
function getWidth(height) {
return Math.tan(deg * Math.PI / 180) * height;
}
// 依据行数得到角的邻边长度,进而算得对边长度
function getWidthByLineIndex(i) {
return getWidth(i * lineHeight);
}
文本内容完成了,接下来做遮罩。使鼠标在图片上面时,介绍内容滑下来。这个一般是用改变dom的属性实现的,但不是本文的重点,我就偷个懒直接用css3 动画来做了。
#person1>.pic:hover>.desc {
-webkit-animation: left-show 0.8s 0s normal forwards;
-webkit-animation-timing-function: ease-in;
}
#person1>.pic>.desc {
-webkit-animation: left-hide 0.8s 0s normal forwards;
-webkit-animation-timing-function: ease-out;
}
#person2>.pic:hover>.desc {
-webkit-animation: right-show 0.8s 0s normal forwards;
-webkit-animation-timing-function: ease-in;
}
#person2>.pic>.desc {
-webkit-animation: right-hide 0.8s 0s normal forwards;
-webkit-animation-timing-function: ease-out;
}
@-webkit-keyframes left-show {
from {
margin-top: -440px;
}
to {
margin-top: 0px;
}
}
@-webkit-keyframes left-hide {
from {
margin-top: 0px;
}
to {
margin-top: -440px;
}
}
@-webkit-keyframes right-show {
from {
margin-top: 440px;
}
to {
margin-top: 0px;
}
}
@-webkit-keyframes right-hide {
from {
margin-top: 0px;
}
to {
margin-top: 440px;
}
}
hover滑动动画
![服务过美国总统竞选的非传统投票UI [解析及DEMO] 服务过美国总统竞选的非传统投票UI [解析及DEMO]](https://image.shishitao.com:8440/aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2kvNjM2MDE1LzIwMTQwNy8wODE1NDczMjc1NDQzOTcuanBn.jpg?w=700&webp=1)
好吧,抱着追求完美的心态,我们来解决这个问题。将元素3d变换不仅可以开启硬件加速,让元素脱离文档流,提升性能,还可以达到我们的目的-反锯齿。但缺点是,字会有点模糊(因为它会把在上面的图或文字等内容当成图片纹理来贴图),不过这个小瑕疵比锯齿好得多。如果大家有别的方法完美消锯齿,也请告诉我。
![服务过美国总统竞选的非传统投票UI [解析及DEMO] 服务过美国总统竞选的非传统投票UI [解析及DEMO]](https://image.shishitao.com:8440/aHR0cHM6Ly9pbWFnZXMwLmNuYmxvZ3MuY29tL2kvNjM2MDE1LzIwMTQwNy8wODE1NDk1NTIzOTY0NTkuanBn.jpg?w=700&webp=1)
好,收摊。现在各位感觉到了,实现这个UI其实也不难,要用点巧即可。实现方法不止一种,我感觉我虽然实现了这个需求,但我相信还有别的更优雅的办法。此文仅做抛砖引玉,大家如果有别的实现方法,和我分享下哟。 :)
<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
<meta charset="UTF-8">
<title>Faceoff</title>
<style type="text/css">
div#faceoff {
overflow: hidden;
width: 710px;
}
.pic>.desc {
background-color: rgba(0, 0, 0, 0.5);
color: white;
}
.pic>.desc>.content {
font-size: 22px;
line-height: 26px;
word-break: break-all;
}
.pic>.desc>.title {
font-size: 30px;
margin-bottom: 20px;
}
.pic_wrap {
-webkit-transform: skewX(-13deg) translateZ(0);
overflow: hidden;
width: 353px;
height: 480px;
position: relative;
}
#person1 {
left: -87px;
float: left;
}
#person1>.pic {
width: 461px;
height: 480px;
background: url("resources/1.jpg") no-repeat;
background-position: -51px 0px;
background-size: 620px 480px;
-webkit-transform: skewX(13deg);
}
#person1>.pic>.desc {
width: 312px;
float: left;
margin-left: 90px;
margin-top: -440px;
}
#person1>.pic>.desc>.title {
text-align: left;
padding-left: 5px;
}
#person1>.pic>.desc>.content {
padding: 2px;
height: 440px;
}
#person2 {
left: -57px;
}
#person2>.pic {
width: 361px;
height: 480px;
background: url("resources/2.jpg") no-repeat;
background-position: 20px -25px;
background-size: 376px 540px;
-webkit-transform: skewX(13deg);
margin-left: -100px;
}
#person2>.pic>.desc {
width: 320px;
float: right;
}
#person2>.pic>.desc>.title {
text-align: right;
padding-right: 5px;
}
#person2>.pic>.desc>.content {
padding-right: 2px;
height: 440px;
}
.space {
/* border: 1px solid red;*/
height: 22px;
}
.space.left {
float: left;
clear: left;
}
.space.right {
float: right;
clear: right;
}
#faceoffIcon {
width: 80px;
height: 80px;
position: absolute;
background-color: red;
border: 3px solid white;
border-radius: 40px;
top: 194px;
left: 247px;
z-index: 2;
color: white;
line-height: 80px;
text-align: center;
font-weight: bold;
}
#faceoff:hover>#faceoffIcon {
display: none;
}
#person1>.pic:hover>.desc {
-webkit-animation: left-show 0.8s 0s normal forwards;
-webkit-animation-timing-function: ease-in;
}
#person1>.pic>.desc {
-webkit-animation: left-hide 0.8s 0s normal forwards;
-webkit-animation-timing-function: ease-out;
}
#person2>.pic:hover>.desc {
-webkit-animation: right-show 0.8s 0s normal forwards;
-webkit-animation-timing-function: ease-in;
}
#person2>.pic>.desc {
-webkit-animation: right-hide 0.8s 0s normal forwards;
-webkit-animation-timing-function: ease-out;
}
@-webkit-keyframes left-show {
from {
margin-top: -440px;
}
to {
margin-top: 0px;
}
}
@-webkit-keyframes left-hide {
from {
margin-top: 0px;
}
to {
margin-top: -440px;
}
}
@-webkit-keyframes right-show {
from {
margin-top: 440px;
}
to {
margin-top: 0px;
}
}
@-webkit-keyframes right-hide {
from {
margin-top: 0px;
}
to {
margin-top: 440px;
}
} </style>
</head>
<body>
<div id="faceoff">
<div id="person1" class="pic_wrap">
<div class="pic">
<div class="desc">
<div class="content">
Raised in Bloomfield Hills, Michigan, by his parents George and Lenore Romney, Mitt Romney spent two and a half years in France as a Mormon missionary starting in 1966. In 1969 he married Ann Davies, with whom he has had five sons. By 1971, Romney had participated in the political campaigns of both of his parents. He earned a Bachelor of Arts at Brigham Young and in 1975.
</div>
<div class="title">Mitt Romney</div>
</div>
</div>
</div>
<div id="faceoffIcon">FACEOFF</div>
<div id="person2" class="pic_wrap">
<div class="pic">
<div class="desc">
<div class="title">Barack Obama</div>
<div class="content">
Born in Honolulu, Hawaii, Obama is a graduate of Columbia University and Harvard Law School, where he served as president of the Harvard Law Review. He was a community organizer in Chicago before earning his law degree. He worked as a civil rights attorney and taught constitutional law at the University of Chicago Law School from 1992 to 2004.
</div>
</div>
</div>
</div>
</div> <script type="text/javascript">
//角度为13度
var deg = 13,
//占位元素的高
lineHeight = 22,
//元素高
contentHeight = 460,
//占位元素个数(行数)
lineCount = Math.ceil(contentHeight / lineHeight),
//相邻两个占位元素的宽度偏移量
lineOffset = getWidth(lineHeight),
//最大占位容器宽度,右侧的占位容器从大到小递减,左侧的占位元素从小到大递增
lineMaxWidth = getWidth(contentHeight); //用占位容器来填充形状
function SetShape(isRight) {
var oFrag = document.createDocumentFragment();
if (isRight) {
for (var i = 0; i < lineCount; i++) {
var op = document.createElement("span");
op.classList.add("space");
op.classList.add("left");
// 右侧的占位容器从大到小递减
op.style.width = (lineMaxWidth - i * lineOffset) + "px";
oFrag.appendChild(op);
}
document.querySelector("#person2 .desc").insertBefore(oFrag, document.querySelector("#person2 .content"));
} else {
for (var i = 0; i < lineCount; i++) {
var op = document.createElement("span");
op.classList.add("space");
op.classList.add("right");
// 左侧的占位元素从小到大递增
op.style.width = (i * lineOffset) + "px";
oFrag.appendChild(op);
}
document.querySelector("#person1 .desc").insertBefore(oFrag, document.querySelector("#person1 .content"));
} }
//依据角的邻边算对边长度
function getWidth(height) {
return Math.tan(deg * Math.PI / 180) * height;
}
// 依据行数得到角的邻边长度,进而算得对边长度
function getWidthByLineIndex(i) {
return getWidth(i * lineHeight);
}
SetShape(false);
SetShape(true);
</script> </body>
</html>
faceoff全部代码
素材两张(尺寸已缩小,可右键下载源图):
本文是博主Arfei Zhang原创,欢迎转载。转载请注明转自博客园,并附上本文链接http://www.cnblogs.com/arfeizhang/p/faceoffdemo.html,谢谢!