Panolens compass
Compass
panolens에는 따로 지원하지 않는 것 같다. 그래서 직접 구현해보기했다.
google tour 에서 볼 수 있는 나침판처럼 동작을 하면 된다 . 누가 나침판 이미지를 만들어 주는게 아니니까 google tour으로 접속해서 나침판에 사용된 이미지를 다운받아 준비를 해뒀다. 기본적으로 panolens에서 버튼을 생성하는 아래 방식처럼 compass를 추가하길 원했다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <script type="text/javascript"> var panorama = new PANOLENS.BasicPanorama(10000); var options = { 'controlButtons':['fullscreen', 'setting', 'video', 'compass'], 'output': 'console' } var viewer = new PANOLENS.Viewer(options); myInfospot = new PANOLENS.Infospot(); myInfospot.position.set( 0, -5000, 0 ); myInfospot.setCursorHoverStyle( 'pointer' ); // set infospot hover style panorama.add(myInfospot); viewer.add(panorama); </script> | cs |
옵션에 controlButtons 항목에 배열로 compass를 추가하면 자동으로 딱! 하고 나오게 말이다.
소스분석
controlButtons를 시작으로 검색을 시작했다.
- PANOLENS.Viewer를 생성하면서 옵션 값을 가져온다.
- this.addDefaultControlBar( this.options.controlButtons ) 호출
- addDefaultControlBar는 다시 new PANOLENS.Widget 으로 위젯을 만들고 this.widget.addControlBar() 으로 컨트롤 바를 생성하고 넘겨받은 배열을 통해 addControlButton( buttonName )를 싱행해서 버튼까지 생성한다 .
addControlBar의 bar.dispose에 compassElement 추가
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | bar.dispose = function () { if ( scope.fullscreenElement ) { bar.removeChild( scope.fullscreenElement ); scope.fullscreenElement.dispose(); scope.fullscreenElement = null; } if ( scope.settingElement ) { bar.removeChild( scope.settingElement ); scope.settingElement.dispose(); scope.settingElement = null; } if ( scope.videoElement ) { bar.removeChild( scope.videoElement ); scope.videoElement.dispose(); scope.videoElement = null; } /* * 작성자: silqwer * 설명: 나침판 배치 */ if (scope.compassElement) { bar.removeChild( scope.compassElement ); scope.compassElement.dispose(); scope.compassElement = null; } }; | cs |
기존에 버튼을 추가하는 로직과 동일하게 맞쳐준다.
addControlButton에 compass 추가
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | /** * Add buttons on top of control bar * @param {string} name - The control button name to be created */ PANOLENS.Widget.prototype.addControlButton = function ( name ) { var element; switch( name ) { case 'fullscreen': element = this.createFullscreenButton(); this.fullscreenElement = element; break; case 'setting': element = this.createSettingButton(); this.settingElement = element; break; case 'video': element = this.createVideoControl(); this.videoElement = element; break; /* * 작성자: silqwer * 설명: 나침판 생성 */ case 'compass': element = this.createCompass(); this.compassElement = element; break; default: return; } if ( !element ) { return; } this.barElement.appendChild( element ); }; | cs |
기존에 버튼을 생성해주는 방식과 동일하게 case를 추가하고 this.createCompass()를 만든다.
createCompass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | /* * 작성자: silqwer * 설명: 나침판 생성 */ PANOLENS.Widget.prototype.createCompass = function () { var scope = this; var item = this.createCustomItem( { style : { float : 'left', cursor :'default' }, } ); item.background = this.createCompassBackground(); item.innerDot = this.createCompassInnerDot(); item.innerView = this.createCompassInnerView(); item.outerRing = this.createCompassOuterRing(); item.appendChild( item.background ); item.appendChild( item.innerDot ); item.appendChild( item.innerView ); item.appendChild( item.outerRing ); return item; }; | cs |
createVideoControl를 참고해서 createCompass 작성했다. compass의 경우 4장의 이미지가 필요하고 innerView에 해당하는 이미지가 카메라가 돌아갈 때마다 회전을 해야한다.
createCompassBackground() 추가
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | /* * 작성자: silqwer * 설명: 나침판 백그라운 이미지 요소 */ PANOLENS.Widget.prototype.createCompassBackground = function () { var item; item = this.createCustomItem( { style : { float : 'left', backgroundImage : 'url("' + PANOLENS.DataImage.CompassBackground + '")', cursor: 'default', position: 'absolute' } } ); return item; }; | cs |
여기서 보면 PANOLENS.DataImage.CompassBackground으로 경로를 가져오는 걸 볼 수 있는데 panolens에서 이미지 리소스를 가져올 때 따로 파일로 저장하지 않고 base64로 변환을 해서 스크립트에 포함 시켰다.
이미지 리소스 변환
이미지 파일을 base64로 변환을 시켜주는 사이트( https://www.base64-image.de/ )에서 변환한 뒤에 PANOLENS.DataImage에 추가 시켰다.
createCompassInnerDot ()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | /* * 작성자: silqwer * 설명: 나침판 점 이미지 요소 */ PANOLENS.Widget.prototype.createCompassInnerDot = function () { var item; item = this.createCustomItem( { style : { float : 'left', backgroundImage : 'url("' + PANOLENS.DataImage.CompassInnerDot + '")', cursor: 'default', position: 'absolute' } } ); return item; }; | cs |
createCompassInnerView ()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | /* * 작성자: silqwer * 설명: 나침판 시점 이미지 요소 */ PANOLENS.Widget.prototype.createCompassInnerView = function () { var item; var scope = this; item = this.createCustomItem( { style : { float : 'left', backgroundImage : 'url("' + PANOLENS.DataImage.CompassInnerView + '")', cursor: 'default', position: 'absolute' } } ); scope.dispatchEvent( { type: 'panolens-viewer-handler', method: 'onRotationChange', data: item } ); return item; }; | cs |
dispatchEvent를 통해서 onRotationChange 함수 호출
onRotationChange ()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /* * 작성자: silqwer * 설명: 나침판 회전 함수 */ PANOLENS.Viewer.prototype.onRotationChange = function (element){ var camera = this.camera; this.control.addEventListener('change', function(){ var rotationY = camera.rotation.y; var dy = 0; if ( rotationY < 0 ){ dy = THREE.Math.radToDeg( rotationY + ( 2 * Math.PI ) ); }else{ dy = THREE.Math.radToDeg( rotationY ); } dy = Math.round(dy) * -1; element.style.transform = 'rotate('+ (dy % 360) +'deg)'; }, false); }; | cs |
createCompassOuterRing ()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | /* * 작성자: silqwer * 설명: 나침판 틀 이미지 요소 */ PANOLENS.Widget.prototype.createCompassOuterRing = function () { var item; item = this.createCustomItem( { style : { float : 'left', backgroundImage : 'url("' + PANOLENS.DataImage.CompassOuterRing + '")', cursor: 'default', position: 'absolute' } } ); return item; }; | cs |
결과