सर्कल में स्थिति आइकन


96

मैं कैसे स्थिति कर सकता हूँ <img> तत्वों को एक दूसरे के चारों ओर एक सर्कल में और उन तत्वों को क्लिक करने योग्य लिंक भी हो सकता है? मैं चाहता हूं कि यह नीचे दी गई तस्वीर की तरह दिखे, लेकिन मुझे नहीं पता कि उस प्रभाव को कैसे प्राप्त किया जाए।

वांछित परिणाम

क्या यह भी संभव है?

जवाबों:


194

2020 समाधान

यहां एक और आधुनिक समाधान है जो मैं इन दिनों उपयोग करता हूं।

मैं छवियों की एक सरणी से शुरू होने वाले HTML को उत्पन्न करके बंद करता हूं। चाहे HTML PHP, JS, कुछ HTML प्रीप्रोसेसर का उपयोग करके उत्पन्न होता है, जो भी ... यह कम महत्वपूर्ण है क्योंकि मूल विचार के पीछे एक ही है।

यहाँ पग कोड है कि यह करना होगा:

//- start with an array of images, described by url and alt text
- let imgs = [
-   {
-       src: 'image_url.jpg', 
-       alt: 'image alt text'
-   } /* and so on, add more images here */
- ];
- let n_imgs = imgs.length;
- let has_mid = 1; /* 0 if there's no item in the middle, 1 otherwise */
- let m = n_imgs - has_mid; /* how many are ON the circle */
- let tan = Math.tan(Math.PI/m); /* tangent of half the base angle */

.container(style=`--m: ${m}; --tan: ${+tan.toFixed(2)}`)
    - for(let i = 0; i < n_imgs; i++)
        a(href='#' style=i - has_mid >= 0 ? `--i: ${i}` : null)
          img(src=imgs[i].src alt=imgs[i].alt)

उत्पन्न HTML इस प्रकार दिखता है (और हाँ, आप HTML को मैन्युअल रूप से भी लिख सकते हैं, लेकिन बाद में बदलाव करने के लिए यह एक दर्द होने वाला है):

<div class="container" style="--m: 8; --tan: 0.41">
  <a href='#'>
    <img src="image_mid.jpg" alt="alt text"/>
  </a>
  <a style="--i: 1">
    <img src="first_img_on_circle.jpg" alt="alt text"/>
  </a>
  <!-- the rest of those placed on the circle -->
</div>

CSS में, हम छवियों के लिए एक आकार तय करते हैं, आइए बताते हैं 8em--mआइटम एक चक्र पर स्थान दिया जाता है और यदि वे की एक बहुभुज के किनारों के बीच में कर रहे हैं यह है --mकिनारों, जो सभी के चक्र को स्पर्श कर रहे हैं।

यदि आपके पास एक कठिन समय है, तो आप इस इंटरेक्टिव डेमो के साथ खेल सकते हैं, जो विभिन्न पॉलीगनों के लिए अंतर्वृत्त और परिधि का निर्माण करता है, जिनकी संख्या आप स्लाइडर को खींचकर उठाते हैं।

एक षट्भुज का घेरा और खतना

यह हमें बताता है कि कंटेनर का आकार सर्कल के त्रिज्या से दोगुना होना चाहिए और छवियों का आधा आधा गुना होना चाहिए।

हम अभी तक त्रिज्या को नहीं जानते हैं, लेकिन यदि हम किनारों की संख्या (और इसलिए आधा आधार कोण की स्पर्शरेखा, पूर्वनिर्धारित और एक कस्टम गुण के रूप में सेट --tan) और बहुभुज किनारे जानते हैं तो हम इसकी गणना कर सकते हैं । हम शायद बहुभुज किनारे को कम से कम छवियों के आकार के रूप में चाहते हैं, लेकिन हम पक्षों पर कितना छोड़ते हैं वह मनमाना है। मान लें कि हमारे पास प्रत्येक तरफ आधा छवि आकार है, इसलिए बहुभुज किनारे छवि का आकार दोगुना है। यह हमें निम्नलिखित सीएसएस देता है:

