使用CSS变换构建环形导航

本教程详细介绍了如何使用CSS变换创建环形导航。通过逐步解释数学原理和CSS转换,展示了如何根据所需的中心角值创建角度。教程涵盖了设置导航布局、定位项目、应用CSS变换、倾斜和旋转元素以及处理内容扭曲的步骤。此外,还提到了JavaScript的使用,以及为不支持CSS变换的浏览器提供备用方案。
摘要由CSDN通过智能技术生成
CircularNavigation

In this tutorial I’m going to show you how to create circular navigations using CSS transforms. I’m going to take you through the steps for creating these styles one by one, and explain the math (yikes!) and simple logic behind them so you get a clear understanding of the technique.

在本教程中,我将向您展示如何使用CSS转换创建循环导航。 我将逐步指导您逐步创建这些样式,并解释其背后的数学原理(简单的逻辑),以便您清楚地了解该技术。

Like I mentioned, there’s going to be some basic math involved, along with CSS transforms to create these styles. But don’t worry, the math is really very simple and I’ll be going through it step by step.

就像我提到的,将涉及一些基本数学,以及创建这些样式CSS转换。 但请放心,数学实际上非常简单,我将逐步讲解它。

I also want to mention that credit for the original technique goes to Ana Tudor. I tweaked it to achieve the results that I wanted, which is also what I’m hoping you’ll be able to do by the end of this tutorial: have a deep and clear understanding of the technique so you can start fiddling around and creating your own styles.

我还想提到,对原始技术的赞誉归于Ana Tudor 。 我对其进行了调整,以实现所需的结果,这也是我希望您能够在本教程结束时完成的工作:对这项技术有深刻而清晰的了解,因此您可以开始摆弄和创建自己的风格。

So, without further ado, let’s get started!

因此,事不宜迟,让我们开始吧!

标记 (The Markup)

We’re going to be building a navigation, so we’ll start with a regular navigation structure. We’ll need a div to contain our unordered list of items, a button to trigger the opening and closing of the navigation, the list of items, and for the first demo we’ll need an extra overlay to cover the page when the navigation is open.

我们将要构建一个导航,因此我们将从常规导航结构开始。 我们需要一个div来包含我们无序的项目列表,一个按钮来触发导航的打开和关闭,项目列表,并且对于第一个演示,我们需要一个额外的覆盖层来覆盖导航时的页面开了。

<button class="cn-button" id="cn-button">+</button>
<div class="cn-wrapper" id="cn-wrapper">
   <ul>
       <li><a href="#"><span class="icon-picture"></span></a></li>
       <li><a href="#"><span class="icon-headphones"></span></a></li>
       <li><a href="#"><span class="icon-home"></span></a></li>
       <li><a href="#"><span class="icon-facetime-video"></span></a></li>
       <li><a href="#"><span class="icon-envelope-alt"></span></a></li>
   </ul>
</div>
<div id="cn-overlay" class="cn-overlay"></div>

The icons we’re using in this demo are from Font Awesome.

我们在此演示中使用的图标来自Font Awesome

CSS转换背后的数学 (The Math Behind the CSS Transforms)

The best way to explain the math is to use a visual explanation instead of a written one. So I’ll start with the logic and we’ll apply the math as we go, and after we’re done with our explanation we’ll get to the coding part, at which point you’ll be able to know what each CSS rule exactly does.

解释数学的最好方法是使用视觉解释,而不是书面解释。 所以我将从逻辑开始,我们将继续应用数学,在完成解释之后,我们将进入编码部分,此时您将能够知道每个CSS的含义。规则确实如此。

First let’s go over what a “central angle” is. This is a visual representation followed by a simple explanation:

首先让我们看一下“中心角”是什么。 这是一个视觉表示,后面是一个简单的解释:

cn-central-angle

Suppose you want to distribute all navigation items on a semi-circle like the example we’re making here, and you have 6 items in your navigation list, then each angle would have a central angle of:

假设您想像我们在此所做的示例一样,将所有导航项分布在一个半圆上,并且您的导航列表中有6个项,那么每个角度的中心角为:

