CSS/Javascript:如何制作具有多种状态的旋转圆形菜单?

ASp*_*Gun 5 html javascript css wordpress jquery

通常我不会发布我自己,我通常会通过其他人的帖子找到我需要的东西,所以如果其中任何一个位置错误或格式不正确,我很抱歉。我以前从来没有这样做过。

所以这里的情况

我正在尝试重建我的网站,我选择使用 WordPress 的 X 主题。大多数情况下,它进展顺利,但有几次我想要自定义并绕过 X,事实证明它有点困难。如果您知道一种在 X 中执行此操作的方法,可以在不进行自定义编码的情况下完成此操作,我会全力以赴。

所以这就是我想要做的

我有一个圆形菜单的想法,将它的元素定位到顶部是菜单的“选定”元素的位置。所以它在布局方面看起来像这样:

(对不起,显然我太新,无法在我的帖子中使用图片:/)

基本状态 http : //i.stack.imgur.com/Gs2Nz.jpg

现在,当用户单击一个项目时,我希望它将新选定的项目旋转到上图中“1”项目所在的顶部。所以它会是这样的:

如果用户选择了第 3 项,则菜单项会旋转 http : //i.stack.imgur.com/KWseu.jpg

其他一些需要注意的事情:我希望菜单项的文本或图像始终正常对齐,换句话说,我不希望元素文本在旋转后颠倒或出现某些情况。

我希望在页面加载时处理的元素的原始定位,而不是在 CSS 样式中进行硬编码。主要是为了它可以动态完成。

我打算对菜单做更多的事情,但我遇到了这种行为的问题。

我尝试过类似 Jquery 的 Animate() 方法,或使用 JavaScript 来影响每个元素的 css“top”和“left”属性,但它似乎不起作用,因为元素似乎不想移动.

我不知道尝试通过 X 的定制器区域是否不是问题,因为这是我被告知添加 JavaScript 代码的地方。或者这可能与我没有正确地将 JavaScript/JQuery 代码与 CSS 连接起来有关,我有相当多的编码经验,但我对 JQuery/CSS 等比较陌生。

如此简短的版本:我试图找到一种方法,当页面加载时,元素围绕中心点动态定位。然后当用户点击一个元素时,所有元素都围绕中心旋转,直到新选择的项目位于顶部。当用户选择不同的项目时,这种行为应该继续。

很抱歉这是一篇很长的文章,但我只是想尽我所能解释一下。任何见解或建议将不胜感激!提前致谢!:)

更新: 所以我最终尝试了 marzelin 的答案,因为它看起来非常适合我想要的。但是,当我将它添加到 X-Theme 的 Javascript 区域并更新我的 CSS 时,元素并没有移动。它们都堆叠在中心,但它们没有环绕中心点,单击它们似乎没有任何作用。似乎 CSS 已经生效,但 Javascript 部分由于某种原因没有影响元素?

这是我使用的 marzelin 的答案只是 JavaScript 部分):

const buttons = Array.from(document.querySelectorAll('.button'))
const count = buttons.length
const increase = Math.PI * 2 / buttons.length
const radius = 150
let angle = 0

buttons.forEach((button, i) => {
  button.style.top = Math.sin(-Math.PI / 2 + i * increase) * radius + 'px'
  button.style.left = Math.cos(-Math.PI / 2 + i * increase) * radius + 'px'
  button.addEventListener('click', move)
})

function move(e) {
  const n = buttons.indexOf(e.target)
  const endAngle = (n % count) * increase
  turn()
  function turn() {
    if (Math.abs(endAngle - angle) > 1/8) {
      const sign = endAngle > angle ? 1 : -1
      angle = angle + sign/8
      setTimeout(turn, 20)
    } else {
      angle = endAngle
    }
    buttons.forEach((button, i) => {
      button.style.top = Math.sin(-Math.PI / 2 + i * increase - angle) * radius + 'px'
      button.style.left = Math.cos(-Math.PI / 2 + i * increase - angle) * radius + 'px'
    })
  }
}
Run Code Online (Sandbox Code Playgroud)

这是我的 X-Theme 的 javascript 部分目前的样子(不包括其他功能的其他代码,例如隐藏我的导航栏等):

jQuery(function($){

/* javascript or jquery code goes here */
  const stars = Array.from(document.querySelectorAll('.btnStars'));
  const count = stars.length;
  const increase = Math.PI * 2 / stars.length;
  const radius = 300;
  let angle = 0;

  stars.forEach((star, i) => {
    star.style.top = Math.sin(-Math.PI / 2 + i * increase) * radius + 'px';
    star.style.left = Math.cos(-Math.PI / 2 + i * increase) * radius + 'px';
    });

  $('.btnStar').click(function(e) {
    const n = stars.indexOf(e.target);
    const endAngle = (n % count) * increase;

    function turn() {
      if (Math.abs(endAngle - angle) > 1/8) {
        const sign = endAngle > angle ? 1 : -1;
        angle = angle + sign/8;
        setTimeout(turn, 20);
      } else {
        angle = endAngle;
      }

      stars.forEach((star, i) => {
        star.style.top = Math.sin(-Math.PI / 2 + i * increase - angle) * radius + 'px';
        star.style.left = Math.cos(-Math.PI / 2 + i * increase - angle) * radius + 'px';
      })
    }

    turn();
  });
});
Run Code Online (Sandbox Code Playgroud)