.container {
  --d: 6.5em; /* image size */
  --rel: 1; /* how much extra space we want between images, 1 = one image size */
  --r: calc(.5*(1 + var(--rel))*var(--d)/var(--tan)); /* circle radius */
  --s: calc(2*var(--r) + var(--d)); /* container size */
  position: relative;
  width: var(--s); height: var(--s);
  background: silver /* to show images perfectly fit in container */
}

.container a {
  position: absolute;
  top: 50%; left: 50%;
  margin: calc(-.5*var(--d));
  width: var(--d); height: var(--d);
  --az: calc(var(--i)*1turn/var(--m));
  transform: 
    rotate(var(--az)) 
    translate(var(--r))
    rotate(calc(-1*var(--az)))
}

img { max-width: 100% }

परिवर्तन श्रृंखला कैसे काम करती है, इसकी व्याख्या के लिए पुराना समाधान देखें।

इस तरह, छवियों के सरणी से एक छवि को जोड़ना या निकालना स्वचालित रूप से एक सर्कल पर छवियों की नई संख्या को व्यवस्थित करता है, जैसे कि वे समान रूप से बाहर होते हैं और कंटेनर के आकार को भी समायोजित करते हैं। आप इस डेमो में इसका परीक्षण कर सकते हैं ।


OLD समाधान (ऐतिहासिक कारणों से संरक्षित)

हाँ, यह बहुत ही संभव है और बहुत सरल बस CSS का उपयोग कर रहा है। आपको केवल उन कोणों को ध्यान में रखना होगा, जिन पर आप चित्रों के साथ लिंक चाहते हैं (मैंने कोणों को दिखाने के लिए अंत में कोड का एक टुकड़ा जोड़ा है जब भी आप उनमें से किसी एक को हॉवर करते हैं)।

आपको सबसे पहले एक रैपर चाहिए। मैंने इसका व्यास 24em( width: 24em; height: 24em;ऐसा करता है) होने के लिए सेट किया है , आप इसे अपनी इच्छानुसार सेट कर सकते हैं। आप दे दो position: relative;

फिर आप अपने लिंक को उस रैपर के केंद्र में क्षैतिज और लंबवत दोनों तरह से लगाते हैं। आप सेटिंग करके position: absolute;और फिर top: 50%; left: 50%;और margin: -2em;(जहां 2emछवि के साथ लिंक की आधी चौड़ाई है, जिसे मैंने सेट किया है4em - फिर से, आप इसे अपनी इच्छानुसार बदल सकते हैं, लेकिन इसमें मार्जिन बदलना न भूलें उस मामले में)।

इसके बाद आप कोण जिस पर आप छवियों के साथ अपने लिंक करना चाहते हैं पर फैसला है और आप एक वर्ग को जोड़ने deg{desired_angle}(उदाहरण के लिए deg0या deg45या जो कुछ भी)। फिर इस तरह के प्रत्येक वर्ग के लिए आप जंजीर सीएसएस रूपांतर लागू करते हैं, जैसे:

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

जहां की जगह {desired_angle}के साथ 0, 45, और इतने पर ...

पहला रोटेट ट्रांसफ़ॉर्म ऑब्जेक्ट और उसके एक्सिस को घुमाता है, ट्रांसलेट ट्रांसफ़ॉर्म ऑब्जेक्ट को रोटेटेड एक्स एक्सिस के साथ ट्रांसलेट करता है और दूसरा रोटेट ट्रांसफ़ॉर्म ऑब्जेक्ट को स्थिति में वापस लाता है।

इस पद्धति का लाभ यह है कि यह लचीला है। आप वर्तमान संरचना को बदलने के बिना विभिन्न कोणों पर नई छवियां जोड़ सकते हैं।

सांकेतिक टुकड़ा

    .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>

इसके अलावा, आप imgटैग का उपयोग करने के बजाय लिंक के लिए पृष्ठभूमि छवियों का उपयोग करके HTML को और सरल बना सकते हैं ।


संपादित करें : IE8 और पुराने (IE8 और IE7 में परीक्षण) के लिए कमबैक के साथ उदाहरण


1
अच्छा है, लेकिन बिना CSS CSS सपोर्ट वाले डिवाइस / ब्राउज़र से एक्सेस करने पर लोग क्या देखेंगे?
14

