- エーオーシステム コーポレートサイト
https://www.aosystem.co.jp/ - エーオーシステム プロダクトサイト
https://ao-system.net/ - レンタルサーバー
- バーチャル展示会
- ウェブカタログサービス
- 3Dグラフィック
- Android アプリ
- iOS (iPhone,iPad) アプリ
- Flutter開発
- プログラミング記録QuickAnswer
- 無料画像素材
- スカイボックス 3D SKY BOX
このページのQRコード
/**
* 画像切り替え
*
* @author ao-system, Inc.
* @date 2020-07-01
* @date 2024-01-12
* @date 2024-01-17 Rewrite the code using the class syntax.
*
* this.stage.style.transition、this.stage.style.transform の処理を
* this.stage.animate()での実装を試みたが正常に動作しなかった。
*
<section class="swipepanel">
<div>
<div id="swipePanelStage"></div>
</div>
</section>
<style>
section.swipepanel {
background-color: #000;
padding: 20px;
> div {
> #swipePanelStage {
display: flex;
justify-content: center;
column-gap: 10px;
> div {
user-select: none;
}
}
}
}
</style>
*
*/
(() => {
'use strict';
class SwipePanel {
#constProperties = [
{prop: 'stage', value: document.getElementById('swipePanelStage')},
{prop: 'imageWidth', value: 300},
{prop: 'imageGap', value: 10},
{prop: 'itemMinCount', value: 14}, //3840 / (300 + 10) + 1
{prop: 'imageSlideInterval', value: 4000}, //画像切り替え間隔
{prop: 'swipeShreshold', value: 50}, //スワイプ判定幅
];
#itemCount = 0; //奇数か偶数かで処理が分岐
#loopTimeoutId = null; //自動スワイプのタイムアウト
#isBusy = false; //動作中
#focusFlag = true; //フォーカスが外れている時は動作させない
#swipeStartX = 0; //スワイプ開始位置
#isSwiping = false; //スワイプ中
#swipeTimeoutId = null; //スワイプ操作のタイムアウト
#values = [];
//
constructor(values) {
this.#values = values;
this.#constProperties.forEach((obj) => Object.defineProperty(this, obj.prop, {value:obj.value, writable:false}));
this.#init();
}
#init() {
//シャッフルさせる場合
//this.#values = shuffle(this.#values);
//window.addEventListener('focus',() => { this.#focusFlag = true;}); //out focusで停止させる場合の処理
//window.addEventListener('blur',() => { this.#focusFlag = false;}); //out focusで停止させる場合の処理
this.#setItemCount();
this.#initImages();
this.#initSwipe();
this.#autoSlide();
}
#shuffle(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
#setItemCount() {
this.#itemCount = this.#values.length;
for (let i = 0; i < this.itemMinCount; i++) {
if (this.#itemCount < this.itemMinCount) {
this.#itemCount += this.#values.length;
} else {
break;
}
}
}
#initImages() {
for (let i = 0; i < this.#itemCount; i++) {
const obj = this.#values[i % this.#values.length];
const img = new Image();
img.src = obj.src;
img.setAttribute('data-link',obj.link);
img.setAttribute('data-external',obj.external);
img.setAttribute('draggable','false');
const div = document.createElement('div');
div.appendChild(img);
this.stage.appendChild(div);
}
//画像数が偶数の場合は先頭に1個ダミーを置く
if (this.#itemCount % 2 == 0) {
const obj = this.#values[0];
const img = new Image();
img.src = obj.src;
img.setAttribute('draggable','false');
const div = document.createElement('div');
div.appendChild(img);
const divs = this.stage.querySelectorAll('div');
this.stage.insertBefore(div,divs[0]);
}
}
#initSwipe() {
this.stage.addEventListener('click', (e) => { e.preventDefault();});
this.stage.addEventListener('mousedown', (e) => { this.#swipeStart(e.clientX); });
this.stage.addEventListener('mousemove', (e) => { this.#swipeMove(e.clientX); });
this.stage.addEventListener('mouseup', (e) => { this.#swipeEnd(e.target, e.clientX); });
this.stage.addEventListener('touchstart', (e) => { this.#swipeStart(e.touches[0].clientX); });
this.stage.addEventListener('touchmove', (e) => { this.#swipeMove(e.touches[0].clientX); });
this.stage.addEventListener('touchend', (e) => { this.#swipeEnd(e.target, e.changedTouches[0].clientX); });
}
#swipeStart(positionX) {
if (this.#isBusy) {
return;
}
this.#swipeStartX = positionX;
this.stage.style.cursor = 'grabbing';
this.#isSwiping = true;
this.#swipeTimeoutId = setTimeout(() => {
this.stage.style.transform = '';
this.stage.style.cursor = '';
this.#isSwiping = false;
},1000);
}
#swipeMove(positionX) {
if (this.#isSwiping == false) {
return;
}
let x = positionX - this.#swipeStartX;
const maxSlideWidth = this.imageWidth + this.imageGap;
if (x <= -maxSlideWidth) {
x = -maxSlideWidth;
} else if (x >= maxSlideWidth) {
x = maxSlideWidth;
}
this.stage.style.transform = 'translateX(' + x + 'px)';
}
#swipeEnd(targetElm,positionX) {
clearTimeout(this.#swipeTimeoutId);
if (this.#isSwiping == false) {
return;
}
if (this.#swipeStartX - positionX > this.swipeShreshold) {
this.#slideAction(true); //正方向
} else if (this.#swipeStartX - positionX < -this.swipeShreshold) {
this.#slideAction(false); //逆方向
} else {
this.stage.style.transform = 'translateX(0px)';
const dataLink = targetElm.getAttribute('data-link');
if (dataLink) {
const dataExternal = targetElm.getAttribute('data-external');
if (dataExternal) {
window.open(dataLink, '_blank');
} else {
window.location.href = dataLink;
}
}
}
setTimeout(() => {
this.stage.style.cursor = '';
this.stage.style.transition = '';
clearTimeout(this.#loopTimeoutId);
this.#autoSlide();
this.#isSwiping = false;
},20);
}
#slideAction(direction) {
this.#isBusy = true;
if (direction) {
setTimeout(() => {
this.stage.style.transition = '0.3s';
this.stage.style.transform = 'translateX(-' + (this.imageWidth + this.imageGap) + 'px)';
setTimeout(() => {
this.stage.style.transition = '';
const divs = this.stage.querySelectorAll('div');
if (this.#itemCount % 2 == 0) {
this.stage.removeChild(divs[1]);
this.stage.appendChild(divs[1]);
} else {
this.stage.removeChild(divs[0]);
this.stage.appendChild(divs[0]);
}
this.stage.style.transform = '';
this.#isBusy = false;
},300);
},50);
} else {
setTimeout(() => {
this.stage.style.transition = '0.3s';
this.stage.style.transform = 'translateX(' + (this.imageWidth + this.imageGap) + 'px)';
setTimeout(() => {
this.stage.style.transition = '';
const divs = this.stage.querySelectorAll('div');
if (this.#itemCount % 2 == 0) {
this.stage.removeChild(divs[divs.length - 1]);
this.stage.insertBefore(divs[divs.length - 1],divs[1]);
} else {
this.stage.removeChild(divs[divs.length - 1]);
this.stage.insertBefore(divs[divs.length - 1],divs[0]);
}
this.stage.style.transform = '';
this.#isBusy = false;
},300);
},50);
}
}
#autoSlide() {
if (this.#isSwiping == false && this.#focusFlag) {
this.#slideAction(true);
}
this.#loopTimeoutId = setTimeout(() => {
this.#autoSlide();
},this.imageSlideInterval);
}
}
//
new SwipePanel(
[
{'src':'./image/panel01.webp','link':'','external':false},
{'src':'./image/panel02.webp','link':'','external':false},
{'src':'./image/panel03.webp','link':'','external':false},
{'src':'./image/panel04.webp','link':'','external':false},
{'src':'./image/panel05.webp','link':'','external':false},
{'src':'./image/panel06.webp','link':'','external':false},
]
);
})();
このページのQRコード
便利ウェブサイト
便利 Android アプリ
便利 iOS(iPhone,iPad) アプリ