纯css使用transform实现同心圆导航栏菜单

来源:互联网 发布:java获取方法执行时间 编辑:程序博客网 时间:2024/05/18 03:00
最近遇到客户来了一个我没遇到过的需求。那就是制作一个同心圆菜单栏。因为公司没有其他人指导我,所以我自己在网上搜索了很久,最后是根据(http://www.w3cplus.com/css3/building-a-circular-navigation-with-css-transforms.html)这个链接上的教程逐步实现了。是使用纯css3的transform来实现的,没有用过什么插件。之前对transform属性接触的比较少,所以刚开始做的时候有点吃力,当你理解后你就会知道transform是有多么的强大,当然做的时候遇到一个bug我怎么也解决不了,下面我会提出来的,希望哪位大神能够解决的告知一声;


制作的步骤:
 1.我们需要将导航项绝对定位在容器里面
 2.将每一项的变换原点设置成他们的右下角
 3.然后往左上角平移导航项,让它们的变换原点和容器中心相吻合
 4.然后按照公式顺时针旋转每一项到指定的位置:对于第i项,需要旋转:i*x,其中x是圆心角的值。
 5.然后让它们变形以获取我们想要的圆心角(使用上面提到过的公式)。
 6.反向倾斜a标签,意味着按列表项需要按相反的值倾斜, 然后用- [90 – (x/2) ]的值反向 旋转,x是圆心角的值。那么对于40度的圆心角,我们需要倾斜a标签-40度并且按-[ 90 – (40/2) ] = -70 度旋转。


a标签被绝对定位在它们的父级中,而且列表项的overflow被设置为hidden,这意味着a标签的一部分被裁切,所以为了确保a标签中的文字/图标出现在可见部分,我们将内容居中对齐。


使用到的数学知识:
 旋转导航项到指定位置:角度y = i * x (i是第几项,x是圆心角的值)
 按照90-x倾斜(x是圆心角的值)
 如果要相对称反方向旋转导航项(这一步实际上和前一步合并)

 “反向倾斜”“反向旋转”导航中的a标签(设置text-align为center)

其他不说了,贴上我的代码;

html源码:

<!doctype html><html lang="zh"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0" name="viewport" /><title></title><link rel="stylesheet" href="css/shouye.css"></head><body><header id="header"><ul><li><a href="">我的朋友圈</a></li><li><a href="">消息提醒<em>3</em></a></li><li><a href="">佩戴天数<em>6</em></a></li></ul></header><div class="logo"><img src="img/logo.png" alt=""></div><div class="wrap"><!-- 制作圆的外层导航 --><div class="csstransforms"><div class="cn-wrapper" id="cn-wrapper">    <ul>        <li><a href="#"><span>血氧</span></a></li>        <li><a href="#"><span>心率</span></a></li>        <li><a href="#"><span>呼吸</span></a></li>        <li><a href="#"><span>体温</span></a></li>        <li><a href="#"><span>体重</span></a></li>        <li><a href="#"><span>身高</span></a></li>        <li><a href="#"><span>血压</span></a></li>        <li><a href="#"><span>BMI</span></a></li>    </ul></div></div><!-- 制作圆的第二层导航 --><div class="csstransforms2"><div class="cn-wrapper2" id="cn-wrapper2">    <ul>        <li><a href="#"><span>睡眠</span></a></li>        <li><a href="#"><span>运动</span></a></li>        <li><a href="#"><span>饮食</span></a></li>        <li><a href="#"><span>情绪</span></a></li>    </ul></div></div><!-- 制作圆的最内层的logo --><div class="lat"><div class="img"><img src="img/yuan.png" alt=""></div></div></div><!-- 遮罩层 --><div id="cn-overlay" class="cn-overlay"></div> <footer id="footer"><ul><li><a href="">Life Watch</a></li><li><a href="">天使服务</a></li><li><a href="">SOS</a></li><li><a href="">健康数据</a></li><li><a href="">个人中心</a></li></ul></footer></body></html>


css源码:

@charset 'ute-8';*{margin: 0;padding: 0;}li {list-style: none;}a {text-decoration: none;}
body {overflow-x: hidden;overflow-y: hidden;/* 禁止滚动条 */}
/* header */#header{width: 100%;height: 50px;background-color: #3cb649;position: fixed;top:0;z-index: 9999;}#header li {width: 33.3%;height: 50px;line-height: 50px;float: left;text-align:center;}#header li:nth-child(3){text-indent: 20px;}#header li a {display:  block;color: #FFF;}#header li em {font-style: normal;position: relative;top: -4px;left: 2px;}/* end header *//* logo */.logo {width: 100%;height: 40px;position: fixed;top: 50px;background-color: #fff;}.logo img {display: block;width: 60%;position: relative;left: 18%;}/* end logo */.csstransforms .cn-wrapper li, .csstransforms2 .cn-wrapper2 li {position: absolute;transform-origin: 100% 100%;/* 变形原点,bottom right | right bottom 等价于 100% 100% ,每一项的变换原点设置成他们的右下角*/overflow: hidden;left: 40%;top:150px;}.csstransforms .cn-wrapper li a, .csstransforms2 .cn-wrapper2 li a {box-sizing: border-box;/* 为了设置内边距让字体居中一点的时候不会让圆变形 */display: block;position: absolute;border-radius: 50%;text-decoration: none;color: #fff;text-align: center;/* 为了确保a标签中的文字/图标出现在可见部分,将内容居中对齐 */transition: opacity 0.3s, color 0.3s;}.csstransforms .cn-wrapper li {font-size: 1.2em;width: 10em;height: 10em;margin-top: -1.3em;margin-left: -8em;}.csstransforms .cn-wrapper li a {font-size: 1.18em;height: 13em;width: 13em;bottom: -6.5em;right: -6.5em;transform: skew(-45deg) rotate(-68.5deg) scale(1);/* 反向倾斜a标签,意味着按列表项需要按相反的值倾斜, 然后用- [90 – (x/2) ]的值反向 旋转,x是圆心角的值。那么对于45度的圆心角,我们需要倾斜a标签-40度并且按-[ 90 – (40/2) ] = -68.5 度旋转 */padding-top: 10px;}.csstransforms2 .cn-wrapper2 li {font-size: 1.3em;width: 6.5em;height: 6.5em;margin-top: 1.6em;margin-left: -4.7em;transition: border .3s ease;}.csstransforms2 .cn-wrapper2 li a {font-size: 1.18em;height: 8em;width: 8em;bottom: -4em;right: -4em;transform: rotate(-45deg) scale(1);padding-top: 15px;}/* 外圈旋转与倾斜 */.csstransforms .cn-wrapper li:first-child {transform: skew(45deg);/* 90deg-xdeg,  x是你想得到的圆心角的值。*/}.csstransforms .cn-wrapper li:nth-child(2) {transform: rotate(45deg) skew(45deg);}.csstransforms .cn-wrapper li:nth-child(3) {    transform: rotate(90deg) skew(45deg)}.csstransforms .cn-wrapper li:nth-child(4) {    transform: rotate(135deg) skew(45deg);}.csstransforms .cn-wrapper li:nth-child(5) {    transform: rotate(180deg) skew(45deg);}.csstransforms .cn-wrapper li:nth-child(6) {    transform: rotate(225deg) skew(45deg);}.csstransforms .cn-wrapper li:nth-child(7) {    transform: rotate(270deg) skew(45deg);}.csstransforms .cn-wrapper li:nth-child(8) {   transform: rotate(315deg) skew(45deg);}/* 修改外圈背景颜色 */.csstransforms .cn-wrapper li:nth-child(1) a {   background-color: #70a4cc;/* 血氧 */}.csstransforms .cn-wrapper li:nth-child(2) a {   background-color: #0a71bc;/* 心率 */}.csstransforms .cn-wrapper li:nth-child(3) a {   background-color: #70a4cc;/* 呼吸 */}.csstransforms .cn-wrapper li:nth-child(4) a {   background-color: #0a71bc;/* 体温 */}.csstransforms .cn-wrapper li:nth-child(5) a {   background-color: #70a4cc;/* 体重 */}.csstransforms .cn-wrapper li:nth-child(6) a {   background-color: #0a71bc;/* 身高 */}.csstransforms .cn-wrapper li:nth-child(7) a {   background-color: #70a4cc;/* 血压 */}.csstransforms .cn-wrapper li:nth-child(8) a {   background-color: #0a71bc;/* BMI */}/* 内圈旋转与倾斜 */.csstransforms2 .cn-wrapper2 li:first-child {  }.csstransforms2 .cn-wrapper2 li:nth-child(2) {  transform: rotate(90deg);}.csstransforms2 .cn-wrapper2 li:nth-child(3) {  transform: rotate(180deg);}.csstransforms2 .cn-wrapper2 li:nth-child(4) {  transform: rotate(270deg);}/*  修改内圈背景颜色 */.csstransforms2 .cn-wrapper2 li:nth-child(1) a {  background-color: #70a4cc;/* 睡眠 */}.csstransforms2 .cn-wrapper2 li:nth-child(2) a {  background-color: #0a71bc;/* 运动 */}.csstransforms2 .cn-wrapper2 li:nth-child(3) a {  background-color: #70a4cc;/* 饮食 */}.csstransforms2 .cn-wrapper2 li:nth-child(4) a {  background-color: #0a71bc;/* 情绪 */}/* 最里层 */.lat {height: 5em;width: 5em;position: absolute;left: 41%;top: 285px;margin-top: -8px;margin-left: -6px;background-color: #0a71bc;border-radius: 50%;}.lat .img {height: 3em;    width: 3em;    margin: 4px 0 0 15px;}.lat img {display: block;width: 100%;}/*  @media screen and (max-width:480px){} */@media screen and (max-width:320px){.csstransforms .cn-wrapper li, .csstransforms2 .cn-wrapper2 li {left: 38%;top:100px;}.csstransforms .cn-wrapper li a {font-size: 1em;height: 12em;width: 12em;bottom: -6em;right: -6em;}.csstransforms2 .cn-wrapper2 li a {font-size: 1em;height: 7em;width: 7em;bottom: -3.5em;right: -3.5em;padding-top: 10px;/* 为了设置内边距的时候不会让圆变形 */}.lat {height: 4em;width: 4em;left: 34%;top: 243px;margin-top: -8px;margin-left: 18px;}.lat .img {height: 2em;width: 2em;margin: 8px 0 0 15px;}.lat img {display: block;width: 100%;}} .cn-overlay{width:100%height:100%;background-color: #eeedf3;position:fixed;top:0;left:0;bottom:0;right:0;transition: all .3s ease;z-index:-2;pointer-events:auto;opacity:0.8;}#footer {width: 100%;height: 40px;position: fixed;bottom: 0;background-color: #e7e7e7;}#footer li {height: 40px;line-height: 40px;float: left;text-align: center;}#footer li:first-child{width: 26%;box-sizing: border-box; border-right: 1px solid #0e7a9e;}#footer li:nth-child(2){width: 20%;}#footer li:nth-child(3){width: 14%;height: 50px;border-radius: 50%;background-color: #3cb649;position: relative;top: -20px;}#footer li:nth-child(4){width: 20%;box-sizing: border-box; border-right: 1px solid #0e7a9e;}#footer li:nth-child(5){width: 20%;}#footer li a {color: #333;font-size: 14px;}#footer li:nth-child(3) a{font-size: 20px;color: #daede9;}


最后提一下自己遇到的一个问题,就是我设置了li隐藏,因为它是绝对定位的,脱离了文档流,所以我想去除掉他的溢出,但是我没有实现到,可以用边框就能检验到,所以他依旧占着空间造成滚动条的出现,我是这样来解决的:

body {overflow-x: hidden;overflow-y: hidden;/* 禁止滚动条 */}


希望哪位牛人能有解决方法告诉我一声。如下图:


最后附上自己最终实现客户需要的效果:


                                             
0 0