JavaScript/HTML5おぼえがき

JavaScriptJavaScript/HTMLサイトマップホーム

デバイスの情報取得

スマートフォン/タブレットのGPS、ジャイロセンサー、マイク、カメラなどのデバイス情報が取得出来て、色々な処理が出来ます。

デバイスの向き情報を取得する   戻る

デバイスのz・x・y軸の向き情報が取得できます。 方位(z軸)は、相対方位と絶対方位(北向き)があり、絶対方位はios(iPhone/iPad)の場合はdeviceorientationのイベントでwebkitCompassHeading値を取得します。
それ以外(Android)の場合はdeviceorientationabsoluteのイベントでalpha値を取得します。
またiosの場合は向きデータへアクセス許可を取得するために requestPermission() を通して明示的に利用者による同意を要求します。
iOS13以降は DeviceOrientationEvent.requestPermission() を呼んでユーザーが「許可」を押さないとセンサーが使えません。
deviceorientation / deviceorientationabsolute は ページロード直後には動かず、ボタンなどをタップしてから DeviceOrientationEvent.requestPermission() を呼ぶ必要があります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ジャイロセンサー</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<h1>ジャイロセンサ</h1>
<input type="button" id="permit" value="デバイス情報取得許可"/>
<div id="out"></div>
<p>ジャイロセンサの(Gyo Sernsor)取得値<br>
alpha(z)は画面に対して垂直な軸の角度(0~360度)<br>
beta(x)は横軸の角度(-180~180度)<br>
gammer(y)は縦軸の角度(-90~90度)</p>
<script>
<!--
const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);
window.onload = function() {
  if (!isIOS) {
    permit.style.display = "none" ;
    window.addEventListener("deviceorientationabsolute", handleOrientation, true);
  }
  dsp(0,45,0) ;
}
// ユーザーの操作(ボタンタップなど)で呼び出す関数
document.getElementById('permit').addEventListener('click', () => {
  // 許可をリクエスト
  if (typeof DeviceOrientationEvent.requestPermission === 'function') {
    DeviceOrientationEvent.requestPermission()
      .then(permissionState => {
        if (permissionState === 'granted') { window.addEventListener("deviceorientation", handleOrientation, true); }
      })
      .catch(console.error);
  } else {
    // requestPermission がない古いブラウザの場合
    window.addEventListener("deviceorientation", handleOrientation, true);
  }
  permit.style.display = "none" ;
});
function handleOrientation(e){
  a = e.alpha ;
  b = e.beta;   // X軸(端末の左右)周りの回転角度
  g = e.gamma; // Y軸(端末の上下)周りの回転角度
  if ( isIOS ) { a = 360-e.webkitCompassHeading; } 
  dsp(a,b,g) ;
}
function dsp(a,b,g) {
  var output = document.getElementById("out");
  output.innerHTML = "Gyro Sensor<br />";
  output.innerHTML += "alpha" + " = " + a + "<br />";
  output.innerHTML += "beta" + " = " + b + "<br />";
  output.innerHTML += "gamma" + " = " + g + "<br /><br />";
}
</script>
</body>
</html>             

位置情報取得   戻る

GPS(地球上の現在位置を測定するためのシステム)より位置情報(緯度・経度)を取得します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>位置情報の取得</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<script>
  z_latitude  = "" ;
  z_longitude = "" ;
  z_altitude = "" ;
  z_accuracy = "" ;
  z_altitudeAccuracy ="" ;
  z_heading = "" ;
  z_speed = "" ;
  z_timestamp = "" ;
  z_msg ="" ;
  if (navigator.geolocation) {
//  navigator.geolocation.getCurrentPosition(successCallback, errorCallback,{ enableHighAccuracy:true,timeout :5000 });
    navigator.geolocation.watchPosition     (successCallback, errorCallback);
  }
  else {z_msg ="Geo Location APIに対応していません" ; dsp() ;alert("\nこのブラウザでは動作しません。\nHTML5サポートプラウザをご利用下さい。"); }

