2022年5月28日土曜日

GASでドライブの画像を表示する

知恵袋への回答は質問に直接答えたが、画面ロード時に時間がかかりそうなので処理を全体的に変えてみた。


コード.gs
function doGet(e) {
  return HtmlService.createTemplateFromFile("index.html").evaluate().setTitle("タイトル");
}

function GetBase64Image(fileId,param)
{
  var file = DriveApp.getFileById(fileId);
  var blob = file.getBlob();
  var contentType = blob.getContentType();
  var base64 = Utilities.base64Encode(blob.getBytes());
  var imageSrc = "data:" + contentType + ";base64, " + base64;
  return {"name":file.getName(),"id":fileId,"base64":imageSrc,"param":param};
}
index.html
<html>
<head>
  <script>
    <?
      var folder = DriveApp.getFolderById("1MdeTdaYDv9BK9QTaZes5_bTDRpKiLRnA");
      var files = folder.getFiles();
      var list = [];

      while (files.hasNext()) {
        var file = files.next();
        list.push({"id":file.getId(),"name":file.getName(),"url":file.getUrl()});
      }
    ?>
    var list = <?!= JSON.stringify(list) ?>;
  
    function onSelected(event)
    {
      var img = document.getElementById("image")
      img.alt = "Loading....";
      img.src = null;
      var fileId = event.currentTarget.value;
      google.script.run
        .withSuccessHandler( SuccessGetBase64Image )
        .withFailureHandler( Failure )
        .GetBase64Image( fileId, img.id );
    }
    function Failure(){
      alert("失敗");
    }
    function SuccessGetBase64Image(entry)
    {
      document.getElementById(entry.param).alt = entry.name;
      document.getElementById(entry.param).src = entry.base64;
    }

    function onLoad()
    {
      var select = document.getElementById("select");
      select.addEventListener('change', onSelected);
      list.forEach( file => {
        var option = document.createElement("option");
        option.value = file.id;
        option.innerText = file.name;
        select.appendChild(option);
      });
    }
  </script>
</head>
<body onload="onLoad();">

<label for="select">Choose a menu:</label>
<select name="select" id="select">
<option value="">--Please choose an option--</option>
</select>

<p><img src="" height="562" width="750" alt="選択されてません" align="top" id="image">ここに画像表示</p>
</script>

</body>
</html>

2022年5月14日土曜日

JavaScriptで○×ゲームを作ってみた

