JavaScript 环形/圆形排列(列表、标签)

要使用JavaScript和数学函数实现环形排列的标签,我们需要按照以下步骤进行

(1)确定圆心: 首先,设定一个固定的圆心位置,通常设在父容器的正中心。假设父容器的宽度和高度相等,且为containerWidth和containerHeight。
(2)确定半径: 设定一个固定的半径radius,这个值将决定环形标签的紧凑程度。

(3)元素数量: 确定需要排列的元素数量,length。

(4)计算角度: 每个元素占据的角度为360° / length。这将帮助我们计算每个元素相对于圆心的位置。
(5)使用三角函数计算位置: 对于每一个元素,我们可以根据其在环中的顺序索引i来计算其在环上的角度θ(单位为弧度)。然后,利用三角函数sin和cos来计算该点在直角坐标系中的x坐标(即left值)和y坐标(即top值)。

		x = radius * Math.cos(θ)
		y = radius * Math.sin(θ)

注意,θ应该是从极坐标转换到直角坐标的弧度值,可以通过 θ = (i * 2 * Math.PI) / elementCount 来计算,其中i是从0开始的索引
(6)调整坐标以适应HTML元素定位: 由于HTML的坐标原点位于元素的左上角,而我们的计算是以圆心为原点,因此还需要对计算出的x和y值进行适当的偏移,使元素正确居中显示。具体来说,需要将x和y值分别加上容器的宽高的一半,并考虑容器的偏移(如果有的话)。
(7)最后,通过JavaScript为每个子元素设置position: absolute,并根据计算出的lefttop值进行定位。

原文介绍👉传送门 亲测好用

在这里插入图片描述

全部代码👇

在这里插入图片描述

<template>
  <div class="li" v-if="boxShow">
    <div
      class="box"
      v-for="(item, index) in data"
      :key="item.id"
      @click="handleItem(item,index)"
    >
      <div class="text">
        {{ item.name }}
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "circle",
  components: {},
  data() {
    return {
      data: [],
      boxShow: true,
    };
  },
  created() {
    this.initData();
  },
  mounted() {
    this.$nextTick(() => this.initBox());
  },
  methods: {    
    // 模拟数据
    initData() {
      /*
       * @Author: Do not edit
       * @Date: 2024-05-20 17:55:50
       * @LastEditors: Do not edit
       * @LastEditTime: 2024-05-20 17:55:50
       * @FilePath: Do not edit
       * @Description: 拟生成数据Array,名称为随机的1、2、3、4、5
       */
      // 生成条数
      const steps = 10;
      const item = () => {
        // 生成随机名称
        const name = Math.floor(Math.random() * steps); 
        // 获取当前时间戳
        const timestamp = Date.now();
        return {name, timestamp};
      };
      let array = [];
      for (let i = 0; i < steps; i++) {
        array.push(item());
      }
      // console.log(array)
      this.data = array;
    },
    initBox() {
      const dotLeft = 150; // 中心点横坐标
      const dotTop = 150; // 中心点纵坐标
      const radius = 100; // 半径
      const boxs = document.getElementsByClassName("box"); // 每个box 数量
      this.setBoxPositions(boxs, radius, dotLeft, dotTop);
    },
    // 处理元素排列位置
    setBoxPositions(boxs, radius, dotLeft, dotTop) {
      const boxCount = boxs.length;
      const stard = 0; //起始角度
      const angle = 360 / boxCount + stard; //每一个BOX对应的角度;
      const radian = (angle * Math.PI) / 180; //每一个BOX对应的弧度;
      for (let i = 0; i < boxCount; i++) {
        boxs[i].style.left = Math.sin(radian * i) * radius + dotLeft + "px";
        boxs[i].style.top = Math.cos(radian * i) * radius + dotTop + "px";
      }
    },
    // 点击
    handleItem(item,index) {
      // 这里处理点击后的逻辑
      console.log(item,index);
    },
  },
};
</script>
<style lang="scss" scoped>
.li {
  position: relative;
  z-index: 199;
  width: 380px;
  height: 380px;
  margin: 10px;
  .box {
    width: 50px;
    height: 50px;
    line-height: 50px;
    font-size: 15px;
    position: absolute;
    cursor: pointer;
    text-align: center;
    border: 1px solid #1ba1ff;
    border-radius: 50%;
  }
}
</style>

还需要有优化的地方

(1)使用Vue的响应式数据更新位置:虽然直接操作DOM可以实现功能,但在Vue中更推荐使用数据绑定来更新视图。可以考虑将计算好的left和top值直接存入每个item的数据对象中,利用Vue的响应式机制自动更新视图。

(2)考虑元素大小:当前代码未考虑box的实际尺寸,可能导致视觉上不是完美的环形排列。可以在计算left和top时,减去或加上box宽度的一半,以确保元素中心对齐。

(3)过渡动画:为了增强用户体验,可以考虑添加CSS过渡或Vue的动态过渡效果,使得元素在布局变化时有平滑的动画效果。

(4)自适应性:如果需要该组件在不同尺寸的容器中都能良好显示,可以考虑将中心点坐标、半径等值与容器尺寸动态绑定,实现更好的响应式设计。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值