;(function($){ //vrbk jQuery.fn.panoramaViewer=function(optUser){ //options const optDef={ src : "", rotationY : 0 }; const opt=$.extend(optDef,optUser); //canvas const myCanvas=$(this); var cv=new Canvas(); function Canvas(){ this._id =myCanvas.attr("id"); this._box =myCanvas.closest(".canvas_box"); this._loader =myCanvas.closest(".canvas_box").find(".canvas_loader"); this._start =myCanvas.closest(".canvas_box").find(".canvas_start"); this._w =this._box.width(); this._h =this._box.height(); } myCanvas.attr({ 'width' : cv._w, 'height' : cv._h }); //three.js var renderer; var scene; var camera; var controls; //group var grpWorld; var grpBase; //loader var loader={}; //timer var timerLoading; //ジャイロセンサー確認 var isGyro=false; if((window.DeviceOrientationEvent)&&('ontouchstart' in window)){ isGyro=true; } //PCなど非ジャイロ if(!isGyro){ setCanvas(); //一応ジャイロ持ちデバイス }else{ //ジャイロ動作確認 var resGyro=false; window.addEventListener("deviceorientation",doGyro,false); function doGyro(){ resGyro=true; window.removeEventListener("deviceorientation",doGyro,false); } //数秒後に判定 setTimeout(function(){ //ジャイロが動いた if(resGyro){ setCanvas(); //ジャイロ持ってるくせに動かなかった }else{ //iOS13+方式ならクリックイベントを要求 if(typeof DeviceOrientationEvent.requestPermission==="function"){ //ユーザアクションを得るための要素を表示 cv._start.show(); cv._start.on("click",function(){ cv._start.hide(); DeviceOrientationEvent.requestPermission().then(res => { //「動作と方向」が許可された if(res==="granted"){ setCanvas(); //「動作と方向」が許可されなかった }else{ isGyro=false; setCanvas(); } }); }); //iOS13+じゃない }else{ //早くアップデートしてもらうのを祈りながら諦める isGyro=false; setCanvas(); } } },300); } /////////////////////////////////////////////////////////////////////////////////////////// // Canvas /////////////////////////////////////////////////////////////////////////////////////////// function setCanvas(){ if(!Detector.webgl){Detector.addGetWebGLMessage();} cv._loader.show(); renderer=new THREE.WebGLRenderer({ canvas : document.querySelector('#'+cv._id), antialias : true, alpha : true }); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(cv._w,cv._h); scene=new THREE.Scene(); grpWorld=new THREE.Group(); grpBase=new THREE.Group(); //スマホなどジャイロセンサーが有効なときはDeviceOrientationControls if(isGyro){ camera=new THREE.PerspectiveCamera(60,cv._w/cv._h,1,20000); camera.position.set(0,0,0.01); camera.lookAt(new THREE.Vector3(0,0,0)); controls=new THREE.DeviceOrientationControls(camera); controls.connect(); controls.update(); //PCなどジャイロセンサーがない場合はOrbitControlsのみ }else{ camera=new THREE.PerspectiveCamera(60,cv._w/cv._h,1,20000); camera.position.set(0,0,0.01); camera.lookAt(new THREE.Vector3(0,0,0)); controls=new THREE.OrbitControls(camera,renderer.domElement); controls.autoRotate =false; controls.enableRotate =true; controls.rotateSpeed =-0.05; controls.enableDamping =true; controls.dampingFactor =0.1; controls.enableZoom =false; controls.enablePan =false; } /////////////////////////////////////////////////////////////////////// // 3Dオブジェクト配置 /////////////////////////////////////////////////////////////////////// //base var gmBase=new THREE.SphereBufferGeometry(1000,60,40); gmBase.scale(-1,1,1); var mtrBase; if(opt.src==""){ mtrBase=new THREE.MeshNormalMaterial(); }else{ loader[opt.src]=false; var texture=new THREE.TextureLoader().load(opt.src,function(){ loader[opt.src]=true; }); texture.minFilter=texture.magFilter=THREE.LinearFilter; texture.mapping=THREE.UVMapping; mtrBase=new THREE.MeshBasicMaterial({ map : texture }); } var base=new THREE.Mesh(gmBase,mtrBase); base.rotation.y=(opt.rotationY*Math.PI/180); grpBase.add(base); grpWorld.add(grpBase); scene.add(grpWorld); //checkLoading var check_sec=500; var check_cnt=0; var check_limit=30000; checkLoading(); function checkLoading(){ var flag_loading=false; Object.keys(loader).forEach(function(key){ if(!loader[key]){ flag_loading=true; } },loader); //読み込み中 if(flag_loading){ timerLoading=setTimeout(function(){ check_cnt+=check_sec; if(check_cnt<check_limit){ checkLoading(); }else{ //エラー処理など alert("読み込みに失敗しました。"); } },check_sec); //読み込み完了 }else{ clearTimeout(timerLoading); cv._loader.hide(); runAnimate(); } } //runAnimate function runAnimate(){ controls.update(); renderer.render(scene,camera); requestAnimationFrame(runAnimate); } } /////////////////////////////////////////////////////////////////////////////////////////// // Window Resize /////////////////////////////////////////////////////////////////////////////////////////// var timerResize=false; $(window).on("resize",function(){ if(timerResize!==false){ clearTimeout(timerResize); } timerResize=setTimeout(function(){ resizeCanvas(); },500); }); function resizeCanvas(){ cv._w=cv._box.width(); cv._h=cv._box.height(); myCanvas.attr({ 'width' : cv._w, 'height' : cv._h }); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(cv._w,cv._h); camera.aspect=cv._w/cv._h; camera.updateProjectionMatrix(); } }; })(jQuery);