1
केवल डेस्कटॉप ब्राउजर जो CSS ट्रांसफॉर्म का समर्थन नहीं करते हैं वे IE8 और पुराने हैं। उन लोगों के लिए, यह IE मैट्रिक्स फ़िल्टर ट्रांसफ़ॉर्म का उपयोग करके अनुकरण किया जा सकता है। जैसा कि मोबाइल ब्राउज़रों के लिए, ओपेरा मिनी सीएसएस ट्रांसफॉर्म का समर्थन नहीं करने वाला एकमात्र है और मैं वास्तव में ऐसी किसी चीज का उपयोग नहीं करूंगा जो कि छोटे परदे पर वैसे भी बर्बाद हो रही है।
एना

1
जब मैंने डेमो देखा तो मैंने नीचे स्क्रॉल किया क्योंकि मुझे पता था कि यह आप ही होंगे जो इस तरह के प्रश्न का उत्तर देंगे। अच्छा हुआ @Ana। आप कहां ब्लॉग करते हैं?
अहमद अल्फी

6
@ बहुत बढ़िया है, यदि आपकी सीएसएस ने n आइटम के लिए एक सामान्य उदाहरण बनाने के लिए उपयोग किया है, यदि रुचि हो। jsfiddle.net/sajjansarkar/zgcgq8cg
सज्जन सरकार

3
@ बहुत अच्छा! आपने मुझे एक गतिशील संस्करण बनाने के लिए प्रेरित किया - jsfiddle.net/skwidbreth/q59s90oy
skwidbreth

18

यहाँ पूर्ण स्थिति के बिना आसान समाधान है:

.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/


10

@ एना के उत्कृष्ट उत्तर का निर्माण करते हुए, मैंने यह डायनामिक संस्करण बनाया, जो आपको 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>


1
महान काम किया है, और अगर मैं कर सकता मैं अधिक upvote होगा। एक समस्या मुझे यह थी कि अगर मैं 360 को किसी और चीज़ में बदल दूं (मुझे एक आधा-चक्र चाहिए), तो चीजें बेकार हो गईं। मैंने इसे घूर्णन कोण की घोषणा के var rotateAngle = zero_start + (offsetAngle * i || 0);लिए ट्रेस किया और इसे इसमें बदल दिया मैंने शून्य_स्टार्ट के लिए एक चर भी जोड़ा, इसलिए यदि आप 0 के बजाय बिंदु 270 पर शुरू करना चाहते हैं, या कुछ इसी तरह। jsfiddle.net/q59s90oy/13 । अंत में मैंने नकारात्मक मार्जिन का उपयोग करने के लिए सूची आइटम के लिए सीएसएस बदल दिया। हालांकि, काम को साझा करने के लिए धन्यवाद, बहुत मदद की।
नियमित जो

यह मूल है, खुशी है कि आप इसे आवश्यकतानुसार ट्विक करने में सक्षम थे। अच्छा बदलाव!
skwidbreth

1
यो यह एक बहुत महाकाव्य सर्पिल प्रभाव 😅 है i.imgur.com/1VrubKC.png
एतान

@ ईथन हा हा हाँ! मुझे ऐसा करना बहुत पसंद है! मुझे लगा कि यह एक अच्छी कला कृति बना सकता है।
स्कीविद्रेथ

5

सीएसएस के साथ किसी अन्य तत्व के चारों ओर क्लिक करने योग्य वस्तुओं को जादुई तरीके से रखने का कोई तरीका नहीं है। जिस तरह से मैं यह करूँगा के साथ एक कंटेनर का उपयोग करके है position:relative;। और फिर सभी तत्वों के साथ position:absolute;और उपयोग topऔरleft करने के लिए इसे लक्षित करने के लिए रखें।

हालांकि आपने नहीं रखा है आपके टैग में इसके लिए jQuery / जावास्क्रिप्ट का उपयोग करना सबसे अच्छा हो सकता है।

पहला चरण कंटेनर के केंद्र में आपकी केंद्र छवि का पूरी तरह से उपयोग कर रहा है position:relative;

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

उसके बाद आप offset()कन्टेनर के सेंटरइमेज माइनस का उपयोग करके इसके आसपास अन्य तत्वों को रख सकते हैं offset()। आपको सटीक topऔर leftछवि दे रहा है।

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 
});