JavaScriptでcanvasを使って、三目並べの○×ゲームを作ってみた。
canvasで作るよりもTableやButtonで作った方が大分楽。
<!DOCTYPE html>
<html lang="jp">
  <head>
    <meta charset="utf-8">
    <script>
      let canvas;
      let context;
      let Magnification = 100;
      let Finished = false;
      let FirstStrike=true;
      let MarubatsuTable={};
      function drawFrame()
      {
        // #を描画
        context.beginPath();
        context.moveTo(Magnification*0, Magnification*1);
        context.lineTo(Magnification*3, Magnification*1);
        context.moveTo(Magnification*0, Magnification*2);
        context.lineTo(Magnification*3, Magnification*2);
        context.moveTo(Magnification*1, Magnification*0);
        context.lineTo(Magnification*1, Magnification*3);
        context.moveTo(Magnification*2, Magnification*0);
        context.lineTo(Magnification*2, Magnification*3);
        context.stroke();
      }
      function onClick(e)
      {
        if( Finished )
        {
          // ゲームが終わっている場合はリセット
          context.clearRect(0, 0, canvas.width, canvas.height);
          drawFrame();
          MarubatsuTable = {};
          Finished = false;
          FirstStrike = true;
          return;
        }
        // クリックされたセルを検出
        let rect = e.target.getBoundingClientRect();
        let x = Math.floor( (e.clientX - rect.left) / Magnification );
        let y = Math.floor( (e.clientY - rect.top) / Magnification );
        let id = "X"+ x + "Y" + y;
        if( !MarubatsuTable[id]  )
        {
          if( FirstStrike )
          {
            MarubatsuTable[id] = "○";
            context.beginPath();
            context.arc( (x+0.5)*Magnification, (y+0.5)*Magnification, Magnification/3 , 0, 2 * Math.PI, false ) ;
            context.stroke();
          }
          else
          {
            MarubatsuTable[id] = "×";
            context.beginPath();
            context.moveTo((x+0.2)*Magnification, (y+0.2)*Magnification);
            context.lineTo((x+0.8)*Magnification, (y+0.8)*Magnification);
            context.moveTo((x+0.8)*Magnification, (y+0.2)*Magnification);
            context.lineTo((x+0.2)*Magnification, (y+0.8)*Magnification);
            context.stroke();
          }
          // 結果判定
          const decisionTable =
            [ {dicision:["X0Y0","X1Y0","X2Y0"],line:{x0:0,y0:0.5,x1:3,y1:0.5}},
              {dicision:["X0Y1","X1Y1","X2Y1"],line:{x0:0,y0:1.5,x1:3,y1:1.5}},
              {dicision:["X0Y2","X1Y2","X2Y2"],line:{x0:0,y0:2.5,x1:3,y1:2.5}},
              {dicision:["X0Y0","X0Y1","X0Y2"],line:{x0:0.5,y0:0,x1:0.5,y1:3}},
              {dicision:["X1Y0","X1Y1","X1Y2"],line:{x0:1.5,y0:0,x1:1.5,y1:3}},
              {dicision:["X2Y0","X2Y1","X2Y2"],line:{x0:2.5,y0:0,x1:2.5,y1:3}},
              {dicision:["X0Y0","X1Y1","X2Y2"],line:{x0:0,y0:0,x1:3,y1:3}},
              {dicision:["X2Y0","X1Y1","X0Y2"],line:{x0:0,y0:3,x1:3,y1:0}} ];
          decisionTable.forEach((a)=>
          {
            var temp = MarubatsuTable[a.dicision[0]] + MarubatsuTable[a.dicision[1]] + MarubatsuTable[a.dicision[2]];
            if( temp == "○○○" || temp == "×××" )
            {
              context.beginPath();
              context.moveTo( a.line.x0*Magnification, a.line.y0*Magnification);
              context.lineTo( a.line.x1*Magnification, a.line.y1*Magnification);
              context.stroke();
              Finished = true;
            }
            if( Object.keys(MarubatsuTable).length == 9 )
            {
              Finished = true;
            }
          });
          // 先攻後攻変更
          FirstStrike = !FirstStrike;
        }
      }
      function onLoad(){
        canvas = document.getElementById('sampleCanvas');
        context = canvas.getContext('2d');
        if ( ! canvas || ! context ) {
          return false;
        }
        canvas.style.width = Magnification * 3+"px";
        canvas.style.height = Magnification * 3+"px";
        canvas.width = Magnification * 3;
        canvas.height = Magnification * 3;

        drawFrame();
        canvas.addEventListener('click', onClick, false);
      }
    </script>
  </head>
  <body onload="onLoad();">
    <canvas id="sampleCanvas"></canvas>
  </body>
</html>

おまけ:Canvas縛りがない場合はもっと簡単

<!DOCTYPE html>
<html lang="jp">
  <head>
    <meta charset="utf-8">
    <script>
      let FirstStrike=true;
      let Finished = false;
      let Count = 0;
      function onClick(event){
        // 勝敗決定後のクリックは結果クリア
        if( Finished )
        {
          for (const td of event.currentTarget.querySelectorAll("td")) {
            td.innerText = " ";
            td.style.backgroundColor = "";
          }
          FirstStrike=true;
          Finished = false;
          Count = 0;
          return;
        }

        // クリックされたセルに"○"/"×"を記録
        if(event.target.tagName=="TD")
        {
          if( event.target.innerText==" " ){
            event.target.innerText = FirstStrike?"○":"×";
            FirstStrike =! FirstStrike;
            Count++;

            // 結果判定
            const decisionTable =
              [ ["00","01","02"],
                ["01","11","12"],
                ["02","21","22"],
                ["00","10","20"],
                ["01","11","21"],
                ["02","12","22"],
                ["00","11","22"],
                ["20","11","02"] ];
            decisionTable.forEach((a)=>
            {
              var temp = document.getElementById(a[0]).innerText+document.getElementById(a[1]).innerText+document.getElementById(a[2]).innerText;
              if( temp == "○○○" || temp == "×××" )
              {
                Finished = true;
                document.getElementById(a[0]).style.backgroundColor = "lightblue"; 
                document.getElementById(a[1]).style.backgroundColor = "lightblue"; 
                document.getElementById(a[2]).style.backgroundColor = "lightblue"; 
              } 
            });
            if( Count >=9 )
            {
              Finished = true;
            }
          }
        }
      }
    </script>
  </head>
  <body>
    <table onclick="onClick(event);" border="1">
      <tr><td id="00"> </td><td id="01"> </td><td id="02"> </td></tr>
      <tr><td id="10"> </td><td id="11"> </td><td id="12"> </td></tr>
      <tr><td id="20"> </td><td id="21"> </td><td id="22"> </td></tr>
    </table>
  </body>
</html>