Html 将图标定位成圆圈

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12813573/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 03:16:24  来源:igfitidea点击:

Position icons into circle

htmlcss

提问by FatalKeystroke

How can I position several <img>elements into a circle around another and have those elements all be clickable links as well? I want it to look like the picture below, but I have no idea how to achieve that effect.

如何将多个<img>元素围绕另一个元素放置在一个圆圈中,并使这些元素也都是可点击的链接?我希望它看起来像下图,但我不知道如何实现这种效果。

Desired Result

想要的结果

Is this even possible?

这甚至可能吗?

回答by Ana

Yes, it is very much possible and very simple using just CSS. You just need to have clear in mind the angles at which you want the links with the images (I've added a piece of code at the end just for showing the angles whenever you hover one of them).

是的,仅使用 CSS 就非常有可能且非常简单。你只需要清楚你想要与图像链接的角度(我在最后添加了一段代码,只是为了在你悬停其中一个时显示角度)。

demo

演示

You first need a wrapper. I set its diameter to be 24em(width: 24em; height: 24em;does that), you can set it to whatever you want. You give it position: relative;.

您首先需要一个包装器。我将其直径设置为24em(width: 24em; height: 24em;这样做),您可以将其设置为任何您想要的。你给它position: relative;

You then position your links with the images in the center of that wrapper, both horizontally and vertically. You do that by setting position: absolute;and then top: 50%; left: 50%;and margin: -2em;(where 2emis half the width of the link with the image, which I've set to be 4em- again, you can change it to whatever you wish, but don't forget to change the margin in that case).

然后,您将链接与图像放置在该包装器的中心,水平和垂直。您可以通过设置position: absolute;然后top: 50%; left: 50%;margin: -2em;(其中2em是图像链接宽度的一半,我已经设置为4em- 再次,您可以将其更改为您想要的任何内容,但不要忘记更改边距那种情况)。

You then decide on the angles at which you want to have your links with the images and you add a class deg{desired_angle}(for example deg0or deg45or whatever). Then for each such class you apply chained CSS transforms, like this:

然后,您决定在要与图像您的链接的角度和你添加一个类deg{desired_angle}(例如deg0deg45或其他)。然后对每个这样的类应用链式 CSS 转换,如下所示:

.deg{desired_angle} {
   transform: rotate({desired_angle}) translate(12em) rotate(-{desired_angle});
}

where you replace {desired_angle}with 0, 45, and so on...

{desired_angle}0,替换的地方45,等等......

The first rotate transform rotates the object and its axes, the translate transform translates the object along the rotated X axis and the second rotate transform brings back the object into position - demo to illustrate how this works.

第一个旋转变换旋转对象及其轴,平移变换沿旋转的 X 轴平移对象,第二个旋转变换将对象带回位置 -演示说明这是如何工作的

The advantage of this method is that it is flexible. You can add new images at different angles without altering the current structure.

这种方法的优点是灵活。您可以在不改变当前结构的情况下添加不同角度的新图像。

CODE SNIPPET

代码片段

    .circle-container {
     position: relative;
     width: 24em;
     height: 24em;
     padding: 2.8em;
        /*2.8em = 2em*1.4 (2em = half the width of a link with img, 1.4 = sqrt(2))*/
     border: dashed 1px;
     border-radius: 50%;
     margin: 1.75em auto 0;
    }
    .circle-container a {
     display: block;
     position: absolute;
     top: 50%; left: 50%;
     width: 4em; height: 4em;
     margin: -2em;
    }
    .circle-container img { display: block; width: 100%; }
    .deg0 { transform: translate(12em); } /* 12em = half the width of the wrapper */
    .deg45 { transform: rotate(45deg) translate(12em) rotate(-45deg); }
    .deg135 { transform: rotate(135deg) translate(12em) rotate(-135deg); }
    .deg180 { transform: translate(-12em); }
    .deg225 { transform: rotate(225deg) translate(12em) rotate(-225deg); }
    .deg315 { transform: rotate(315deg) translate(12em) rotate(-315deg); }
    <div class='circle-container'>
     <a href='#' class='center'><img src='image.jpg'></a>
     <a href='#' class='deg0'><img src='image.jpg'></a>
     <a href='#' class='deg45'><img src='image.jpg'></a>
     <a href='#' class='deg135'><img src='image.jpg'></a>
     <a href='#' class='deg180'><img src='image.jpg'></a>
     <a href='#' class='deg225'><img src='image.jpg'></a>
     <a href='#' class='deg315'><img src='image.jpg'></a>
    </div>

Also, you could further simplify the HTML by using background images for the links instead of using imgtags.

此外,您可以通过为链接使用背景图像而不是使用img标签来进一步简化 HTML 。



EDIT: example with fallback for IE8 and older(tested in IE8 and IE7)

编辑IE8 及更早版本的回退示例(在 IE8 和 IE7 中测试)

回答by gkond

Here is the easy solution without absolute positioning:

这是没有绝对定位的简单解决方案:

.container .row {
  margin: 20px;
  text-align: center;
}

.container .row img {
  margin: 0 20px;
}
<div class="container">
  <div class="row">
    <img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
    <img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
  </div>
  <div class="row">
    <img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
    <img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
    <img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
  </div>
  <div class="row">
    <img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
    <img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
  </div>
</div>

http://jsfiddle.net/mD6H6/

http://jsfiddle.net/mD6H6/

回答by skwidbreth

Building off @Ana's excellent answer, I created this dynamic version that allows you to add and remove elements from the DOM and maintain proportionate spacing between the elements - check out my fiddle: https://jsfiddle.net/skwidbreth/q59s90oy/

基于@Ana 的出色答案,我创建了这个动态版本,允许您从 DOM 中添加和删除元素并保持元素之间的比例间距 - 查看我的小提琴:https: //jsfiddle.net/skwidbreth/q59s90oy/

var list = $("#list");

var updateLayout = function(listItems) {
  for (var i = 0; i < listItems.length; i++) {
    var offsetAngle = 360 / listItems.length;
    var rotateAngle = offsetAngle * i;
    $(listItems[i]).css("transform", "rotate(" + rotateAngle + "deg) translate(0, -200px) rotate(-" + rotateAngle + "deg)")
  };
};

$(document).on("click", "#add-item", function() {
  var listItem = $("<li class='list-item'>Things go here<button class='remove-item'>Remove</button></li>");
  list.append(listItem);
  var listItems = $(".list-item");
  updateLayout(listItems);

});

$(document).on("click", ".remove-item", function() {
  $(this).parent().remove();
  var listItems = $(".list-item");
  updateLayout(listItems);
});
#list {
  background-color: blue;
  height: 400px;
  width: 400px;
  border-radius: 50%;
  position: relative;
}

