0

0

CSS与JavaScript实现圆形头像周围的环形评分星级展示

花韻仙語

花韻仙語

发布时间:2025-09-14 12:00:05

|

825人浏览过

|

来源于php中文网

原创

CSS与JavaScript实现圆形头像周围的环形评分星级展示

本教程详细介绍了两种在圆形头像周围以环形方式展示星级评分的方法。第一种利用CSS transform属性结合JavaScript动态生成,通过旋转和平移实现精确布局;第二种则采用纯JavaScript结合三角函数计算每个星形图标的精确位置。两种方法均提供了示例代码,旨在帮助开发者创建美观且功能性的环绕式评分UI。

在现代web应用中,为用户头像或产品图片添加环形星级评分是一种常见的ui设计需求,它能直观地展示评分信息,同时保持界面的美观与紧凑。实现这种效果需要结合css布局技巧和javascript的动态计算能力。本文将深入探讨两种主要的实现策略:利用css transform属性和纯javascript结合三角函数。

方法一:利用CSS transform属性实现环形布局

这种方法的核心思想是利用CSS的 rotate() 和 translateX() 变换函数。首先,将所有星级图标放置在一个中心点,然后通过 translateX() 将它们沿一个轴线平移到圆形半径上的某一点,最后通过 rotate() 围绕中心点旋转,形成环形布局。为了确保星形图标本身不随其父容器旋转而倾斜,还需要对图标自身进行反向旋转。

1. HTML结构

首先,我们需要一个包含头像图片和评分容器的基础HTML结构。



@@##@@

photo-container 将作为整个评分组件的外部容器,它内部包含实际的头像图片。评分星级将通过JavaScript动态生成并添加到此容器中。

2. CSS样式

CSS主要用于设置容器的尺寸、圆形边框以及定位基础。

立即学习Java免费学习笔记(深入)”;

.photo-container {
  position: relative; /* 关键:为内部绝对定位元素提供参考 */
  display: flex;
  align-items: center;
  justify-content: center;
  width: 200px;
  height: 200px;
  border-radius: 50%; /* 使容器呈圆形 */
  overflow: hidden; /* 隐藏超出容器的部分 */
  margin: 20px; /* 示例间距 */
  background-color: #f0f0f0; /* 备用背景 */
}

.avatar-image {
  width: 100%;
  height: 100%;
  object-fit: cover; /* 确保图片填充容器 */
  border-radius: 50%; /* 确保图片也是圆形 */
}

.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; /* 悬停效果 */
}

3. JavaScript动态生成与定位

JavaScript负责计算每个星形图标的位置,并将其添加到DOM中。

// 图标数量
const count = 5;
// 图标大小(px)
const size = 18;
// 图标间距(px)
const margin = 4;
// 整体旋转角度(deg),用于调整星级环的起始位置
// 例如:底部居中约55度,左侧约120度,顶部约240度,右侧约330度
const initialRotation = 55; // 例如,让星级从底部开始

const photoContainers = document.querySelectorAll(".photo-container");

