view source

JavaScript

document.title = '視力検査';
p1 = document.title + ':画面から5m離れて、輪の空いてる方向のキーを押してください';
p2 = document.title + 'ディスプレイをつかっておうちで視力検査ができます';
p3 = '距離5m離れたところからc(ランドルト環)の向きを判別する能力=視力1.0';
p4 = 'ランドルト環とは 1.5mmのスキマをもつ直径7.5mmサイズの円 円の線の幅1.5mm';

$(function(){
  $demo = $('#demo');
  $img = $('<img>',{src:'c.svg'}).css({width:'100vmin',height:'100vmin',transform:'rotate(90deg)'});
  $demo.append($img);
  $img.css({width:'7.5mm',height:'7.5mm'});
  $p = $('<p>',{id:'p'}).text(p1);
  $q = $('<p>',{id:'q'});
  $demo.append($p);
  $demo.append($q);

  $text = $('<p>').text(p1+'■'+p2+'■'+p3+'■'+p4);
  $demo.after($text);

  $('html,body').animate({scrollTop: 0}, 99);
  const seOK = new Audio('/mp3/ok.mp3');
  const seMiss = new Audio('/mp3/miss.mp3');
  var r = 0;
  var cDef = 9;
  var c = cDef;
  var eyesightAry = [10.0, 8.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.8, 1.5, 1.2, 1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4 ,0.3, 0.2, 0.1, 0.08, 0.05 ];
  
  var d = [
    {
      ar:'→',
      angle:'right',
      deg:0,
      key:39,
    },
    {
      ar:'↓',
      angle:'down',
      deg:90,
      key:40,
    },
    {
      ar:'←',
      angle:'left',
      deg:180,
      key:37,
    },
    {
      ar:'↑',
      angle:'up',
      deg:270,
      key:38,
    },
  ];

  d.forEach(function(v){
    $btn = $('<a>').addClass('btn').text(v.ar);
    rad = v.deg * Math.PI / 180;
    w = 80;
    bottom = 120 - Math.sin(rad) * w;
    left = 120 + Math.cos(rad) * w;
    $btn.css({left:left + 'px',bottom:bottom + 'px'});
    $demo.append($btn);
    console.log($btn);
    $btn.on('click', function(e){
      if(v.key === d[r].key){
        setD(-1);
        seOK.currentTime = 0;
        seOK.play();
      } else {
        setD(1);
        seMiss.currentTime = 0;
        seMiss.play();
      }
    });
  });

  $table = $('<table>');
  $demo.after($table);
  var eyesightAryTable = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.5, 2.0];
  var angleAry = [0, 1, 2, 3];
  eyesightAryTable.forEach(function(v, i){
    $tr = $('<tr>');
    $table.append($tr);
    $th = $('<th>').text(v.toFixed(1));
    $td = $('<td>');
    $tr.append($th);
    var scale = 1/v;
    var size = 7.5 * scale;
    var ary = _.shuffle(angleAry);
    for(var j=0;j<3;j++){
      $td = $('<td>');
      $tr.append($td);
      var $img = $('<img>',{src:'c.svg'}).css({width:size+'mm',height:size+'mm'})
      $img.css({transform:'rotate('+d[ary[j]].deg+'deg)'});
      $td.append($img);
    }
  });

  var scale = 1;
  var setD = function(n=0){
    c+=n;
    if(c<0){
      c=0;
    }
    if(c>eyesightAry.length){
      c=eyesightAry.length;
    }
    var eyesight = eyesightAry[c];
    var scale = 1/eyesight;
    var size = 7.5 * scale;
    r = Math.floor(Math.random()*d.length);
    $img.css({width:size+'mm',height:size+'mm'})
    $img.css({transform:'rotate('+d[r].deg+'deg)'});
    var iw = $img.width();
    console.log(iw);
    $q.text(eyesight.toFixed(1));
    if(eyesight<0.1){
      $q.text(eyesight.toFixed(2));
    }
  }

  setD(0);
  var w = window.innerWidth;
  var h = window.innerHeight;
  $(document).on('click', '#demo', function(e){

    var x = e.clientX;
    var y = e.clientY;
    var key = 13;
    if(x < w * 1/16){
      key = 37;
    }
    if(x > w * 15/16){
      key = 39;
    }
    if(y < h * 1/16){
      key = 38;
    }
    if(y > h * 15/6){
      key = 40;
    }

    if(key >= keys[0] && key <= keys[3]){
      if(key === d[r].key){
        setD(-1);
        seOK.currentTime = 0;
        seOK.play();
      } else {
        setD(1);
        seMiss.currentTime = 0;
        seMiss.play();
      }
    }
  });


  //var keys = [90,88,67,86];//zxcv
  var keys = [37,38,39,40];//←↑→↓
  $(document).on('keydown', function(e){
    console.log(e.keyCode);
    keys.forEach(function(k, i){
      if(e.keyCode === k){
        e.preventDefault();
      }
    });
    if(e.keyCode === 13 || e.keyCode === 32){
      c = cDef;
      setD();
    }
    if(e.keyCode >= keys[0] && e.keyCode <= keys[3]){
      if(e.keyCode === d[r].key){
        setD(-1);
        seOK.currentTime = 0;
        seOK.play();
      } else {
        setD(1);
        seMiss.currentTime = 0;
        seMiss.play();
      }
    }
  });
});

CSS

body{
 /* overflow:hidden;*/
}
#demo{
  position:relative;
  top:0;
  right:0;
  text-align:center;
  user-select:none;
  display:grid;
  align-items:center;
  justify-items:center;
}
#p{
  position:absolute;
  top:0;
  right:0;
  padding:10px;
  font-size:24px;
  color:#999;
}
#q{
  position:absolute;
  bottom:0;
  right:0;
  padding:10px;
  font-size:120px;
  color:#999;
}

table{
  margin:24px auto;
}
th,
td{
  font-size:32px;
  font-weight:bold;
  padding:10mm 2mm;
  width:15mm;
  vertical-align:middle;
  text-align:center;
}
.btn{
  display:inline-block;
  position:absolute;
  width:100px;
  height:100px;
  line-height:100px;
  font-size:24px;
  font-weight:bold;
  vertical-align:middle;
  text-align:center;
  border:1px solid #555;
  border-radius:50%;
}
.btn:hover{
  cursor:pointer;
  background-color:#999;
}

HTML

ページのソースを表示 : Ctrl+U , DevTools : F12

view-source:https://hi0a.com/demo/-js/js-vision-test/

ABOUT

hi0a.com 「ひまアプリ」は無料で遊べるミニゲームや便利ツールを公開しています。

プログラミング言語の動作デモやWEBデザイン、ソースコード、フロントエンド等の開発者のための技術を公開しています。

必要な機能の関数をコピペ利用したり勉強に活用できます。

プログラムの動作サンプル結果は画面上部に出力表示されています。

環境:最新のブラウザ GoogleChrome / Windows / Android / iPhone 等の端末で動作確認しています。

画像素材や音素材は半分自作でフリー素材配布サイトも利用しています。LINK参照。

動く便利なものが好きなだけで技術自体に興味はないのでコードは汚いです。

途中放置や実験状態、仕様変更、API廃止等で動かないページもあります。