.list-item {
  list-style: none;
  background-color: red;
  height: 50px;
  width: 50px;
  position: absolute;
  top: 50%;
  left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

<ul id="list"></ul>
<button id="add-item">Add item</button>

回答by Nobita

You can certainly do it with pure css or use JavaScript. My suggestion:

您当然可以使用纯 css 或使用 JavaScript 来完成。我的建议:

  • If you already know that the images number will never change just calculate your styles and go with plain css (pros: better performances, very reliable)

  • If the number can vary either dynamically in your app or just may vary in the future go with a Js solution (pros: more future-proof)

  • 如果您已经知道图像编号永远不会改变,只需计算您的样式并使用纯 css(优点:性能更好,非常可靠)

  • 如果数字可以在您的应用程序中动态变化,或者将来可能会发生变化,请使用 Js 解决方案(优点:更面向未来)

I had a similar job to do, so I created a script and open sourced it here on Githubfor anyone who might need it. It just accepts some configuration values and simply outputs the CSS code you need.

我有一个类似的工作要做,所以我创建了一个脚本并在 Github 上将其开源,供任何可能需要它的人使用。它只接受一些配置值并简单地输出您需要的 CSS 代码。

If you want to go for the Js solution here's a simple pointer that can be useful to you. Using this html as a starting point being #boxthe container and .dotthe image/div in the middle you want all your other images around:

如果您想使用 Js 解决方案,这里有一个对您有用的简单指针。使用此 html 作为起点作为#box容器和.dot中间的图像/div,您需要所有其他图像:

Starting html:

开始html:

<div id="box">
  <div class="dot"></div>
  <img src="my-img.jpg">
  <!-- all the other images you need-->
</div>

Starting Css:

开始CSS:

 #box{
  width: 400px;
  height: 400px;
  position: relative;
  border-radius: 100%;
  border: 1px solid teal;
}

.dot{
    position: absolute;
    border-radius: 100%;
    width: 40px;
    height: 40px;
    left: 50%;
    top: 50%;
    margin-left: -20px;
    margin-top: -20px;
    background: rebeccapurple;
}
img{
  width: 40px;
  height: 40px;
  position: absolute;
}

You can create a quick function along these lines:

您可以按照以下方式创建快速函数:

