Fix : 360 모바일 개선
This commit is contained in:
parent
95eaf73e30
commit
ca88e829ad
@ -440,7 +440,6 @@
|
||||
height: 100vh;
|
||||
background: rgba(0, 0, 0, 0.95);
|
||||
z-index: 2000;
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.panorama-modal.active {
|
||||
@ -515,7 +514,6 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
backdrop-filter: blur(10px);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
@ -549,7 +547,6 @@
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.3s ease;
|
||||
backdrop-filter: blur(10px);
|
||||
min-width: 80px;
|
||||
font-family: inherit;
|
||||
}
|
||||
@ -594,7 +591,6 @@
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
transition: all 0.3s ease;
|
||||
backdrop-filter: blur(10px);
|
||||
z-index: 100;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
@ -651,7 +647,6 @@
|
||||
max-width: 500px;
|
||||
width: 90%;
|
||||
z-index: 200;
|
||||
backdrop-filter: blur(20px);
|
||||
border: 2px solid rgba(255, 255, 255, 0.2);
|
||||
display: none;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.8);
|
||||
@ -696,10 +691,8 @@
|
||||
|
||||
/* 서버 호환성을 위한 추가 스타일 */
|
||||
.panorama-modal {
|
||||
/* 서버에서 배경 블러 지원 안될 때 대비 */
|
||||
/* 깔끔한 배경 - 블러 효과 제거 */
|
||||
background: rgba(0, 0, 0, 0.95) !important;
|
||||
backdrop-filter: blur(5px);
|
||||
-webkit-backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.panorama-viewer-container {
|
||||
@ -728,45 +721,69 @@
|
||||
padding: 3rem 0;
|
||||
margin: 3rem 0;
|
||||
}
|
||||
|
||||
|
||||
.panorama-section h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
|
||||
.panorama-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1.5rem;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
|
||||
.panorama-container {
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
|
||||
/* 모바일 360도 뷰어 컨테이너 최적화 - 경계 문제 해결 */
|
||||
.panorama-viewer-container {
|
||||
/* GPU 가속 활성화로 부드러운 렌더링 */
|
||||
transform: translateZ(0);
|
||||
-webkit-transform: translateZ(0);
|
||||
will-change: transform;
|
||||
/* 터치 시 확대/축소 제어 */
|
||||
touch-action: pan-x pinch-zoom;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
/* 경계 부분 매끄럽게 처리 */
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: crisp-edges;
|
||||
}
|
||||
|
||||
/* 모바일 줌 시 이미지 품질 개선 */
|
||||
.panorama-viewer-container img {
|
||||
/* 확대 시에도 선명한 이미지 유지 */
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: crisp-edges;
|
||||
/* 경계 부분 부드럽게 처리 */
|
||||
backface-visibility: hidden;
|
||||
-webkit-backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.panorama-modal-close {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
|
||||
.panorama-modal-close .close-icon::before,
|
||||
.panorama-modal-close .close-icon::after {
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
|
||||
.panorama-modal-controls {
|
||||
padding: 1.5rem;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
.panorama-control-buttons {
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
|
||||
.panorama-btn {
|
||||
min-width: 70px;
|
||||
padding: 0.75rem 1rem;
|
||||
|
||||
@ -375,25 +375,32 @@ class Easy360Viewer {
|
||||
}
|
||||
|
||||
setupImageSize() {
|
||||
// 이미지 자연 어숙비를 유지하면서 컨테이너 높이에 맞춤
|
||||
// 컨테이너 크기 가져오기
|
||||
const containerHeight = this.container.clientHeight;
|
||||
const containerWidth = this.container.clientWidth;
|
||||
const imageAspectRatio = this.image.naturalWidth / this.image.naturalHeight;
|
||||
|
||||
// 360도 이미지는 매우 가로가 기므로 컨테이너보다 훨씬 커야 함
|
||||
let imageWidth = containerHeight * imageAspectRatio;
|
||||
|
||||
// 컨테이너보다 작으면 컨테이너 너비에 맞춤
|
||||
if (imageWidth < containerWidth * 2) {
|
||||
imageWidth = containerWidth * 3; // 360도를 위해 충분히 큼
|
||||
|
||||
// 모바일에서 줌 시 경계 문제 해결을 위한 더 정확한 크기 계산
|
||||
let imageHeight = containerHeight * this.zoom;
|
||||
let imageWidth = imageHeight * imageAspectRatio;
|
||||
|
||||
// 360도 이미지는 매우 가로가 길므로 최소 크기 보장
|
||||
const minWidth = Math.max(containerWidth * 3, imageWidth);
|
||||
imageWidth = minWidth;
|
||||
imageHeight = imageWidth / imageAspectRatio;
|
||||
|
||||
// 줌 레벨에 따른 크기 조정 (모바일 확대 시 경계 문제 해결)
|
||||
if (this.zoom > 1) {
|
||||
imageHeight = Math.max(containerHeight, imageHeight);
|
||||
imageWidth = imageHeight * imageAspectRatio;
|
||||
}
|
||||
|
||||
// 이미지 크기 설정 - 브라우저 호환성 개선
|
||||
|
||||
// 이미지 크기 설정 - 픽셀 완벽 정렬로 경계 문제 방지
|
||||
this.image.style.width = Math.round(imageWidth) + 'px';
|
||||
this.image.style.height = Math.round(containerHeight) + 'px';
|
||||
this.image.style.height = Math.round(imageHeight) + 'px';
|
||||
this.imageWrapper.style.width = Math.round(imageWidth) + 'px';
|
||||
this.imageWrapper.style.height = Math.round(containerHeight) + 'px';
|
||||
|
||||
|
||||
// 단일 이미지 너비 저장
|
||||
this.singleImageWidth = imageWidth;
|
||||
}
|
||||
@ -553,13 +560,17 @@ class Easy360Viewer {
|
||||
|
||||
updatePosition(currentX) {
|
||||
const deltaX = currentX - this.lastX;
|
||||
|
||||
|
||||
// 좌우 이동 (드래그 방향과 반대)
|
||||
this.currentX -= deltaX;
|
||||
|
||||
// 속도 계산 (관성용)
|
||||
this.velocity = -deltaX * 0.1;
|
||||
|
||||
|
||||
// 속도 계산 (관성용) - 더 부드러운 관성 적용
|
||||
this.velocity = -deltaX * 0.15;
|
||||
|
||||
// 극한 속도 제한 (튀는 현상 방지)
|
||||
const maxVelocity = this.singleImageWidth * 0.05;
|
||||
this.velocity = Math.max(-maxVelocity, Math.min(maxVelocity, this.velocity));
|
||||
|
||||
this.updateTransform();
|
||||
this.lastX = currentX;
|
||||
}
|
||||
@ -583,32 +594,55 @@ class Easy360Viewer {
|
||||
|
||||
handleResize() {
|
||||
if (this.image && this.image.complete) {
|
||||
// 리사이즈 시 비율 유지
|
||||
const oldRatio = this.currentX / this.singleImageWidth;
|
||||
// 리사이즈 시 비율 유지하되, 튀는 현상 방지
|
||||
const oldRatio = (this.currentX - this.singleImageWidth) / this.singleImageWidth;
|
||||
const oldImageWidth = this.singleImageWidth;
|
||||
|
||||
this.setupImageSize();
|
||||
this.createDuplicateImages(); // 이미지 다시 생성
|
||||
this.currentX = this.singleImageWidth * oldRatio; // 비율 유지
|
||||
|
||||
// 정규화된 위치로 복원 (중앙 이미지 기준)
|
||||
this.currentX = this.singleImageWidth + (this.singleImageWidth * oldRatio);
|
||||
|
||||
// 경계값 확인 및 보정
|
||||
if (this.currentX < 0) this.currentX += this.singleImageWidth;
|
||||
if (this.currentX > this.singleImageWidth * 2) this.currentX -= this.singleImageWidth;
|
||||
|
||||
this.updateTransform();
|
||||
}
|
||||
}
|
||||
|
||||
updateTransform() {
|
||||
if (!this.imageWrapper || !this.singleImageWidth) return;
|
||||
|
||||
// 무한 스크롤 처리 - 더 부드럽게
|
||||
if (this.currentX <= 0) {
|
||||
this.currentX = this.singleImageWidth;
|
||||
} else if (this.currentX >= this.singleImageWidth * 2) {
|
||||
this.currentX = this.singleImageWidth;
|
||||
|
||||
// 무한 스크롤 처리 - 튀는 버그 방지를 위한 부드러운 전환
|
||||
const threshold = this.singleImageWidth * 0.1; // 10% 여유 공간
|
||||
|
||||
// 왼쪽 경계 처리 - 부드러운 전환
|
||||
if (this.currentX < -threshold) {
|
||||
this.currentX = this.singleImageWidth + (this.currentX + threshold);
|
||||
}
|
||||
|
||||
// 부드러운 변환을 위해 소수점 제거
|
||||
// 오른쪽 경계 처리 - 부드러운 전환
|
||||
else if (this.currentX > this.singleImageWidth * 2 + threshold) {
|
||||
this.currentX = this.singleImageWidth + (this.currentX - this.singleImageWidth * 2 - threshold);
|
||||
}
|
||||
|
||||
// 정확한 무한 루프 경계 처리 (튀는 현상 방지)
|
||||
const normalizedX = ((this.currentX % this.singleImageWidth) + this.singleImageWidth) % this.singleImageWidth;
|
||||
const actualX = normalizedX + this.singleImageWidth;
|
||||
|
||||
// 현재 위치와 목표 위치의 차이가 큰 경우만 보정 (부드러운 회전 유지)
|
||||
if (Math.abs(this.currentX - actualX) > this.singleImageWidth * 0.5) {
|
||||
this.currentX = actualX;
|
||||
}
|
||||
|
||||
// 고정밀 변환 계산 (소수점 2자리까지 유지하여 부드러움 보장)
|
||||
const translateX = Math.round(-this.currentX * 100) / 100;
|
||||
const scale = Math.round(this.zoom * 100) / 100;
|
||||
|
||||
const scale = Math.round(this.zoom * 1000) / 1000;
|
||||
|
||||
const transform = `translateX(${translateX}px) scale(${scale})`;
|
||||
this.imageWrapper.style.transform = transform;
|
||||
|
||||
|
||||
// 브라우저 호환성
|
||||
this.imageWrapper.style.webkitTransform = transform;
|
||||
this.imageWrapper.style.msTransform = transform;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user