React 커스터마이징

React 환경에서 VRISM Viewer SDK를 커스터마이징하는 방법을 소개합니다.

UI 설정을 통한 커스터마이징

기본 UI 설정

<VrismViewer
  token="your-token-here"
  contentId="your-content-id"
  ui={{
    // 배경색 변경
    viewerBackgroundColor: '#f8f9fa',
    
    // UI 요소 제어
    gestureGuide: true,           // 제스처 가이드 표시
    fullscreenButton: true,       // 전체화면 버튼 표시
    userGuide: true,              // 사용자 가이드 표시
    vtoControl: true,             // VTO 컨트롤 표시
    
    // 로더 커스터마이징
    loader: {
      type: 'circle',             // 'circle' 또는 'bar'
      size: 'medium',             // 'small', 'medium', 'large'
      loaderFillColor: '#007bff', // 로더 색상
      loaderPlaceholderColor: '#e9ecef'
    }
  }}
/>

카메라 설정

<VrismViewer
  token="your-token-here"
  contentId="your-content-id"
  camera={{
    // 자동 회전
    autoRotation: -2,
    
    // 사용자 조작 제어
    controls: {
      enableZoom: true,    // 줌 허용
      enablePan: true,     // 팬(이동) 허용  
      enableRotate: true   // 회전 허용
    },
    
    // 데스크톱 초기 위치
    desktop: {
      angle: { x: 0.2, y: 0.1 },
      zoom: 1.5,
      limits: {
        angleUp: 1.5,
        angleDown: -1.5,
        zoomMin: 0.5,
        zoomMax: 3.0
      }
    }
  }}
/>

ℹ️ desktopmobile 설정은 뷰포트 너비 769px을 기준으로 자동 전환됩니다.

CSS Variables를 통한 커스터마이징

전체화면 버튼 커스터마이징

.my-viewer {
  /* 버튼 색상 */
  --fullscreenBtnBgColor: #007bff;        /* 배경색 */
  --fullscreenIconColor: white;           /* 아이콘 색 */
  
  /* 버튼 크기 */
  --fullscreenBtnSize: 48px;              /* 버튼 크기 */

  /* 아이콘 크기 */
  --fullscreenIconSize: 24px;              /* 버튼 크기 */
  
  /* 버튼 위치 */
  --fullscreenBtnTop: auto;            /* 위쪽 여백 */
  --fullscreenBtnRight: 20px;             /* 오른쪽 여백 */
  --fullscreenBtnBottom: 20px;            /* 아래쪽 여백 */
  --fullscreenBtnLeft: auto;            /* 왼쪽 여백 */
}
<VrismViewer
  className="my-viewer"
  token="your-token-here"
  contentId="your-content-id"
  ui={{ fullscreenButton: true }}
/>

사용자 가이드 버튼 커스터마이징

.my-viewer {
  /* 가이드 버튼 스타일 */
  --guideBtnBgColor: #ffffff;           /* 배경색 */
  --guideBtnIconColor: #333333;         /* 아이콘 색 */
  --guideBtnSize: 48px;                 /* 버튼 크기 */
  --guideIconSize: 28px;                /* 아이콘 크기 */
  
  /* 가이드 버튼 위치 */
  --guideBtnTop: auto;                  /* 위쪽 여백 */
  --guideBtnRight: 28px;                /* 오른쪽 여백 */
  --guideBtnBottom: 80px;               /* 아래쪽 여백 */
  --guideBtnLeft: auto;                 /* 왼쪽 여백 */
}

VTO 버튼 커스터마이징

.my-viewer {
  /* VTO 버튼 스타일 */
  --vtoBtnBgColor: #28a745;               /* 배경색 */
  --vtoBtnColor: white;                   /* 텍스트 색 */
  --vtoFontSize: 16px;                    /* 텍스트 크기 */
  --vtoIconSize: 28px;                    /* 아이콘 크기 */
  
  /* VTO 버튼 위치 */
  --vtoBtnTop: auto;                       /* 위쪽 여백 */
  --vtoBtnRight: auto;                     /* 오른쪽 여백 */
  --vtoBtnBottom: 20px;                    /* 아래쪽 여백 */
  --vtoBtnLeft: 20px;                      /* 왼쪽 여백 */
}

제스처 가이드 커스터마이징

.my-viewer {
  --gestureGuideIconSize: 48px;           /* 제스처 가이드 크기 */
}

브랜드 통합 예시

// CSS (별도 파일 또는 styled-components)
const customStyles = `
.brand-viewer {
  /* 브랜드 컬러로 버튼 통일 */
  --fullscreenBtnBgColor: #ff6b35;
  --fullscreenIconColor: white;
  --guideBtnBgColor: #ff6b35;
  --guideBtnIconColor: white;
  --vtoBtnBgColor: #ff6b35;
  
  /* 버튼들을 더 크게 */
  --fullscreenBtnSize: 56px;
  --guideBtnSize: 56px;
  
  /* 버튼 위치 조정 */
  --fullscreenBtnRight: 24px;
  --fullscreenBtnBottom: 24px;
  --guideBtnRight: 24px;
  --guideBtnBottom: 88px;
}
`;