180deg / 6 = 30deg

180度/ 6 = 30度

If you want the items to take up a complete circle, and you have 6 items you want to have in this circle, the central angle for each item would be:

如果您希望这些项目占据一个完整的圆,并且您希望在该圆中包含6个项目,则每个项目的中心角将为:

360deg / 6 = 60deg

360度/ 6 = 60度

And so on. So you calculate the value of the central angle you want, and from here on we’ll start applying some simple math to CSS transforms to actually create these angles.

等等。 因此,您可以计算所需的中心角的值,从这里开始,我们将对CSS转换应用一些简单的数学运算以实际创建这些角度。

To create an angle of value equal to our desired central angle value, we’ll have to skew the items (using the skew() CSS function) by:

要创建一个等于我们期望的中心角值的角度,我们必须通过以下方式使这些项目倾斜(使用skew()CSS函数):

90deg – x deg, where x is the value of the central angle we want.

90deg – x deg其中x是我们想要的中心角的值

Simple. But in this case, all the content inside the list items will also be skewed and the content will look distorted, which is not what we want, so we’ll “unskew” the anchors inside each item so that the content looks fine, but we’ll get to that in a moment.

简单。 但是在这种情况下,列表项中的所有内容也会发生扭曲,并且内容看起来会失真,这不是我们想要的,因此我们将“扭曲”每个项中的锚点,以使内容看起来不错,但是我们稍后会解决。

I’ve set up a live and interactive demo that will show you how the transforms are applied to the navigation items step by step so you get a clearer understanding of what we’ll be doing in the code. (Note that the walkthrough in the demo may differ slightly in order of steps from the steps we’ll be taking in the tutorial)

我已经建立了一个实时的交互式演示,它将向您逐步展示如何将变换应用于导航项,以便您更清楚地了解我们将在代码中执行的操作。 (请注意,演示中的演练在步骤顺序上可能与我们在本教程中将采取的步骤略有不同)

You might want to play the step-by-step demo at this point to get a clearer understanding of what we’ll be doing next. I’ve also added a walkthrough to the demo which explains what’s happening in each step, so take a minute to play the demo and try to gain a better understanding of what we’ll do. You can play the demo from start to finish using the Start Demo Button, or control moving from step to step using the Next Step Button, and you can reset it anytime using the Reset Button.

您可能需要在此时播放分步演示,以更清楚地了解我们下一步将要做的事情。 我还在演示中添加了演练,它解释了每个步骤中发生的事情,因此请花一点时间来播放演示,并尝试更好地了解我们将做的事情。 您可以使用“开始演示”按钮从头到尾播放演示,也可以使用“下一步”按钮控制逐步移动的演示,您可以随时使用“重置”按钮将其重置。

View the interactive demo

查看互动演示

Here are screenshots of the steps you’re going to see in the demo:

这是您将在演示中看到的步骤的屏幕截图:

初始状态: (Initial state:)
Step-0
第1步: (Step 1:)
Step-1
第2步: (Step 2:)
step-2
第4步: (Step 4:)
Step-4
步骤5: (Step 5:)
Step-5
步骤6: (Step 6:)
Step-6
步骤7 (Step 7)
Step-7

So let’s go over this again:

因此,让我们再看一遍:

  • we’ll need to position the items absolutely inside their container.

    我们需要将这些物品完全放置在其容器内。
  • We’ll set the transform-origin for each item to be the bottom right corner.

    我们将每个项目的transform-origin设置为右下角。
  • We’ll then translate the items up and to the left just enough so that their transform origin coincides with their container’s center.

    然后,我们将这些项左右平移,以使它们的变换原点与容器的中心重合。
  • We’ll then rotate the items clockwise into their positions using this formula: For each item of index i we rotate it by: i * x , where x is again the value of the central angle

    然后,我们使用以下公式将项目顺时针旋转到它们的位置:对于索引i的每个项目,我们将其旋转: i * x其中x再次是中心角的值

  • then skew them to get the central angle we want (using the formula we mentioned above)

    然后倾斜它们以获得我们想要的中心角(使用上面提到的公式)

