
在现代网页设计中,为圆形用户头像或产品图片添加星级评分是常见的需求。然而,将评分星星以圆形路径环绕在图片周围,而非简单地堆叠在下方,需要一些巧妙的css和javascript技巧。本教程将深入探讨两种实现此效果的专业方法。
这种方法结合了CSS的强大转换能力和JavaScript的灵活性,通过计算每个星形图标的旋转角度和位移,将其精确地放置在圆形路径上。
首先,我们需要一个包含头像图片和未来星级评分的容器。为了使用Font Awesome图标,请确保引入其CSS库。
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" /> <div class="photo-container"> <img style="width: 100%;" src="https://i.ibb.co/bmfXcFw/avatar.png" alt="Profile Avatar" /> </div>
定义容器的基本样式,使其成为一个圆形,并为评分图标提供占位符。
.photo-container {
position: relative; /* 关键:用于绝对定位子元素 */
display: flex;
align-items: center;
justify-content: center;
width: 200px;
height: 200px;
border-radius: 50%; /* 使容器成为圆形 */
overflow: hidden; /* 隐藏超出容器的图片部分 */
margin: 20px; /* 示例间距 */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 添加阴影 */
}
.rating-container {
position: absolute;
inset: 0; /* 使评分容器覆盖整个父容器 */
}
.rating-container .icons-holder {
position: relative;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.icons-holder > div {
cursor: pointer;
}
.icons-holder > div .icon {
color: orange; /* 星星颜色 */
}
.icons-holder > div .icon:hover {
color: darkgoldenrod; /* 悬停效果 */
}JavaScript负责计算和生成星形图标,并应用CSS transform。
立即学习“Java免费学习笔记(深入)”;
// 图标数量
const count = 5;
// 图标大小 (px)
const size = 18;
// 图标间距 (px)
const margin = 4;
// 整体旋转角度 (度) - 0度表示从右侧开始
const position = 0; // 例如:55度用于底部,120度用于左侧,240度用于顶部,330度用于右侧
// 获取所有图片容器
const photoContainers = document.querySelectorAll(".photo-container");
photoContainers.forEach((container) => {
// 获取容器半径
const r = container.offsetHeight / 2;
// 计算图标的偏移量,用于调整translateX的精确值
const offset = (size / Math.PI) * -1;
const ratingContainer = document.createElement("div");
ratingContainer.className = "rating-container";
const iconsHolder = document.createElement("div");
iconsHolder.className = "icons-holder";
const posAngles = [];
for (let i = 0; i < count; i++) {
// 计算每个图标的旋转角度
posAngles.push(i * (size + offset + margin));
const div = document.createElement("div");
div.style.position = "absolute";
div.style.display = "block";
div.style.height = `${size}px`;
div.style.width = `${size}px`;
// 应用旋转和位移,将图标放置在圆形路径上
div.style.transform = `rotate(${posAngles[i]}deg) translateX(${r - size + Math.abs(offset)}px)`;
const icon = document.createElement("span");
icon.className = "icon fa fa-star"; // Font Awesome 星星图标
icon.style.fontSize = `${size}px`;
// 对图标进行反向旋转,使其保持垂直
icon.style.transform = `rotate(${posAngles[i] * -1}deg)`;
div.append(icon);
iconsHolder.append(div);
}
// 应用整体旋转,调整所有图标的起始位置
iconsHolder.style.transform = `rotate(${position}deg)`;
ratingContainer.append(iconsHolder);
container.append(ratingContainer);
});这种方法不依赖CSS transform 的 translateX,而是直接通过三角函数计算每个图标在圆周上的 x 和 y 坐标,然后使用 left 和 top 属性进行定位。这种方法通常更易于理解和控制每个图标的精确位置。
为了展示可配置性,我们创建多个头像容器。
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<div style="display: flex; flex-wrap: wrap; gap: 20px; justify-content: center; margin-top: 20px;">
<div class="avatar" style="width: 300px; height: 300px;">
<img src="https://i.pravatar.cc/300?random=1" style="height: 100%" alt="Avatar 1" />
</div>
<div class="avatar">
<img src="https://i.pravatar.cc/300?random=2" style="height: 100%" alt="Avatar 2" />
</div>
<div class="avatar">
<img src="https://i.pravatar.cc/300?random=3" style="height: 100%" alt="Avatar 3" />
</div>
<div class="avatar">
<img src="https://i.pravatar.cc/300?random=4" style="height: 100%" alt="Avatar 4" />
</div>
<div class="avatar">
<img src="https://i.pravatar.cc/300?random=5" style="height: 100%" alt="Avatar 5" />
</div>
<div class="avatar">
<img src="https://i.pravatar.cc/300?random=6" style="height: 100%" alt="Avatar 6" />
</div>
<div class="avatar">
<img src="https://i.pravatar.cc/300?random=7" style="height: 100%" alt="Avatar 7" />
</div>
<div class="avatar">
<img src="https://i.pravatar.cc/300?random=8" style="height: 100%" alt="Avatar 8" />
</div>
<div class="avatar">
<img src="https://i.pravatar.cc/300?random=9" style="height: 100%" alt="Avatar 9" />
</div>
</div>定义头像容器和评分图标的样式。
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh; /* 确保body至少占据视口高度 */
margin: 0;
background: radial-gradient(circle farthest-corner at 10% 20%, rgba(90, 92, 106, 1) 0%, rgba(32, 45, 58, 1) 81.3%);
font-family: sans-serif;
}
.avatar {
position: relative; /* 关键:用于绝对定位子元素 */
width: 200px;
height: 200px;
border-radius: 50%;
overflow: hidden;
background: #f0f0f0; /* 默认背景色 */
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2);
}
.rating-icons {
color: orange;
cursor: pointer;
transition: all 0.3s ease; /* 添加过渡效果 */
}
.rating-icons:hover {
color: darkgoldenrod;
transform: scale(1.15) rotate(70deg); /* 悬停动画 */
}
/* 自定义颜色类 */
.red {
color: red;
}
.red:hover {
color: darkred;
}
.green {
color: green;
}
.green:hover {
color: yellowgreen;
}创建一个名为 ratingStars 的函数,它接受一个根元素和可选配置对象作为参数。
function ratingStars(root, options) {
// 获取元素的半径
const getRadius = (element) => {
if (element.offsetHeight === element.offsetWidth) return Math.round(element.offsetWidth / 2);
else {
console.error("The given element is not a perfect circle, positioning might be off.");
return Math.round(element.offsetWidth / 2); // 即使不是圆形也尝试返回一个半径
}
};
// 根据半径、角度计算x,y坐标
const pos = (r, theta) => {
return {
x: Math.round(r * Math.cos(theta * (Math.PI / 180))),
y: Math.round(r * Math.sin(theta * (Math.PI / 180))),
};
};
// 默认选项
let op = {
count: 6, // 星星数量
icons_class: "rating-icons", // 图标CSS类
rotate: 0, // 整体旋转角度 (度)
clock_wise: true, // 是否顺时针排列
size: 28, // 图标大小 (pt)
icons_margin: 3.8, // 图标间距 (px)
edge_margin: 0, // 距离边缘的额外间距 (px)
};
// 合并用户自定义选项
op = { ...op, ...options };
const radius = getRadius(root); // 获取根元素的半径
if (radius) {
// 创建主容器,用于包裹所有图标
const rating = document.createElement("div");
rating.style.position = "absolute";
// 将主容器移动到根元素的中心
rating.style.left = `${radius - op.size / 2}px`;
rating.style.top = `${radius - op.size / 2}px`;
root.append(rating);
// 根据图标数量和间距生成角度数组
let degs = [];
const angleIncrement = op.size / Math.PI + op.icons_margin;
for (let i = 0; i < op.count; i++) {
degs.push(Math.round(i * angleIncrement * (op.clock_wise ? 1 : -1)));
}
// 遍历角度数组,为每个图标创建并定位
degs.forEach((deg) => {
let iconHolder = document.createElement("div");
iconHolder.style.position = "absolute";
iconHolder.style.textAlign = "center";
// 计算图标的定位半径(从中心到图标中心的距离)
const currentRadius = radius - op.size / 2 - op.edge_margin;
// 使用pos函数计算x,y坐标,并加上整体旋转角度
const { x, y } = pos(currentRadius, deg + op.rotate);
iconHolder.style.left = `${x}px`;
iconHolder.style.top = `${y}px`;
// 插入Font Awesome星星图标
iconHolder.innerHTML = `<span style="font-size: ${op.size * 0.75}pt;" class="${op.icons_class} fa fa-star"></span>`;
rating.append(iconHolder);
});
}
}
// 获取所有头像元素
const avatars = document.querySelectorAll(".avatar");
// 应用不同的配置选项
ratingStars(avatars[0], { count: 5, rotate: 270, edge_margin: 10 }); // 默认配置,但星星在顶部
ratingStars(avatars[1], { icons_class: 'rating-icons red', count: 4, rotate: 100 }); // 红色星星,数量4,旋转100度
ratingStars(avatars[2], { rotate: 143, count: 7, edge_margin: 5 }); // 旋转143度,数量7
ratingStars(avatars[3], { clock_wise: false, count: 6, icons_margin: 10 }); // 逆时针排列,间距更大
ratingStars(avatars[4], { size: 28, count: 5, rotate: 0 }); // 图标更大,从右侧开始
ratingStars(avatars[5], { icons_margin: 20, count: 3, rotate: 180 }); // 图标间距更大,星星在左侧
ratingStars(avatars[6], { edge_margin: 20, count: 8, rotate: 45 }); // 距离边缘更远
ratingStars(avatars[7], { // 综合示例
count: 4,
icons_class: 'rating-icons green',
rotate: 50,
clock_wise: true,
size: 30,
icons_margin: 40,
edge_margin: 15
});
ratingStars(avatars[8], { count: 15, size: 16, icons_margin: 2 }); // 大量小星星两种方法都能实现圆形头像周围的星级评分布局,但各有侧重:
方法一 (CSS transform + JavaScript):
方法二 (纯JavaScript + 三角函数):
在实际开发中,推荐使用方法二,因为它将布局逻辑封装在一个易于使用的函数中,提供了丰富的配置选项,使得组件更具通用性和可维护性。无论是哪种方法,都应确保引入Font Awesome等图标库,并根据实际设计需求调整图标大小、颜色和间距。
以上就是CSS与JavaScript实现圆形头像周围的星级评分布局的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号