我确实更改了一些内容,即 CSS 类名称等,但大部分内容是相同的。我做了一些事情,比如重新组织,因为 X Theme 的编辑器似乎不知道其中一些函数是什么,所以我在调用它们之前将它们移到了,然后它似乎找到了它们。诸如此类的小事。

我还尝试将 move 函数更改为 JQuery .click 函数以查看是否会触发任何内容,但它似乎没有改变任何内容。

虽然我之前使用过 Javascript 和一些 JQuery,但我从未真正尝试过将它合并到 WordPress 主题中,所以我真的不知道这不起作用。

有没有人看到我做错了什么?因为我很困惑为什么这不起作用。:/

mar*_*lin 5

简单的MVP

const buttons = Array.from(document.querySelectorAll('.button'))
const count = buttons.length
const increase = Math.PI * 2 / buttons.length
const radius = 150

buttons.forEach((button, i) => {
  button.style.top = Math.sin(-Math.PI / 2 + i * increase) * radius + 'px'
  button.style.left = Math.cos(-Math.PI / 2 + i * increase) * radius + 'px'
  button.addEventListener('click', move)
})

function move(e) {
  const n = buttons.indexOf(e.target)
  buttons.forEach((button, i) => {
    button.style.top = Math.sin(-Math.PI / 2 + (i - n % count) * increase) * radius + 'px'
    button.style.left = Math.cos(-Math.PI / 2 + (i - n % count) * increase) * radius + 'px'
  })
}
Run Code Online (Sandbox Code Playgroud)
html,
body {
  height: 100%;
}
.menu {
  height: 100%;
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  background-color: seagreen;
  -webkit-box-pack: center;
  -webkit-justify-content: center;
  -ms-flex-pack: center;
  justify-content: center;
  -webkit-box-align: center;
  -webkit-align-items: center;
  -ms-flex-align: center;
  align-items: center;
}
.center {
  width: 100px;
  height: 100px;
  background-color: goldenrod;
  border-radius: 100%;
  position: relative;
  line-height: 100px;
  text-align: center;
}
.button {
  position: absolute;
  width: 100px;
  height: 100px;
  border-radius: 100%;
  -webkit-transition: all 0.5s;
  transition: all 0.5s;
  background-color: pink;
  line-height: 100px;
  text-align: center;
}
Run Code Online (Sandbox Code Playgroud)
<div class="menu">
  <div class="center">Menu
    <div class="button">1</div>
    <div class="button">2</div>
    <div class="button">3</div>
    <div class="button">4</div>
    <div class="button">5</div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

圆周运动

const buttons = Array.from(document.querySelectorAll('.button'))
const count = buttons.length
const increase = Math.PI * 2 / buttons.length
const radius = 150
let angle = 0

buttons.forEach((button, i) => {
  button.style.top = Math.sin(-Math.PI / 2 + i * increase) * radius + 'px'
  button.style.left = Math.cos(-Math.PI / 2 + i * increase) * radius + 'px'
  button.addEventListener('click', move)
})

function move(e) {
  const n = buttons.indexOf(e.target)
  const endAngle = (n % count) * increase
  turn()
  function turn() {
    if (Math.abs(endAngle - angle) > 1/8) {
      const sign = endAngle > angle ? 1 : -1
      angle = angle + sign/8
      setTimeout(turn, 20)
    } else {
      angle = endAngle
    }
    buttons.forEach((button, i) => {
      button.style.top = Math.sin(-Math.PI / 2 + i * increase - angle) * radius + 'px'
      button.style.left = Math.cos(-Math.PI / 2 + i * increase - angle) * radius + 'px'
    })
  }
}
Run Code Online (Sandbox Code Playgroud)
html, body {
  height: 100%;
}

.menu {
  height: 100%;
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  background-color: seagreen;
  -webkit-box-pack: center;
  -webkit-justify-content: center;
      -ms-flex-pack: center;
          justify-content: center;
  -webkit-box-align: center;
  -webkit-align-items: center;
      -ms-flex-align: center;
          align-items: center;
  line-height: 100px;
  text-align: center;
}

.center {
  width: 100px;
  height: 100px;
  background-color: goldenrod;
  border-radius: 100%;
  position: relative;
}

.button {
  position: absolute;
  width: 100px;
  height: 100px;
  border-radius: 100%;
  background-color: pink;
  line-height: 100px;
  text-align: center;
  cursor: pointer;
}
Run Code Online (Sandbox Code Playgroud)
<div class="menu">
  <div class="center">menu
    <div class="button">1</div>
    <div class="button">2</div>
    <div class="button">3</div>
    <div class="button">4</div>
    <div class="button">5</div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)