function successCallback(position) {
  z_latitude  = position.coords.latitude ;  //緯度
  z_longitude =  position.coords.longitude ;   //経度
  z_altitude = position.coords.altitude ;
  z_accuracy = position.coords.accuracy ;
  z_altitudeAccuracy = position.coords.altitudeAccuracy ;
  z_heading = position.coords.heading ;      //方角
  z_speed = position.coords.speed * 3.6 ;          //速度
  z_timestamp = position.timestamp ;
 time = position.timestamp;
  dateObj = new Date(time);
  yy = dateObj.getFullYear();
  mo = dateObj.getMonth() + 1;
  dd = dateObj.getDate();
  hh = dateObj.getHours();
  mm = dateObj.getMinutes();
  ss = dateObj.getSeconds();
  ms = dateObj.getMilliseconds();
  z_timestamp = hh+":"+mm+":"+ss+"."+ms ;
  z_msg ="" ;
  dsp() ;
}
function dsp() {
  tx  = "緯度(度): " + z_latitude + "<br>";
  tx += "経度(度): " + z_longitude + "<br>";
  tx += "高度(m): " + z_altitude + "<br>";
  tx += "緯度・経度の<br>";
  tx += "誤差(度): " + z_accuracy + "<br>";
  tx += "高度の誤差(m): " + z_altitudeAccuracy + "<br>";
  tx += "方角(度): " + z_heading + "<br>";
  tx += "速度(Km/h): " + z_speed + "<br>";
  tx += "時間(時分秒): " + z_timestamp + "<br>";
  tx += "状態: " + z_msg + "<br><br>";
  document.getElementById("show_result").innerHTML = tx;
  msg.innerHTML ="" ;
}
function errorCallback(error) {
  var z_msg = "予期しないエラー:"+error ;
  switch(error) {
    case 1 : z_msg = "位置情報の利用が許可されていません" ; break;
    case 2 : z_msg = "デバイスの位置が判定できません" ; break;
    case 3 : z_msg = "タイムアウトしました" ; break;
  }
  dsp() ;
}
</script> 
</head>
<body>
<h1>位置情報の取得</h1>
<p id="msg">しばらくお待ちください。</p>
<div id="show_result"></div>
</body> 
</html>

マイクの操作   戻る

navigator.mediaDevices.getUserMediaでマイクから音声を取り込んで、WevAudioAPIの処理で音の加工ができます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>音声チェック</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<h1>音響チェック</h1>
<p><br>
入力音(マイクなど)の波形とスペクトル(音を構成する周波数とその強度の分布)分析グラフを表示します。スペクトル分析範囲は0~22028Hzです。</p>
<canvas id = "c1" width="320" height="160"></canvas><br>
<canvas id = "c2" width="320" height="160"></canvas>
<form name="form">
Level:<input type="range" min="0" max="1" step="0.1" name="level" value="0.5" onchange="srt()">
</form>
<script type="text/javascript">
  canvas1        = document.getElementById("c1"); // キャンバスの設定
  canvasContext1 = canvas1.getContext('2d');
  canvas2        = document.getElementById("c2"); // キャンバスの設定
  canvasContext2 = canvas2.getContext('2d');

  var handleSuccess = function(stream) {
  window.AudioContext = window.AudioContext || window.webkitAudioContext; // AudioContextクラスインスタンス生成(Web互換指定)
  context = new AudioContext();
  input = context.createMediaStreamSource(stream) ;
  analyser = context.createAnalyser();    // Analyserノードのインスタンスの作成
  analyser.fftSize = 2048;                // 標準値  context.createGain = context.createGain || context.createGainNode;
  gain = context.createGain();            // gainノードのインスタンスの作成
  gain.gain.value = parseFloat(form.level.value); // レベルの設定
  input.connect(gain);           // analyserノードに接続する
//analyser.connect(gain);  // gainノードに接続する
  gain.connect(analyser);      // サウンド出力ノードに接続する
  analyser.connect(context.destination);      // サウンド出力ノードに接続する
  drawwave1() ;
  drawwave3() ;
}
srt() ;
function srt(){
  navigator.mediaDevices.getUserMedia({ audio: true, video: false })
      .then(handleSuccess,errorFunc) ;
}
function cngg() { stp() ; srt() ; }
function cng() {}
function errorFunc(error) { alert("error"); }
function stp() { context.close() }   // 音源の再生停止
function errorFunc(error) { alert("入力音源がありません"); }
function drawwave1() {
    intervalid1 = window.setInterval(function() {
        var times = new Uint8Array(analyser.fftSize);  // Array sizeは1024 (FFTサイズの半分の値)
        analyser.getByteTimeDomainData(times);
        canvasContext1.fillStyle = "#333333" ;
        canvasContext1.fillRect(0, 0, canvas1.width, canvas1.height); // キャンバスのクリア
        canvasContext1.beginPath();        // 描画の開始
        canvasContext1.strokeStyle ="#ffffff" ;
        for (var i = 0, len = times.length; i < len; i++) {
            var x = (i / len) * canvas1.width;
            var y = (1 - (times[i] / 255)) * canvas1.height;
            if (i === 0) { canvasContext1.moveTo(x, y); } else { canvasContext1.lineTo(x, y); }
        }
        canvasContext1.stroke();           // 描画
    }, 50);                                // 1秒間に50回
}
function drawwave3() {
    intervalid2 = window.setInterval(function() {
        var spectrums = new Uint8Array(analyser.frequencyBinCount);  // Array sizeは1024 (FFTサイズの半分の値)
        analyser.getByteFrequencyData(spectrums);
        canvasContext2.fillStyle = "#333333" ;
        canvasContext2.fillRect(0, 0, canvas2.width, canvas2.height); //キャンバスのクリア
        k = Math.round( 5000 * canvas2.width / 22050) ;
        canvasContext2.fillStyle = "#ffffff" ;
        canvasContext2.strokeRect(0,0,canvas2.width,canvas2.height);
        canvasContext2.font = "11pt Arial";
        canvasContext2.fillStyle = "#ffffff";
        jj = 0 ;
        for ( var j = 0 ; j < canvas2.width ; j = j + k ) {
          canvasContext2.strokeRect(0,0,j,canvas2.height ) ;
          canvasContext2.fillText  ( jj*5 + "kHz",j-40, 15); jj++ ;
        }
        canvasContext2.beginPath();       // 描画開始
        for (var i = 0, len = spectrums.length; i < len; i++) {
          var value = spectrums[i]
          var percent = value /256 ;
          var height = canvas2.height * percent ;
          var offset = canvas2.height - height - 1 ;
          var barWidth = canvas2.width / analyser.frequencyBinCount ;
          var hue = i / analyser.frequencyBinCount * 360 ;
          canvasContext2.fillStyle = "hsl(" + hue + ",100%,50%)" ;
          canvasContext2.fillStyle = "#ffffff" ;
          canvasContext2.fillRect( i * barWidth,offset,barWidth,height) ;
        }
    }, 10);                               // 1秒間に10回
}
</script>
</body>
</html>