function BrandedViewer() {
  return (
    <>
      <style>{customStyles}</style>
      <VrismViewer
        className="brand-viewer"
        token="your-token-here"
        contentId="your-content-id"
        ui={{
          viewerBackgroundColor: '#f8f9fa',
          fullscreenButton: true,
          userGuide: true,
          vtoControl: true
        }}
      />
    </>
  );
}

Step Annotation 제어

마커만 끄고 스텝 기능 유지

<VrismViewer
  token="your-token-here"
  contentId="your-content-id"
  ui={{
    step: {
      enabled: true,           // 스텝 기능 활성화
      stepControls: true,      // 이전/다음 버튼 표시
      stepDots: true,          // 스텝 도트 네비게이션 표시
      stepNavigation: true,    // 스텝 정보 표시 (1/3 형태)
      stepAnnotation: false    // 🎯 마커만 끄기
      items: [
        {
          id: 1,
          name: '전체 보기',
          order: 1,
          anchor: {
            desktop: {
              position: { x: 0, y: 0, z: 5 },
              target: { x: 0, y: 0, z: 0 }
            },
            mobile: {
              position: { x: 0, y: 0, z: 5 },
              target: { x: 0, y: 0, z: 0 }
            }
          },
        },
        {
          id: 2,
          name: '디테일 보기',
          order: 2,
          anchor: {
            desktop: {
              position: { x: 2, y: 1, z: 3 },
              target: { x: 0, y: 0, z: 0 }
            },
            mobile: {
              position: { x: 2, y: 1, z: 3 },
              target: { x: 0, y: 0, z: 0 }
            }
          },
          annotation: {
            marker: {
              position: { x: 1, y: 0.5, z: 0 }
            },
            content: {
              title: '디테일 보기',
              description: '제품의 세부 디테일을 살펴보세요'
            }
          }
        }
      ]
    }
  }}
/>

결과: 카메라 앵글은 변경되지만 3D 마커는 표시되지 않음

외부 제어로 커스텀 네비게이션

import { useRef, useState } from 'react';

function ExternalControlViewer() {
  const viewerRef = useRef(null);
  const [currentStep, setCurrentStep] = useState(0);

  const goToStep = (step) => {
    viewerRef.current?.setStep(step);
    setCurrentStep(step);
  };

  return (
    <div>
      {/* 커스텀 스텝 네비게이션 */}
      <div className="custom-nav">
        <button onClick={() => goToStep(0)}>전체 뷰</button>
        <button onClick={() => goToStep(1)}>측면 뷰</button>
        <button onClick={() => goToStep(2)}>상세 뷰</button>
      </div>
      
      <VrismViewer
        ref={viewerRef}
        token="your-token-here"
        contentId="your-content-id"
        ui={{
          step: {
            enabled: true,           // 스텝 기능 활성화
            stepControls: false,     // 기본 이전/다음 버튼 숨김
            stepDots: false,         // 기본 도트 네비게이션 숨김
            stepAnnotation: false    // 마커 숨김
          }
        }}
        onStepChange={(options) => setCurrentStep(options.step || 0)}
      />
    </div>
  );
}

스텝 제어 조합표

step기능을 활성화 하기 위해서는 step.enabled를 true로 설정하고, step.items에 항목을 추가해야 합니다.

stepControls stepDots stepNavigation stepAnnotation 결과
true true true true 모든 UI 표시 (기본)
true true true false 버튼+도트+스텝정보, 마커 없음
true true false false 버튼+도트만, 마커 없음
true false true false 버튼+스텝정보만
false true true false 도트+스텝정보만
false true false false 도트 네비게이션만
false false true false 스텝정보만 (1/3 형태)
false false false false 모든 UI 숨김 (외부 제어용)

동적 설정 변경

import { useRef } from 'react';

function DynamicViewer() {
  const viewerRef = useRef(null);
  
  const changeBackground = async (color) => {
    // 뷰어 리로드로 설정 변경
    await viewerRef.current?.reload({
      ui: { viewerBackgroundColor: color }
    });
  };
  
  return (
    <div>
      <div style={{ marginBottom: '10px' }}>
        <button onClick={() => changeBackground('#ffffff')}>
          흰색 배경
        </button>
        <button onClick={() => changeBackground('#000000')}>
          검은색 배경
        </button>
        <button onClick={() => changeBackground('#f8f9fa')}>
          회색 배경
        </button>
      </div>
      
      <VrismViewer
        ref={viewerRef}
        token="your-token-here"
        contentId="your-content-id"
      />
    </div>
  );
}