In our example, we have 5 items, which means 5 central angles, that we want to cover only the upper half of the circle, so according to the math we explained above, every item would have a central angle of 36deg, but in our example I’ve set the central angle value to 40deg (because it provides a bigger clickable area), so the sum of all angles will be 5 * 40 = 200deg which is greater than 180deg. In this case, all we do is just rotate the items “back” counter-clockwise by (200-180)/2 deg to ensure they are balanced on both sides.

在我们的示例中,我们有5个项,即5个圆心角,我们只想覆盖圆的上半部分,因此根据我们上面解释的数学,每个项目的中心角为36度,但是在我们的示例中示例我将中心角度值设置为40deg(因为它提供了更大的可单击区域),因此所有角度的总和将为5 * 40 = 200deg ,大于180deg。 在这种情况下,我们要做的只是逆时针将项目“向后”旋转(200-180)/ 2度,以确保它们在两侧都平衡。

At this point we have created our central angles and positioned them. But skewing the list items has also caused their content (anchor tags) to skew too, and thus caused their content to be distorted, so the last mathematical rule we’ll be applying here (phew!) is one that will make sure the anchor tags aren’t distorted and their content be visible. The rule is:

至此,我们已经创建了中心角并对其进行了定位。 但是倾斜列表项也会导致其内容(锚标记)也倾斜,从而导致其内容失真,因此我们将在此处应用的最后一个数学规则(phe!)将确保锚定标签不会失真,其内容可见。 规则是:

You unskew the anchor tags, which means you skew them by the opposite value of that you used to skew the list items, and then you unrotate the anchors by a value of: – [90 – (x/2) ] , with x being the value of the central angle so, for a central angle value of 40deg, we have to skew the anchors by -40deg and rotate them by: -[ 90 – (40/2) ] = -70 deg

倾斜锚标记,这意味着您以与倾斜列表项时使用的值相反的值使其倾斜,然后以以下值旋转锚: – [90 –(x / 2)]其中x为中心角的值,因此,对于40deg的中心角,我们必须将锚点倾斜-40deg并将其旋转: -[90 –(40/2)] = -70 deg

The anchors are positioned absolutely inside their parents, and the overflow is set to hidden on the list items, which means that part of the anchors is cut off, so in order to make sure that the text/icon content of the anchors lies within their visible part, we’ll set their text to be aligned at the center.

锚点绝对位于其父对象的内部,并且溢出项在列表项中设置为隐藏,这意味着部分锚点被切除,因此,请确保锚点的文本/图标内容位于它们的内部可见部分,我们将其文字设置为居中对齐。

And that’s all the math you need to create the slices inside the navigation! Phew, finally, right?

这就是在导航内创建切片所需的全部数学知识! ew,最后,对吧?

So let’s go over this one more time, quickly:

因此,让我们快速地再经历一次:

  1. Rotate the items into position by: angle y = i * x (where i = index of item, and x = value of central angle)

    将项目旋转​​到适当的位置:角度y = i * x(其中i =项目的索引,x =中心角的值)
  2. Skew them by 90deg – x (where x is the value of central angle, again)

    将它们倾斜90度– x(其中x再次是中心角的值)
  3. Rotate items in the opposite direction if/when needed to balance (this step is actually merged with the previous one, you subtract the value by which you want to rotate the angles back from the value of the angle you rotate them by)

    如果需要平衡,则沿相反方向旋转项目(此步骤实际上与上一步合并,您从旋转角度的值中减去要向后旋转角度的值)
  4. “Unskew” and “unrotate” the anchors inside them (and set their text align to center”)

    “扭曲”和“旋转”其中的锚点(并使其文本居中对齐)

Of course I’ve skipped part where you move the list items so that their transform origin coincides with their container’s center (as shown in the demo). And that’s pretty much all you need to create the angles, but that’s not everything you need to create the whole navigation. A few simple steps remain, and they are pretty much just regular styling, so let’s start with the CSS and talk about these steps as we go!