क्या मैं यहाँ किया है तत्वों रखने है रिश्तेदार centerImage करने के लिए। उम्मीद है की यह मदद करेगा।


5

आप निश्चित रूप से इसे शुद्ध सीएसएस के साथ कर सकते हैं या जावास्क्रिप्ट का उपयोग कर सकते हैं। मेरा सुझाव:

  • यदि आप पहले से ही जानते हैं कि छवियों की संख्या कभी भी आपकी शैलियों की गणना नहीं करेगी और सादे सीएसएस के साथ जाएगी (पेशेवरों: बेहतर प्रदर्शन, बहुत विश्वसनीय)

  • यदि संख्या आपके ऐप में या तो गतिशील रूप से भिन्न हो सकती है या भविष्य में जेएस समाधान के साथ भिन्न हो सकती है (पेशेवरों: अधिक भविष्य के सबूत)

मेरे पास करने के लिए एक समान काम था, इसलिए मैंने एक स्क्रिप्ट बनाई और इसे जीथब पर यहां किसी के लिए भी खोल दिया, जिसे इसकी आवश्यकता हो सकती है। यह सिर्फ कुछ कॉन्फ़िगरेशन मूल्यों को स्वीकार करता है और बस आपको आवश्यक सीएसएस कोड को आउटपुट करता है।

यदि आप जेएस समाधान के लिए यहां जाना चाहते हैं तो एक सरल सूचक है जो आपके लिए उपयोगी हो सकता है। इस html का उपयोग #boxकंटेनर और .dotबीच में इमेज / डिव के रूप में किया जा रहा है , जिसे आप चाहते हैं कि आपकी सभी अन्य छवियां आसपास हैं:

Html शुरू करना:

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

सीएसएस शुरू करना:

 #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;
}

आप इन पंक्तियों के साथ एक त्वरित कार्य बना सकते हैं:

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;
}

आप यहां एक जीवंत उदाहरण देख सकते हैं


4

@Ana द्वारा प्रस्तावित समाधान का उपयोग करना:

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

मैंने निम्नलिखित jsFiddle को बनाया है, जो सादे जावास्क्रिप्ट (jQuery संस्करण भी उपलब्ध है) का उपयोग करके मंडलियों को गतिशील रूप से रखता है।

जिस तरह से यह काम करता है बल्कि सरल है:

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>


2

यहाँ एक ऐसा संस्करण है जिसे मैंने यहाँ के उदाहरणों से प्रतिक्रिया में बनाया है।

CodeSandbox उदाहरण

import React, { useRef, useEffect } from "react";

import "./styles.css";

export default function App() {
  const graph = useRef(null);

  useEffect(() => {
    const ciclegraph = graph.current;
    const circleElements = ciclegraph.childNodes;

    let angle = 360 - 90;
    let dangle = 360 / circleElements.length;

    for (let i = 0; i < circleElements.length; i++) {
      let circle = circleElements[i];
      angle += dangle;
      circle.style.transform = `rotate(${angle}deg) translate(${ciclegraph.clientWidth /
        2}px) rotate(-${angle}deg)`;
    }
  }, []);

  return (
    <div className="App">
      <div className="ciclegraph" ref={graph}>
        <div className="circle" />
        <div className="circle" />
        <div className="circle" />
        <div className="circle" />
        <div className="circle" />
        <div className="circle" />
      </div>
    </div>
  );
}

महान जवाब और कोड का महान टुकड़ा, केवल मुद्दा यह है कि आपने इसे एक जवाब पर पोस्ट किया है जिसका रिएक्ट से कोई लेना-देना नहीं है!
अनब्रांडेड मैनचेस्टर

मुझे पता है, एक उत्तर किसी ने नहीं मांगा, लेकिन यहाँ वैसे भी है :)
br3ntor

मैं यहां एक समाधान की तलाश में आया था जिसे मैं रिएक्ट में उपयोग कर सकता हूं इसलिए अभी भी बहुत उपयोगी है
अभिषेक कासर्ड्डी

1

आप इसे इस तरह से कर सकते हैं: बेला

स्थिति का बुरा मत मानना, इसका एक त्वरित उदाहरण है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.