Giải pháp năm 2020
Đây là một giải pháp hiện đại hơn mà tôi sử dụng ngày nay.
Tôi bắt đầu bằng cách tạo HTML bắt đầu từ một mảng hình ảnh. Cho dù HTML được tạo bằng PHP, JS, một số bộ tiền xử lý HTML nào đó ... thì điều này ít quan trọng hơn vì ý tưởng cơ bản đằng sau là như nhau.
Đây là mã Pug sẽ làm điều này:
//- 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 được tạo trông như sau (và vâng, bạn cũng có thể viết HTML theo cách thủ công, nhưng sẽ rất khó để thực hiện các thay đổi sau đó):
<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>
Trong CSS, chúng tôi quyết định kích thước cho hình ảnh 8em
. Các --m
mục được đặt trên một vòng tròn và nếu chúng nằm ở giữa các cạnh của đa giác các --m
cạnh, tất cả đều tiếp tuyến với hình tròn.
Nếu bạn gặp khó khăn trong việc hình dung điều đó, bạn có thể chơi với bản trình diễn tương tác này để tạo hình tròn và đường tròn ngoại tiếp cho các đa giác khác nhau có số cạnh bạn chọn bằng cách kéo thanh trượt.
Điều này cho chúng ta biết rằng kích thước của vùng chứa phải gấp đôi bán kính của hình tròn cộng với hai lần một nửa kích thước của hình ảnh.
Chúng tôi chưa biết bán kính, nhưng chúng tôi có thể tính toán nó nếu chúng tôi biết số cạnh (và do đó tiếp tuyến của một nửa góc cơ sở, được tính toán trước và đặt làm thuộc tính tùy chỉnh --tan
) và cạnh đa giác. Chúng ta có thể muốn cạnh đa giác có kích thước nhỏ nhất của hình ảnh, nhưng chúng ta để lại bao nhiêu cạnh là tùy ý. Giả sử chúng ta có một nửa kích thước hình ảnh mỗi bên, vì vậy cạnh đa giác gấp đôi kích thước hình ảnh. Điều này cung cấp cho chúng tôi CSS sau:
.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% }
Xem giải pháp cũ để biết giải thích về cách hoạt động của chuỗi biến đổi.
Bằng cách này, việc thêm hoặc xóa hình ảnh khỏi mảng hình ảnh sẽ tự động sắp xếp số lượng hình ảnh mới trên một vòng tròn sao cho chúng cách đều nhau và cũng điều chỉnh kích thước của vùng chứa. Bạn có thể kiểm tra điều này trong bản demo này .
Giải pháp CŨ (được bảo tồn vì lý do lịch sử)
Có, rất có thể và rất đơn giản chỉ bằng cách sử dụng CSS. Bạn chỉ cần ghi nhớ rõ ràng các góc mà bạn muốn liên kết với các hình ảnh (Tôi đã thêm một đoạn mã ở cuối chỉ để hiển thị các góc bất cứ khi nào bạn di chuột qua một trong số chúng).
Trước tiên, bạn cần một trình bao bọc. Tôi đặt đường kính của nó là 24em
( width: 24em; height: 24em;
không), bạn có thể đặt nó thành bất cứ thứ gì bạn muốn. Bạn cho nó position: relative;
.
Sau đó, bạn đặt các liên kết của mình với các hình ảnh ở trung tâm của trình bao bọc đó, theo cả chiều ngang và chiều dọc. Bạn làm điều đó bằng cách thiết lập position: absolute;
và sau đó top: 50%; left: 50%;
và margin: -2em;
( 2em
bằng một nửa chiều rộng của liên kết với hình ảnh, mà tôi đã đặt là 4em
- một lần nữa, bạn có thể thay đổi nó thành bất cứ điều gì bạn muốn, nhưng đừng quên thay đổi lề trong trường hợp).
Sau đó bạn quyết định về các góc độ mà bạn muốn có liên kết của bạn với những hình ảnh và bạn thêm một lớp deg{desired_angle}
(ví dụ deg0
hoặc deg45
hoặc bất kỳ). Sau đó, đối với mỗi lớp như vậy, bạn áp dụng các biến đổi CSS theo chuỗi, như sau:
.deg{desired_angle} {
transform: rotate({desired_angle}) translate(12em) rotate(-{desired_angle});
}
nơi bạn thay thế {desired_angle}
bằng 0
, 45
v.v.
Phép biến đổi xoay thứ nhất làm quay đối tượng và các trục của nó, phép biến đổi tịnh tiến sẽ dịch đối tượng dọc theo trục X được quay và phép biến đổi xoay thứ hai đưa đối tượng trở lại vị trí.
Ưu điểm của phương pháp này là nó linh hoạt. Bạn có thể thêm hình ảnh mới ở các góc khác nhau mà không làm thay đổi cấu trúc hiện tại.
MÃ SỐ MÃ
.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>
Ngoài ra, bạn có thể đơn giản hóa HTML hơn nữa bằng cách sử dụng hình nền cho các liên kết thay vì sử dụng img
thẻ.
CHỈNH SỬA : ví dụ với dự phòng cho IE8 trở lên (được thử nghiệm trong IE8 và IE7)