当然,我已经跳过了将列表项移至何处的部分,以使它们的变换原点与容器的中心重合(如演示中所示)。 这几乎是创建角度所需的全部,但这不是创建整个导航所需的全部。 剩下一些简单的步骤,它们几乎只是常规样式,所以让我们从CSS开始,然后讨论这些步骤!

CSS (The CSS)

We’re first going to style the first demo.

我们首先要设计第一个演示的样式。

CircularNavigation_Demo1

We’re going to use Modernizr‘s classes applied to the body tag to target supporting and non-supporting browsers, and provide a very simple and basic fallback for older browsers that do not support CSS transforms. Let’s start with the styles for the navigation wrapper. It will get a fixed position at the bottom center of the page, and will initially be scaled down, and when the open button is clicked it will open / scale up.

我们将使用应用于body标签的Modernizr的类来定位支持和不支持的浏览器,并为不支持CSS转换的旧版浏览器提供非常简单和基本的备用。 让我们从导航包装的样式开始。 它会在页面底部居中放置一个固定位置,并且最初会按比例缩小,而当单击打开按钮时,它将打开/放大。

.csstransforms .cn-wrapper {
  font-size:1em;
  width: 26em;
  height: 26em;
  overflow: hidden;
  position: fixed;
  z-index: 10;
  bottom: -13em;
  left: 50%;
  border-radius: 50%;
  margin-left: -13em;
  transform: scale(0.1);
  transition: all .3s ease;
}
/* class applied to the container via JavaScript that will scale the navigation up */
.csstransforms .opened-nav {
  border-radius: 50%;
  transform: scale(1);
}

We’ll also style and position the button which will trigger the opening and closing of our navigation.

我们还将设置按钮的样式和位置,以触发导航的打开和关闭。

.cn-button {
  border:none;
  background:none;
  color: white;
  text-align: Center;
  font-size: 1.5em;
  padding-bottom: 1em;
  height: 3.5em;
  width: 3.5em;
  background-color: #111;
  position: fixed;
  left: 50%;
  margin-left: -1.75em;
  bottom: -1.75em;
  border-radius: 50%;
  cursor: pointer;
  z-index: 11
}
.cn-button:hover,
.cn-button:active,
.cn-button:focus{
  background-color: #222;
}

When the navigation is opened, an overlay covers the page. Here are the styles for the overlay.

导航打开后,页面上将覆盖一个覆盖层。 这是叠加层的样式。

.cn-overlay{
  width:100%
  height:100%;
  background-color: rgba(0,0,0,0.6);
  position:fixed;
  top:0;
  left:0;
  bottom:0;
  right:0;
  opacity:0;
  transition: all .3s ease;
  z-index:2;
  pointer-events:none;
}

/* Class added to the overlay via JavaScript to show it when navigation is open */
.cn-overlay.on-overlay{
  pointer-events:auto;
  opacity:1;
}

Now we’ll style the navigation items and their anchors, applying the logic and math-based transformed we explained earlier.

现在,我们将对导航项及其锚点进行样式设置,应用我们之前解释的基于逻辑和数学的转换。


.csstransforms .cn-wrapper li {
  position: absolute;
  font-size: 1.5em;
  width: 10em;
  height: 10em;
  transform-origin: 100% 100%;
  overflow: hidden;
  left: 50%;
  top: 50%;
  margin-top: -1.3em;
  margin-left: -10em;
  transition: border .3s ease;
}

.csstransforms .cn-wrapper li a {
  display: block;
  font-size: 1.18em;
  height: 14.5em;
  width: 14.5em;
  position: absolute;
  bottom: -7.25em;
  right: -7.25em;
  border-radius: 50%;
  text-decoration: none;
  color: #fff;
  padding-top: 1.8em;
  text-align: center;
  transform: skew(-50deg) rotate(-70deg) scale(1);
  transition: opacity 0.3s, color 0.3s;
}

.csstransforms .cn-wrapper li a span {
  font-size: 1.1em;
  opacity: 0.7;
}
/* for a central angle x, the list items must be skewed by 90-x degrees
in our case x=40deg so skew angle is 50deg
items should be rotated by x, minus (sum of angles - 180)2s (for this demo) */