var circle = document.getElementById('box'),
    imgs = document.getElementsByTagName('img'),
    total = imgs.length,
    coords = {},
    diam, radius1, radius2, imgW;

// get circle diameter
// getBoundingClientRect outputs the actual px AFTER transform
//      using getComputedStyle does the job as we want
diam = parseInt( window.getComputedStyle(circle).getPropertyValue('width') ),
radius = diam/2,
imgW = imgs[0].getBoundingClientRect().width,
// get the dimensions of the inner circle we want the images to align to
radius2 = radius - imgW

var i,
    alpha = Math.PI / 2,
    len = imgs.length,
    corner = 2 * Math.PI / total;

// loop over the images and assign the correct css props
for ( i = 0 ; i < total; i++ ){

  imgs[i].style.left = parseInt( ( radius - imgW / 2 ) + ( radius2 * Math.cos( alpha ) ) ) + 'px'
  imgs[i].style.top =  parseInt( ( radius - imgW / 2 ) - ( radius2 * Math.sin( alpha ) ) ) + 'px'

  alpha = alpha - corner;
}

You can see a live example here

你可以在这里看到一个活生生的例子

回答by Sem

There is no way to magically place clickable items in a circle around another element with CSS. The way how I would do this is by using a container with position:relative;. And then place all the elements with position:absolute;and using topand leftto target it's place.

没有办法用 CSS 神奇地将可点击的项目放在另一个元素周围的圆圈中。我这样做的方法是使用带有position:relative;. 然后放置所有元素,position:absolute;使用topleft定位它的位置。

Even though you haven't placed jqueryin your tags it might be best to use jQuery / javascript for this.

即使您没有在标签中放置jquery,最好为此使用 jQuery/javascript。

First step is placing your center image perfectly in the center of the container using position:relative;.

第一步是使用 将您的中心图像完美地放置在容器的中心position:relative;

#centerImage {
  position:absolute;
  top:50%;
  left:50%;
  width:200px;
  height:200px;
  margin: -100px 0 0 -100px;
}

After that you can place the other elements around it by using an offset()of the centerImage minus the offset()of the container. Giving you the exact topand leftof the image.

之后,您可以使用offset()centerImage 的 减去offset()容器的将其他元素放在它周围。给你确切topleft图像。

var left = $('#centerImage').offset().left - $('#centerImage').parent().offset().left;
var top = $('#centerImage').offset().top - $('#centerImage').parent().offset().top;

$('#surroundingElement1').css({
  'left': left - 50,
  'top': top - 50 
});

$('#surroundingElement2').css({
  'left': left - 50,
  'top': top 
});

$('#surroundingElement3').css({
  'left': left - 50,
  'top': top + 50 
});

What I've done here is placing the elements relativeto the centerImage. Hope this helps.

我在这里所做的是对于 centerImage放置元素。希望这可以帮助。

回答by Itay Grudev

Using the solution proposed by @Ana:

使用@Ana 提出的解决方案:

transform: rotate(${angle}deg) translate(${radius}px) rotate(-${angle}deg)

I created the following jsFiddlethat places circles dynamically using plain JavaScript (jQuery version also available).

我创建了以下jsFiddle,它使用纯 JavaScript(也可用 jQuery 版本)动态放置圆圈。

The way it works is rather simple:

它的工作方式相当简单:

document.querySelectorAll( '.ciclegraph' ).forEach( ( ciclegraph )=>{
  let circles = ciclegraph.querySelectorAll( '.circle' )
  let angle = 360-90, dangle = 360 / circles.length
  for( let i = 0; i < circles.length; ++i ){
    let circle = circles[i]
    angle += dangle
    circle.style.transform = `rotate(${angle}deg) translate(${ciclegraph.clientWidth / 2}px) rotate(-${angle}deg)`
  }
})
.ciclegraph {
  position: relative;
  width: 500px;
  height: 500px;
  margin: calc(100px / 2 + 0px);
}

.ciclegraph:before {
  content: "";
  position: absolute;
  top: 0; left: 0;
  border: 2px solid teal;
  width: calc( 100% - 2px * 2);
  height: calc( 100% - 2px * 2 );
  border-radius: 50%;
}

.ciclegraph .circle {
  position: absolute;
  top: 50%; left: 50%;
  width: 100px;
  height: 100px;
  margin: calc( -100px / 2 );
  background: teal;
  border-radius: 50%;
}
<div class="ciclegraph">
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
</div>

回答by Mark

You could do it like this: fiddle

你可以这样做:小提琴

Don't mind the positioning, its a quick example

不要介意定位,这是一个简单的例子