カメラの操作   戻る

navigator.mediaDevices.getUserMediaでカメラの操作ができます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>カメラの応用</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style></style>
</head>
<body>
<h1>カメラの応用</h1>
<p>スマートフォンカメラの応用で、鏡、虫メガネで使えます。</P><br>
<div id="contents" style="text-align: center;">
<video id="camera"></video>
<br>
<button type="button" onclick="cng_camera()">カメラの切替</button>
<button type="button" onclick="video.pause();">停止</button>
<button type="button" onclick="video.play() ;">開始</button>
<p>カメラの切替でフロントとリアが無い場合はエラーになりますので、再度切替ボタンを押してください。</P>
</div>
<script>
// カメラのデフォルト設定
var CONSTRAINTS = {
  audio: false,
  video: {
    width: 320,
    height: 240,
    facingMode: null  // どのカメラを利用するか
    // facingModeには最終的に以下のいずれかの値を入れる
    //   facingMode: "user"                    // フロントカメラを利用する
    //   facingMode: { exact: "environment" }  // リアカメラを利用する
  }
}
// 現在のStream
var curSTREAM = null;

window.onload = function() {
  video = document.querySelector("#camera");
  useFront = true;     // フロントカメラ:true, バックカメラ:false
  // 縦横の解像度を調整
//adjustCameraSize(video, 640, 480);
  // カメラと同期開始
  syncCamera(video, useFront);
  useFront = !useFront;         // boolean値を反転
} ;
// 切り替えボタン押下
function cng_camera() {
    syncCamera(video, useFront);
    useFront = !useFront;      // boolean値を反転
}
// カメラを<video>と同期
function syncCamera(video, is_front=true){
  // 前後カメラの設定
  CONSTRAINTS.video.facingMode = (is_front)?  "user":{ exact: "environment" };
  // すでにカメラと接続していたら停止
  if( curSTREAM !== null ){
    curSTREAM.getVideoTracks().forEach( function (camera) { camera.stop() ; });
  }
  // カメラと接続する
  navigator.mediaDevices.getUserMedia(CONSTRAINTS)
    .then( function(stream) {
      curSTREAM = stream;   // 前後の切り替え用に保持
      // <video>とStremaを接続
      video.srcObject = stream;
      video.onloadedmetadata = (e) => {
        video.play();
      };
    })
    .catch( function(err) {
//   console.log(`${err.name}: ${err.message}`);
      alert("カメラとの接続時にエラーが発生しました");
    });
}
//解像度に合わせて<video>サイズを調整する
function adjustCameraSize(video, longside, shortside){
  if( window.innerWidth < window.innerHeight ){
    CONSTRAINTS.video.width  = shortside;
    CONSTRAINTS.video.height = longside;
    video.style.width  = shortside;
    video.style.height = longside;
  }
}
</script>
</body>
</html>

JavaScriptJavaScript/HTMLサイトマップホーム