.csstransforms .cn-wrapper li:first-child {
  transform: rotate(-10deg) skew(50deg);
}

.csstransforms .cn-wrapper li:nth-child(2) {
  transform: rotate(30deg) skew(50deg);
}

.csstransforms .cn-wrapper li:nth-child(3) {
  transform: rotate(70deg) skew(50deg)
}

.csstransforms .cn-wrapper li:nth-child(4) {
  transform: rotate(110deg) skew(50deg);
}

.csstransforms .cn-wrapper li:nth-child(5) {
  transform: rotate(150deg) skew(50deg);
}

.csstransforms .cn-wrapper li:nth-child(odd) a {
  background-color: #a11313;
  background-color: hsla(0, 88%, 63%, 1);
}

.csstransforms .cn-wrapper li:nth-child(even) a {
  background-color: #a61414;
  background-color: hsla(0, 88%, 65%, 1);
}

/* active style */
.csstransforms .cn-wrapper li.active a {
  background-color: #b31515;
  background-color: hsla(0, 88%, 70%, 1);
}

/* hover style */
.csstransforms .cn-wrapper li:not(.active) a:hover,
.csstransforms .cn-wrapper li:not(.active) a:active,
.csstransforms .cn-wrapper li:not(.active) a:focus {
  background-color: #b31515;
  background-color: hsla(0, 88%, 70%, 1);
}
.csstransforms .cn-wrapper li:not(.active) a:focus {
  position: fixed; /* fix the "displacement" bug in webkit browsers when using tab key */
}

We’ll provide a simple and basic fallback for browsers that do not support CSS transforms.

我们将为不支持CSS转换的浏览器提供一个简单而基本的备用。


.no-csstransforms .cn-wrapper{
  font-size:1em;
  height:5em;
  width:25.15em;
  bottom:0;
  margin-left: -12.5em;
  overflow: hidden;
  position: fixed;
  z-index: 10;
  left:50%;
  border:1px solid #ddd;
}

.no-csstransforms .cn-button{
  display:none;
}

.no-csstransforms .cn-wrapper li{
  position:static;
  float:left;
  font-size:1em;
  height:5em;
  width:5em;
  background-color: #eee;
  text-align:center;
  line-height:5em;
}

.no-csstransforms .cn-wrapper li a{
  display:block;
  width:100%;
  height:100%;
  text-decoration:none;
  color:inherit;
  font-size:1.3em;
  border-right: 1px solid #ddd;
}

.no-csstransforms .cn-wrapper li a:last-child{
  border:none;
}

.no-csstransforms .cn-wrapper li a:hover,
.no-csstransforms .cn-wrapper li a:active,
.no-csstransforms .cn-wrapper li a:focus{
  background-color: white;
}

.no-csstransforms .cn-wrapper li.active a {
  background-color: #6F325C;
  color: #fff;
}

Of course we want our navigation to be responsive, so it will shrink to fit smaller screens. Here are the responsive styles for both the circular and the simple styles.

当然,我们希望导航能够响应,因此它将缩小以适合较小的屏幕。 这是圆形和简单样式的响应样式。

@media screen and (max-width:480px){
  .csstransforms .cn-wrapper{
    font-size:.68em;
  }
  .cn-button{
    font-size:1em;
  }
  .csstransforms .cn-wrapper li {
    font-size:1.52em;
  }
}

@media screen and (max-width:320px){
  .no-csstransforms .cn-wrapper{
    width:15.15px;
    margin-left: -7.5em;
  }
  .no-csstransforms .cn-wrapper li{
    height:3em;
    width:3em;
  }
}

And that’s it for the first demo! Let’s move on to the next one.

这就是第一个演示! 让我们继续下一个。

CircularNavigation_Demo2

The second circular style is different from the first one, but all the math and logic and transforms needed to create this style is pretty much the same as the previous one, except for three differences. So we won’t be going over the same explanation again, we’ll only cover the three different steps needed for this style.