photoContainers.forEach((container) => {
  const radius = container.offsetHeight / 2; // 获取容器半径
  // 计算平移偏移量,确保星级图标边缘位于圆形路径上
  // 这里的 offset 经过微调,使图标更贴合圆形边缘
  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 angles = [];
  for (let i = 0; i < count; i++) {
    // 计算每个图标的旋转角度
    // (size + offset + margin) 决定了每个图标在圆周上的间隔
    angles.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`;

    // 关键:应用旋转和平移
    // rotate(${angles[i]}deg): 围绕中心旋转到指定角度
    // translateX(${radius - size + Math.abs(offset)}px): 沿X轴平移到距离中心指定半径的位置
    div.style.transform = `rotate(${angles[i]}deg) translateX(${radius - 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(${angles[i] * -1}deg)`;

    div.append(icon);
    iconsHolder.append(div);
  }

  // 应用整体旋转,调整星级环的起始位置
  iconsHolder.style.transform = `rotate(${initialRotation}deg)`;
  ratingContainer.append(iconsHolder);
  container.append(ratingContainer);
});

注意事项:

  • position: relative 在父容器上是必不可少的,以便内部的绝对定位元素能正确参照。
  • transform: translateX() 的值需要根据容器半径、图标大小和所需间距进行精确计算,以确保图标位于正确的环形路径上。
  • 图标的反向旋转 (rotate(${angles[i] * -1}deg)) 是为了抵消父容器的旋转,使图标保持其原始朝向。
  • initialRotation 变量可以方便地调整整个星级环的起始位置。

方法二:利用纯JavaScript和三角函数实现环形布局

这种方法更加灵活,通过计算每个星形图标在圆周上的精确 x, y 坐标来定位。它将布局逻辑封装在一个可复用的函数中,并提供了丰富的配置选项。

1. HTML结构

与方法一类似,我们只需要一个基础的头像容器。

Onu
Onu

将脚本转换为内部工具,不需要前端代码。

下载


@@##@@

这里将 photo-container 更名为 avatar-container 以区分示例。

2. CSS样式

CSS主要设置容器样式和星级图标的基本外观。

body {
  display: flex;
  flex-wrap: wrap; /* 允许换行 */
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  margin: 0;
  background: radial-gradient(circle farthest-corner at 10% 20%, rgba(90, 92, 106, 1) 0%, rgba(32, 45, 58, 1) 81.3%);
}

.avatar-container {
  position: relative;
  width: 200px; /* 默认尺寸 */
  height: 200px;
  border-radius: 50%;
  overflow: hidden;
  background: #ccc; /* 备用背景 */
  margin: 15px; /* 示例间距 */
}

.avatar-container img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}

.rating-icons {
  color: orange;
  cursor: pointer;
  transition: all 0.5s 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;
}

3. JavaScript函数封装与定位

此方法将所有逻辑封装在一个 ratingStars 函数中,提供丰富的配置选项。

/**
 * 在圆形元素周围生成环形星级评分。
 * @param {HTMLElement} root - 作为星级容器的圆形根元素。
 * @param {Object} [options] - 配置选项。
 * @param {number} [options.count=6] - 星级图标的数量。
 * @param {string} [options.icons_class="rating-icons"] - 星级图标的CSS类名。
 * @param {number} [options.rotate=0] - 整体旋转角度(度)。
 * @param {boolean} [options.clock_wise=true] - 是否顺时针排列。
 * @param {number} [options.size=20] - 星级图标的字体大小(pt)。
 * @param {number} [options.icons_margin=8] - 星级图标之间的额外间距(px)。
 * @param {number} [options.edge_margin=0] - 星级环距离根元素边缘的间距(px)。
 */
function ratingStars(root, options) {
  // 获取元素的半径(假定为圆形)
  const getRadius = (element) => {
    if (element.offsetHeight === element.offsetWidth) {
      return Math.round(element.offsetWidth / 2);
    } else {
      console.error("传入的元素不是圆形,可能导致布局异常。");
      return null;
    }
  };

  // 根据半径和角度计算圆周上的 x, y 坐标
  const pos = (r, theta) => {
    // theta * (Math.PI / 180) 将角度转换为弧度
    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",
    rotate: 0, // 整体旋转角度 (deg)
    clock_wise: true, // 是否顺时针排列 (boolean)
    size: 20, // 图标字体大小 (pt)
    icons_margin: 8, // 图标之间的额外间距 (px)
    edge_margin: 0, // 星级环距离根元素边缘的间距 (px)
  };
  // 合并自定义选项
  op = { ...op, ...options };

  const radius = getRadius(root); // 根元素的半径
  if (radius) {
    // 创建主容器,用于包裹所有星级图标
    const ratingWrapper = document.createElement("div");
    ratingWrapper.style.position = "absolute";
    // 将主容器移动到根元素的中心
    ratingWrapper.style.left = `${radius - op.size / 2}px`;
    ratingWrapper.style.top = `${radius - op.size / 2}px`;
    root.append(ratingWrapper);

    // 计算每个星级图标的角度
    let degrees = [];
    const step = op.size / Math.PI + op.icons_margin; // 计算每个图标在圆周上的理论间距
    if (op.clock_wise) {
      for (let i = 0; i < op.count; i++) degrees.push(Math.round(i * step));
    } else {
      for (let i = 0; i < op.count; i++) degrees.push(-Math.round(i * step));
    }

    // 遍历角度数组,创建并定位每个星级图标
    degrees.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 坐标
      // deg + op.rotate 结合了单个图标的角度和整体旋转角度
      const { x, y } = pos(currentRadius, deg + op.rotate);
      iconHolder.style.left = `${x}px`;
      iconHolder.style.top = `${y}px`;

      // 插入星级图标
      iconHolder.innerHTML = ``;
      ratingWrapper.append(iconHolder);
    });
  }
}

// 示例用法:
const avatars = document.querySelectorAll(".avatar-container");

// 默认配置
ratingStars(avatars[0]);

// 自定义图标颜色
ratingStars(avatars[1], { icons_class: 'rating-icons red' });

// 整体旋转角度
ratingStars(avatars[2], { rotate: 143 });

// 逆时针排列
ratingStars(avatars[3], { clock_wise: false });

// 自定义图标大小
ratingStars(avatars[4], { size: 28 });

// 自定义图标间距
ratingStars(avatars[5], { icons_margin: 20 });

// 自定义距离边缘的间距
ratingStars(avatars[6], { edge_margin: 20 });

// 综合自定义
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 });

注意事项:

  • getRadius 函数用于确保传入的元素是圆形,以避免计算错误。
  • pos 函数是核心,它利用 Math.cos 和 Math.sin 将极坐标(半径和角度)转换为笛卡尔坐标(x, y)。
  • options 对象提供了极大的灵活性,可以调整星级的数量、颜色、旋转方向、大小、间距以及距离容器边缘的距离。
  • ratingWrapper 被定位在根元素的中心,其内部的图标再根据计算出的 x, y 坐标进行相对定位。

总结与选择

两种方法都能有效地在圆形头像周围创建环形星级评分,但它们各有侧重:

  1. CSS transform 方法:

    • 优点: 相对直观,利用CSS原生变换能力,对于固定数量和布局的星级,性能可能略优。
    • 缺点: 计算 translateX 和反向旋转的角度可能需要一些尝试和调整,灵活性相对较低,每次调整都需要修改JavaScript逻辑。
    • 适用场景: 当星级数量和布局相对固定,且对性能有较高要求时。
  2. 纯JavaScript与三角函数方法:

    • 优点: 极高的灵活性和可配置性,通过 options 对象可以轻松调整星级的各种属性,代码封装性好,易于复用。
    • 缺点: 涉及三角函数计算,初次理解可能稍复杂,对于大量元素的动态生成和定位,可能会有轻微的性能开销(通常可忽略)。
    • 适用场景: 需要高度定制化、动态调整星级布局,或在不同场景下复用评分组件时。

在实际开发中,推荐使用第二种基于纯JavaScript和三角函数的方法,因为它提供了更强大的抽象和配置能力,使得组件更易于维护和扩展。无论选择哪种方法,都应确保代码的清晰性、可读性,并考虑到响应式设计和无障碍访问的需求。例如,可以为星级添加ARIA属性,以提高屏幕阅读器用户的体验。

User AvatarUser Avatar

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

559

2023.06.20

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

437

2023.07.04

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

776

2023.07.04

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

480

2023.09.01

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

554

2023.09.04

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

1091

2023.09.04

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

659

2023.09.12

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

554

2023.09.20

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

31

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.8万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3万人学习

CSS教程
CSS教程

共754课时 | 23.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号