💬
ローカルサーバでスマートフォンブラウザから端末の向きを検出する
結論から
httpsサーバじゃないといけない
カメラを利用するのにも必要だったので、以前の記事を参考に
$ openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
で、鍵作ったあと
$ http-server -S -C cert.pem
or
server.js
const fs = require('fs')
const express = require('express');
const app = express();
const https = require('https');
const options = {
key: fs.readFileSync('./key.pem'),
cert: fs.readFileSync('./cert.pem')
};
const server = https.createServer(options, app);
const PORT = process.env.PORT || 3000;
// ルート
app.get('/' , function(req, res){
res.sendFile(__dirname+'/public/index.html');
});
// サーバの立ち上げ
server.listen(PORT, () => {
console.log('listening on https://localhost:' + PORT);
});
動作した環境
- iOS15.6.1(iPhone8)
- safari
- chrome
- Android12(Pixel 6a)
- chrome
- Node.js v16.15.1
- express v4.18.1
スマートフォンブラウザで向き取得するための参考サイト
ここらへんだけを見るとすぐ使えそうに思えたけども、コードコピペしてもローカルサーバだとこんなエラー
CodePenやOpenProcessingなんかだとうまくいく
あと、Netlifyにアップしたらうまくできたし、たぶんGitHub pagesでもできると思う
が、今回動作させたい環境でインターネット使えるか怪しかったので、ローカルサーバで動作させてみたかった
注意点
ローカルサーバ関係ないが、スマフォの向き情報を取得するための許可をもらうための処理の
//. ユーザーに「許可」を求めるダイアログを表示
DeviceOrientationEvent.requestPermission().then(function (response) {
if (response === 'granted') {
// 許可
}
}).catch(function (e) {
alert(e);
console.error(e);
});
この処理は、ボタンクリックした後に処理します
サンプルコード集
p5jsを使って画面に傾きをテキスト表示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>スマフォ向き取得テスト</title>
</head>
<body>
<button id="btn">クリック</button>
<ul>
<li id="rx"></li>
<li id="ry"></li>
<li id="rz"></li>
</ul>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.2/p5.min.js"></script>
<script>
function setup() {
frameRate(10);
select('#btn').mousePressed(() => {
if (window.DeviceOrientationEvent) {
//. ユーザーに「許可」を求めるダイアログを表示
DeviceOrientationEvent.requestPermission().then(function (response) {
if (response === 'granted') {
// 許可
select('#btn').hide();
}
}).catch(function (e) {
alert(e);
console.error(e);
});
}
});
}
function draw() {
const rx = round(rotationX * 100) / 100;
const ry = round(rotationY * 100) / 100;
const rz = round(rotationZ * 100) / 100;
select('#rx').html(rx);
select('#ry').html(ry);
select('#rz').html(rz);
}
</script>
</body>
</html>
p5jsだと許可もらったあとは rotationX
で扱えます
その他は、こちら
socket.ioでサーバに共有
サーバ側(Node.js)
npm i socket.io express
const fs = require('fs')
const express = require('express');
const app = express();
const path = require('path');
const https = require('https');
const options = {
key: fs.readFileSync('./key.pem'),
cert: fs.readFileSync('./cert.pem')
};
const server = https.createServer(options, app);
const io = require('socket.io')(server);
const PORT = process.env.PORT || 3000;
// app.get('/', express.static(path.join(__dirname, '/public/index.html')));
app.get('/' , function(req, res){
res.sendFile(__dirname+'/public/index.html');
});
// app.use('/public', express.static(path.join(__dirname, '/public')));
io.on('connection',function(socket){
socket.on('rotation',function(rot){
console.log('rx:' + rot.x + ', ry:'+rot.y+', rz:'+rot.z);
});
});
// サーバの立ち上げ
server.listen(PORT, () => {
console.log('listening on https://localhost:' + PORT);
});
クライアント側(html,js)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
html, body {
margin: 0;
padding: 0;
}
canvas {
display: block;
}
</style>
<title>スマフォ向き取得テスト</title>
</head>
<body>
<script src="/socket.io/socket.io.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.2/p5.min.js"></script>
<script>
const socket = io();
let rots = {};
let textArea;
function setup() {
if (DeviceOrientationEvent && DeviceOrientationEvent.requestPermission) {
const btn = createButton('クリックして許可', () => {
//. ユーザーに「許可」を求めるダイアログを表示
DeviceOrientationEvent.requestPermission().then(function (response) {
if (response === 'granted') {
// 許可
btn.hide();
}
}).catch(function (e) {
alert(e);
console.error(e);
});
});
}
// createCanvas(windowWidth, windowHeight);
textArea = createElement('textArea');
textArea.position(10, 10);
textArea.style('width:95%;height:95vh');
socket.on('rotation', (rot) => {
// console.log(rot);
rots[rot.id] = rot;
});
}
function draw() {
textArea.html(JSON.stringify(rots, null, ' '));
}
function deviceMoved() {
const rx = round(rotationX * 100) / 100;
const ry = round(rotationY * 100) / 100;
const rz = round(rotationZ * 100) / 100;
socket.emit('rotation', {
x: rx,
y: ry,
z: rz
});
}
</script>
</body>
</html>
p5jsだと、デバイス端末が動いたときだけ送るってこともできます
Discussion