Skip to content

Instantly share code, notes, and snippets.

@kobitoDevelopment
Last active June 14, 2022 16:46
Show Gist options
  • Select an option

  • Save kobitoDevelopment/d979a4dab2bb0eda175dc05b62e6e7ac to your computer and use it in GitHub Desktop.

Select an option

Save kobitoDevelopment/d979a4dab2bb0eda175dc05b62e6e7ac to your computer and use it in GitHub Desktop.
<button class="prev">prev</button>
<button class="next">next</button>
<div class="circle-wrap">
<div class="circle-item">1</div>
<div class="circle-item">2</div>
<div class="circle-item">3</div>
<div class="circle-item">4</div>
<div class="circle-item">5</div>
<div class="circle-item">6</div>
<div class="circle-item">7</div>
<div class="circle-item">8</div>
</div>
const deviceWidth = window.innerWidth;
const circleWrap = document.querySelector(".circle-wrap");
const circleItem = document.querySelectorAll(".circle-item");
const circleItemLength = circleItem.length;
const deg = 360.0 / circleItemLength;
const red = (deg * Math.PI) / 180.0;
let xArray = [];
let maxDiameter;
const buttonPrev = document.querySelector(".prev");
const buttonNext = document.querySelector(".next");
const rotateSize = 360 / circleItemLength;
let nextRotateSize = 0;
const slideTime = 4000;
let timer;
// 自動スライドを設定
function startTimer() {
timer = setInterval(function () {
buttonNext.click();
}, slideTime);
}
// 自動スライドの停止を設定
function stopTimer() {
clearInterval(timer);
}
window.addEventListener("load", function () {
circleItem.forEach(function (elem, index) {
const circleR = elem.offsetWidth * 1.4; // 要素同士の感覚比率
const x = Math.cos(red * index) * circleR + circleR;
const y = Math.sin(red * index) * circleR + circleR;
elem.style.left = x + "px";
elem.style.top = y + "px";
const circleWidth = document.defaultView.getComputedStyle(elem, null).width;
const circleLeft = document.defaultView.getComputedStyle(elem, null).left;
const circleWidthNum = Number(parseFloat(circleWidth));
const circleLeftNum = Number(parseFloat(circleLeft));
xArray.push(circleLeftNum);
// Math.max Math.min は複数の数値を比較できるが配列を比較できないためスプレッド構文で渡す
const maxLeft = Math.max(...xArray);
// 最もleftの大きい要素+要素幅を合計する事で円周上に配置された要素全体の横幅を算出
maxDiameter = maxLeft + circleWidthNum;
});
circleWrap.style.width = maxDiameter + "px";
circleWrap.style.height = maxDiameter + "px";
// コンテンツ幅が画面幅を超えた場合
if (deviceWidth < maxDiameter) {
// 両橋を見切れさせて中央寄せ
const dif = (deviceWidth - maxDiameter) / 2;
circleWrap.style.left = dif + "px";
}
buttonNext.addEventListener("click", function () {
nextRotateSize = nextRotateSize + rotateSize;
circleWrap.style.transform = `rotate(${nextRotateSize}deg)`;
circleItem.forEach(function (elem, index) {
/// -(x)でxが正数なら負数へ、xが負数なら正数へ変換する事でwrapとitemのrotate数値を反転
elem.style.transform = `rotate(${-nextRotateSize}deg)`;
});
});
buttonPrev.addEventListener("click", function () {
nextRotateSize = nextRotateSize - rotateSize;
circleWrap.style.transform = `rotate(${nextRotateSize}deg)`;
circleItem.forEach(function (elem, index) {
/// -(x)でxが正数なら負数へ、xが負数なら正数へ変換する事でwrapとitemのrotate数値を反転
elem.style.transform = `rotate(${-nextRotateSize}deg)`;
});
});
// 自動スライド発火
startTimer();
circleItem.forEach(function (elem, index) {
// マウスオンで自動スライド停止
elem.addEventListener("mouseover", function () {
stopTimer();
});
// マウスリーブで自動スライド再開
elem.addEventListener("mouseleave", function () {
startTimer();
});
});
});
// リザイズ時に円周場の要素を再配置
window.addEventListener("resize", function () {
stopTimer();
xArray = [];
const deviceWidth = window.innerWidth;
circleItem.forEach(function (elem, index) {
const circleR = elem.offsetWidth * 1.4;
const x = Math.cos(red * index) * circleR + circleR;
const y = Math.sin(red * index) * circleR + circleR;
elem.style.left = x + "px";
elem.style.top = y + "px";
const circleWidth = document.defaultView.getComputedStyle(elem, null).width;
const circleLeft = document.defaultView.getComputedStyle(elem, null).left;
const circleWidthNum = Number(parseFloat(circleWidth));
const circleLeftNum = Number(parseFloat(circleLeft));
xArray.push(circleLeftNum);
// Math.max Math.min は複数の数値を比較できるが配列を比較できないためスプレッド構文で渡す
const maxLeft = Math.max(...xArray);
maxDiameter = maxLeft + circleWidthNum;
});
circleWrap.style.width = maxDiameter + "px";
circleWrap.style.height = maxDiameter + "px";
if (deviceWidth < maxDiameter) {
const dif = (deviceWidth - maxDiameter) / 2;
circleWrap.style.left = dif + "px";
}
startTimer();
});
.circle-wrap {
position: relative;
top: 0;
left: 0;
z-index: 1;
margin-right: auto;
margin-left: auto;
display: flex;
justify-content: center;
align-items: center;
transform-origin: center;
transition: 1s 0.1s;
.circle-item {
width: 30vw; //希望の円形要素1つの横幅
max-width: 200px; // 希望の最大幅
aspect-ratio: 1/1;
background-color: orange; //デバッグ用背景
border-radius: 50%;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
transform-origin: center;
transition: 1s 0.1s;
}
}
.prev {
z-index: 2;
}
.next {
z-index: 2;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment