- エーオーシステム コーポレートサイト
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 2024-02-05
*/
(() => {
'use strict';
new class {
////constant
#contentMagnificationWidth = 3000; //画像サイズ
#contentAspectRatio = (1500 / 2121); //画像アスペクト比
#stage = document.querySelector('div.stage');
#figure = document.querySelector('div.stage > figure');
#rangeScale = document.getElementById('rangeScale');
#rangeScaleValue = document.getElementById('rangeScaleValue');
#stageHeight = 600;
#magnificationMax = 100; //拡大率最大% floatは誤差が出るのでintで計算する
#magnificationMin = 10; //拡大率最小% floatは誤差が出るのでintで計算する
#magnificationRate = 50; //拡大率%。初期値。floatは誤差が出るのでintで計算する
#magnificationStep = 5; //拡大ステップ% floatは誤差が出るのでintで計算する
////variable
#isDragging = false; //ドラッグ操作 ドラッグ実行中
#startMouseX = 0; //ドラッグ操作 マウス位置
#startMouseY = 0; //ドラッグ操作 マウス位置
#startFigureX = 0; //ドラッグ操作 画像位置
#startFigureY = 0; //ドラッグ操作 画像位置
constructor() {
this.#init();
}
#init() {
//初期値
this.#figure.style.width = this.#contentMagnificationWidth + 'px';
this.#figure.style.height = (this.#contentMagnificationWidth / this.#contentAspectRatio) + 'px';
this.#rangeScale.setAttribute('min',this.#magnificationMin);
this.#rangeScale.setAttribute('max',this.#magnificationMax);
this.#rangeScale.setAttribute('step',this.#magnificationStep);
this.#figure.style.left = '0px';
this.#figure.style.top = '0px';
//リスナー登録
this.#setListenerSlider();
this.#setListenerWheel();
this.#setListenerDrag();
//初期サイズにする
this.#magnificationRate = this.#magnificationMin;
const rect = this.#stage.getBoundingClientRect();
const positionLeft = (rect.width / 2) + rect.left - ((this.#contentMagnificationWidth * this.#magnificationMin / this.#magnificationMax) / 4);
const positionTop = (rect.height / 2) + (rect.top / 2) - (this.#stageHeight * this.#magnificationMin / this.#magnificationMax) - ((window.pageYOffset || document.documentElement.scrollTop) / 2);
this.#scaleChange(positionLeft,positionTop);
}
//拡大スライダー操作のイベントリスナー登録
#setListenerSlider() {
this.#rangeScale.addEventListener('input', (event) => {
this.#magnificationRate = parseInt(event.target.value);
const rect = this.#stage.getBoundingClientRect();
this.#scaleChange(rect.width / 2 + rect.left, rect.height / 2 + rect.top);
});
}
//ホイール操作のイベントリスナー登録
#setListenerWheel() {
this.#stage.addEventListener('wheel', (event) => {
event.preventDefault();
//拡大率 this.#magnificationRate を求める
const lastMagnificationRate = this.#magnificationRate;
const delta = event.wheelDelta ? event.wheelDelta : -event.deltaY;
if (delta > 0) {
this.#magnificationRate += this.#magnificationStep;
if (this.#magnificationRate > this.#magnificationMax) {
this.#magnificationRate = this.#magnificationMax;
}
} else if (delta < 0) {
this.#magnificationRate -= this.#magnificationStep;
if (this.#magnificationRate < this.#magnificationMin) {
this.#magnificationRate = this.#magnificationMin;
}
}
if (lastMagnificationRate == this.#magnificationRate) { //拡大率に変化が無ければ何もしない
return;
}
this.#scaleChange(event.clientX, event.clientY);
});
}
//拡大縮小実行
#scaleChange(mouseX, mouseY) {
//拡大縮小前の値
const figureRect = this.#figure.getBoundingClientRect();
const figureWidth = figureRect.width;
const figureHeight = figureRect.height;
const figureLeft = figureRect.left;
const figureTop = figureRect.top;
//拡大縮小
this.#figure.style.transform = 'scale(' + (this.#magnificationRate / this.#magnificationMax) + ')';
//拡大縮小後の値
const figureRect2 = this.#figure.getBoundingClientRect();
const figureWidth2 = figureRect2.width;
const figureHeight2 = figureRect2.height;
//拡大縮小の前と後を比較して差をずらす
const pLeft = (parseFloat(this.#figure.style.left) - ((figureWidth - figureWidth2) / 2)); //左端基準に拡大縮小した場合に停止する位置
const pRight = (parseFloat(this.#figure.style.left) + ((figureWidth - figureWidth2) / 2)); //右端基準に拡大縮小した場合に停止する位置
const pRatioX = (mouseX - figureLeft) / figureWidth; //figureに対するマウス位置の割合
this.#figure.style.left = (pLeft + ((pRight - pLeft) * pRatioX)) + 'px';
//拡大縮小の前と後を比較して差をずらす
const pTop = (parseFloat(this.#figure.style.top) - ((figureHeight - figureHeight2) / 2)); //上端基準に拡大縮小した場合に停止する位置
const pBottom = (parseFloat(this.#figure.style.top) + ((figureHeight - figureHeight2) / 2)); //下端基準に拡大縮小した場合に停止する位置
const pRatioY = (mouseY - figureTop) / figureHeight; //figureに対するマウス位置の割合
this.#figure.style.top = (pTop + ((pBottom - pTop) * pRatioY)) + 'px';
this.#rangeScaleValue.textContent = String(parseInt(this.#magnificationRate / this.#magnificationMax * 100)).padStart(3,'0') + '%';
this.#rangeScale.value = this.#magnificationRate;
}
//ドラッグのイベントリスナー登録
#setListenerDrag() {
this.#figure.addEventListener('mousedown', (event) => {
this.#isDragging = true;
this.#startMouseX = event.clientX;
this.#startMouseY = event.clientY;
this.#startFigureX = this.#figure.offsetLeft;
this.#startFigureY = this.#figure.offsetTop;
this.#figure.style.cursor = 'grabbing';
});
this.#figure.addEventListener('mousemove', (event) => {
if (this.#isDragging) {
const deltaX = event.clientX - this.#startMouseX;
const deltaY = event.clientY - this.#startMouseY;
this.#figure.style.left = (this.#startFigureX + deltaX) + 'px';
this.#figure.style.top = (this.#startFigureY + deltaY) + 'px';
this.#figure.style.cursor = 'grabbing';
if (!event.buttons) {
this.#isDragging = false;
this.#figure.style.cursor = 'grab';
}
}
});
this.#figure.addEventListener('mouseup', () => {
if (this.#isDragging) {
this.#isDragging = false;
this.#figure.style.cursor = 'grab';
}
});
this.#figure.addEventListener('touchstart', (event) => {
this.#isDragging = true;
const touch = event.touches[0];
this.#startMouseX = touch.clientX;
this.#startMouseY = touch.clientY;
this.#startFigureX = this.#figure.offsetLeft;
this.#startFigureY = this.#figure.offsetTop;
});
this.#figure.addEventListener('touchmove', (event) => {
if (this.#isDragging) {
const touch = event.touches[0];
const deltaX = touch.clientX - this.#startMouseX;
const deltaY = touch.clientY - this.#startMouseY;
this.#figure.style.left = (this.#startFigureX + deltaX) + 'px';
this.#figure.style.top = (this.#startFigureY + deltaY) + 'px';
}
});
this.#figure.addEventListener('touchend', () => {
if (this.#isDragging) {
this.#isDragging = false;
}
});
}
}
})();
このページのQRコード
便利ウェブサイト
便利 Android アプリ
便利 iOS(iPhone,iPad) アプリ