第二种圆形样式与第一种圆形样式不同,但是创建该样式所需的所有数学,逻辑和变换与前一种样式几乎相同,除了三个区别。 因此,我们将不再重复相同的解释,我们将仅介绍此样式所需的三个不同步骤。

Let’s take the above example again, and change just a small simple CSS rule, and see what difference it makes to the shape of the items.

让我们再次以上述示例为例,并更改一条简单的简单CSS规则,看看它对项目形状有何不同。

cn-radial-gradient
cn-demo2-step1

As you see the navigation is already starting to look different; we’re more than halfway through. We still have one important thing to do. At the current state of this style, the clickable area of the anchors is still bigger than what we want. What we do want, is that only the colored part of the navigation shown in the image be clickable/hoverable. The image below shows the extra clickable area of the anchors.

如您所见,导航已经开始看起来有所不同。 我们已经完成了一半以上。 我们还有一件重要的事情要做。 在此样式的当前状态下,锚点的可单击区域仍大于我们想要的区域。 我们要做的是仅使图像中显示的导航的彩色部分可点击/可悬停。 下图显示了锚点的额外可点击区域。

cn-demo2-cover

When you hover over the red area shown in the image, which is the lower part of the anchor tags, the hover state of the anchors is fired, which is the normal thing to happen, but because we want it to seem like the anchors are only the purple area, we need to prevent mouse events from firing on the lower part of the anchors. For this we’re going to use a “cover” which we’ll place over at the center of the navigation container, which will be a circular shape covering the lower parts of the anchors, and therefore blocking the mouse events on these parts. We’ll be using a pseudo-element for this to avoid adding additional empty tags to our markup.

当您将鼠标悬停在图像中显示的红色区域(即锚标记的下部)上时,会触发锚的悬停状态,这是正常的情况,但是因为我们希望它看起来像是锚仅紫色区域,我们需要防止鼠标事件在锚点的下部触发。 为此,我们将使用“盖”,将其放置在导航容器的中心,该盖将是覆盖锚点下部的圆形,从而阻止这些部分上的鼠标事件。 为此,我们将使用伪元素,以避免在标记中添加其他空标签。

So, applying these three steps to our CSS, and changing the overall styles (colors and size) of the navigation and navigation items to look like the preview image above, we end up with the following CSS:

因此,将这三个步骤应用于我们CSS,并更改导航和导航项目的整体样式(颜色和大小),使其看起来像上面的预览图像,我们得到以下CSS:


.csstransforms .cn-wrapper {
  position: absolute;
  top: 100%;
  left: 50%;
  z-index: 10;
  margin-top: -13em;
  margin-left: -13.5em;
  width: 27em;
  height: 27em;
  border-radius: 50%;
  background: transparent;
  opacity: 0;
  transition: all .3s ease 0.3s;
  transform: scale(0.1);
  pointer-events: none;
  overflow: hidden; 
}

/*cover to prevent extra space of anchors from being clickable*/
.csstransforms .cn-wrapper:after{
  color: transparent;
  content:".";
  display:block;
  font-size:2em;
  width:6.2em;
  height:6.2em;
  position: absolute;
  left: 50%;
  margin-left: -3.1em;
  top:50%;
  margin-top: -3.1em;
  border-radius: 50%;
  z-index:10;
}

.csstransforms .cn-wrapper li {
  position: absolute;
  top: 50%;
  left: 50%;
  overflow: hidden;
  margin-top: -1.3em;
  margin-left: -10em;
  width: 10em;
  height: 10em;
  font-size: 1.5em;
  transition: all .3s ease;
  transform: rotate(76deg) skew(60deg);
  transform-origin: 100% 100%;
  pointer-events: none;
}

.csstransforms .cn-wrapper li a {
  position: absolute;
  position: fixed; /* fix the "displacement" bug in webkit browsers when using tab key */
  right: -7.25em;
  bottom: -7.25em;
  display: block;
  width: 14.5em;
  height: 14.5em;
  border-radius: 50%;
  background: #429a67;
  background: radial-gradient(transparent 35%, #429a67 35%);
  color: #fff;
  text-align: center;
  text-decoration: none;
  font-size: 1.2em;
  line-height: 2;
  transition: all .3s ease;
  transform: skew(-60deg) rotate(-75deg) scale(1);
  pointer-events: auto;
}

.csstransforms .cn-wrapper li a span {
  position: relative;
  top: 1.8em;
  display: block;
  font-size: .5em;
  font-weight: 700;
  text-transform: uppercase;
}

.csstransforms .cn-wrapper li a:hover,
.csstransforms .cn-wrapper li a:active,
.csstransforms .cn-wrapper li a:focus {
	background: radial-gradient(transparent 35%, #449e6a 35%);
}

We want the navigation items in the second demo to spread out in a fan-like effect when the navigation is opened. To achieve this effect, we have positioning the items in the same place and with the same rotation/skew of rotate(76deg) skew(60deg).

我们希望第二个演示中的导航项在打开导航时以扇形效果散开。 为了达到此效果,我们将物品放置在相同的位置,并且rotate(76deg) skew(60deg)相同。

Using transition delays we allow the items to spread out after we scale the wrapper up. When the navigation gets closed, we’ll wait for the items to move back in, before we scale the wrapper down again.

使用过渡延迟,我们可以在扩大包装后使物品散开。 导航关闭后,我们将等待项目移回,然后再次缩小包装。

When the open button is clicked we’re going to spread the items out by rotating each of them to their final position on the circle.

单击打开按钮后,我们将通过将每个项目旋转到圆上的最终位置来展开它们。


.csstransforms .opened-nav {
  border-radius: 50%;
  opacity: 1;
  transition: all .3s ease;
  transform: scale(1);
  pointer-events: auto;
}

.csstransforms .opened-nav li {
  transition: all .3s ease .3s;
}

.csstransforms .opened-nav li:first-child {
  transform: rotate(-20deg) skew(60deg);
}

.csstransforms .opened-nav li:nth-child(2) {
  transform: rotate(12deg) skew(60deg);
}

.csstransforms .opened-nav  li:nth-child(3) {
  transform: rotate(44deg) skew(60deg);
}

.csstransforms .opened-nav li:nth-child(4) {
  transform: rotate(76deg) skew(60deg);
}

.csstransforms .opened-nav li:nth-child(5) {
  transform: rotate(108deg) skew(60deg);
}

.csstransforms .opened-nav li:nth-child(6) {
  transform: rotate(140deg) skew(60deg);
}

.csstransforms .opened-nav li:nth-child(7) {
  transform: rotate(172deg) skew(60deg);
}

Of course, we’ll also provide a basic fallback for non-supporting browsers.

当然,我们还将为不支持的浏览器提供基本的备用功能。


.no-csstransforms .cn-wrapper{
  margin:10em auto;
  overflow:hidden;
  text-align:center;
  padding:1em;
}
.no-csstransforms .cn-wrapper ul{
  display:inline-block;
}
.no-csstransforms li{
  font-size:1em;
  width:5em;
  height:5em;
  float:left;
  line-height:5em;
  text-align:center;
  background-color: #fff;
}
.no-csstransforms li a{
  display:block;
  height:100%;
  width:100%;
  text-decoration: none;
  color: inherit;
}
.no-csstransforms .cn-wrapper li a:hover,
.no-csstransforms .cn-wrapper li a:active,
.no-csstransforms .cn-wrapper li a:focus{
  background-color: #f8f8f8;
}
.no-csstransforms .cn-wrapper li.active a {
  background-color: #6F325C;
  color: #fff;
}
.no-csstransforms .cn-button{
  display:none;
}

And the navigation is also going to be responsive, so we’ll shrink it on smaller screens. Here are the responsive styles for both circular and simple styles.

导航也将响应,因此我们将其缩小到较小的屏幕上。 这是圆形和简单样式的响应样式。

@media only screen and (max-width: 620px) {
  .no-csstransforms li{
    width:4em;
    height:4em;
    line-height:4em;
  }
}
@media only screen and (max-width: 500px) {
  .no-ccstransforms .cn-wrapper{
    padding:.5em;
  }
  .no-csstransforms .cn-wrapper li{
    font-size:.9em;
    width:4em;
    height:4em;
    line-height:4em;
  }
}
@media only screen and (max-width: 480px) {
  .csstransforms .cn-wrapper{
    font-size: .68em;
  }
  .cn-button{
    font-size:1em;
  }
}
@media only screen and (max-width:420px){
  .no-csstransforms .cn-wrapper li{
    width:100%;
    height:3em;
    line-height:3em;
  }
}

And that’s pretty much all the CSS you need to create these styles!

这就是创建这些样式所需的几乎所有CSS!

JavaScript (The JavaScript)

We won’t be using any JavaScript framework for these demos. I will be using David De Sandro’s Classie.js to add and remove classes. And finally for browsers that don’t support the addEventListener and removeEventListener we’ll use Jonathan Neal’s EventListener polyfill.

这些演示将不会使用任何JavaScript框架。 我将使用David De Sandro的Classie.js添加和删​​除类。 最后,对于不支持addEventListenerremoveEventListener浏览器,我们将使用Jonathan Neal的EventListener polyfill

We’ll add an event handler to the button in each of the two demos. Clicking the button and/or focusing it will trigger opening/closing of the navigation. Also, for the first demo, clicking anywhere outside the navigation when it’s open will also close it. Let’s start with the JavaScript for the first demo.

我们将在两个演示中的每个演示中向按钮添加事件处理程序。 单击按钮和/或将其聚焦将触发导航的打开/关闭。 另外,对于第一个演示,在打开导航栏之外的任何位置时也会将其关闭。 让我们从第一个演示JavaScript开始。


(function(){

  var button = document.getElementById('cn-button'),
    wrapper = document.getElementById('cn-wrapper'),
    overlay = document.getElementById('cn-overlay');

  //open and close menu when the button is clicked
  var open = false;
  button.addEventListener('click', handler, false);
  button.addEventListener('focus', handler, false);
  wrapper.addEventListener('click', cnhandle, false);

  function cnhandle(e){
    e.stopPropagation();
  }

  function handler(e){
    if (!e) var e = window.event;
    e.stopPropagation();//so that it doesn't trigger click event on document

      if(!open){
        openNav();
      }
    else{
        closeNav();
      }
  }
  function openNav(){
    open = true;
      button.innerHTML = "-";
      classie.add(overlay, 'on-overlay');
      classie.add(wrapper, 'opened-nav');
  }
  function closeNav(){
    open = false;
    button.innerHTML = "+";
    classie.remove(overlay, 'on-overlay');
    classie.remove(wrapper, 'opened-nav');
  }
  document.addEventListener('click', closeNav);

})();

The JavaScript for the second demo is similar to the previous one, except that we customize it for this case:

第二个演示JavaScript与上一个演示JavaScript类似,不同之处在于我们针对这种情况对其进行了自定义:


(function(){

  var button = document.getElementById('cn-button'),
    wrapper = document.getElementById('cn-wrapper');

    //open and close menu when the button is clicked
  var open = false;
  button.addEventListener('click', handler, false);
  button.addEventListener('focus', handler, false);

  function handler(){
    if(!open){
      this.innerHTML = "Close";
      classie.add(wrapper, 'opened-nav');
    }
    else{
      this.innerHTML = "Menu";
    classie.remove(wrapper, 'opened-nav');
    }
    open = !open;
  }
  function closeWrapper(){
    classie.remove(wrapper, 'opened-nav');
  }

})();


And that’s pretty much it! I hope you liked this tutorial and found it useful!

就是这样! 我希望您喜欢本教程并发现它很有用!

Update: The demo has been updated based on a few of the reported bugs in the comments section below. The menu should now be fully functional in Chrome/Webkit.

更新:演示已根据下面的评论部分中报告的一些错误进行了更新。 该菜单现在应该在Chrome / Webkit中可以正常使用。

翻译自: https://tympanus.net/codrops/2013/08/09/building-a-circular-navigation-with-css-transforms/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值