iT邦幫忙

0

Day 53、54 (JS_API)

  • 分享至 

  • xImage
  •  

1. Canvas-1 (Lab_Canvas > Lab_Canvas > Lab_Canvas.html)

畫畫
http://www.effectgames.com/demos/canvascycle/
https://www.w3schools.com/graphics/canvas_coordinates.asp
https://www.w3schools.com/graphics/game_sound.asp

刷上藍色漸層背景增添質感
以下這段程式,若非不是一開始就畫出,就必須設定
globalCompositeOperation,否則,預設會蓋掉先前的內容
https://www.w3schools.com/tags/playcanvas.asp?filename=playcanvas_globalcompop&preval=source-over

    ctx.globalCompositeOperation = "destination-over";
    var grd = ctx.createLinearGradient(0, 0, 0, 50);
    grd.addColorStop(0, "white");
    grd.addColorStop(1, "#0000EE");
    ctx.fillStyle = grd;
    ctx.fillRect(0, 0, 200, 50);

畫線

    var canvas = document.getElementById("myCanvas2");
    var ctx = canvas.getContext("2d");
    ctx.moveTo(0, 0);
    ctx.lineTo(100, 50);
    ctx.moveTo(100, 50);
    ctx.lineTo(200, 0);
    ctx.stroke(); //定案

塗滿

    var canvas = document.getElementById("myCanvas3");
    var ctx = canvas.getContext("2d");
    ctx.moveTo(0, 0);
    ctx.lineTo(100, 50);
    ctx.lineTo(200, 0);
    ctx.fill();

劃十字

    // width="400px" height="300px"
    ctx.moveTo(0, 150);
    ctx.lineTo(400, 150);
    ctx.stroke();
    ctx.moveTo(200, 0);
    ctx.lineTo(200, 300);
    ctx.stroke();

用來對齊文字(自己的口絕:起始點在中間 => 相反)

    ctx.font = "64px Arial";
    ctx.textBaseline = "top"; //top ,middle ,botton
    ctx.textAlign = "left"; //對齊起點 ; left, center, right
    ctx.fillText("hello", 200, 150);

https://ithelp.ithome.com.tw/upload/images/20210818/20137684Dc1tynt5pP.jpg

還原 讓後面的設計不受此處影響

    let bakFillStyle = ctx.fillStyle;
    ctx.font = "8px Arial italic";
    ctx.textBaseline = "top";
    ctx.textAlign = "center";
    ctx.fillStyle = "#FFFFFF";
    ctx.fillText("Powered by HTML5", 100, 35);
    ctx.fillStyle = bakFillStyle; //

2. Canvas-2 (Lab_Canvas > Lab_Canvas_Part2 > Lab_Image.html)

arc畫圓圈圈
arc(120, 100, 80, 0, 2 * Math.PI [0~2PI] ,true[是否逆時針:預設False])

        ctx.arc(120, 100, 80, 0, 2 * Math.PI, true);
        ctx.stroke(); //1.輸出

        // ctx.fill(); //2.填滿

        ctx.clip(); //3.裁切畫布
        ctx.drawImage(imgRabbit, 0, 0); //3.放圖片

做一個重複的
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage

        var ctxSmall = canvasSmall.getContext("2d");

        // (canvasLab, 來源[0, 0, 240, 200], 目的[0, 0, 120, 100])
        ctxSmall.drawImage(canvasLab, 0, 0, 240, 200, 0, 0, 120, 100);

圖片灰階
原理:紅綠藍相同,為灰色(數字大小只差在深淺)
把紅綠藍抓出來,取得平均數,作為灰階的漸層

        var imgData = ctxSmall.getImageData(0, 0, 120, 100);
        console.log(imgData);
        var data = imgData.data;

        //data.length 48000 ; 一個畫素4位元 ; 0, 4, ,8 ,12
        for (var i = 0; i < data.length; i += 4) {
          var avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
          data[i] = avg; // red ; 4
          data[i + 1] = avg; // green ; 5
          data[i + 2] = avg; // blue  ; 6
        }
        ctxSmall.putImageData(imgData, 0, 0);

畫布轉圖片 toDataURL
如同 img src="data:image/png;base64,iVBORw0KGgoAAAANSUhE............."

       imgView.src = canvasSmall.toDataURL("image/png");

3. Canvas-3 (Lab_Canvas > Demo > demo.html)

撞球

      var canvas = document.getElementById("surface");
      var ctx = canvas.getContext("2d");

      setInterval(function () {
        //撞到牆壁反彈
        //下
        if (ball.y + ball.r >= surface.height) {
          ball.vy = Math.abs(ball.vy) * -1;
        }
        //上
        if (ball.y + ball.r <= 0) {
          ball.vy = Math.abs(ball.vy);
        }
        //右
        if (ball.x + ball.r >= surface.width) {
          ball.vx = Math.abs(ball.vx) * -1;
        }
        //左
        if (ball.x + ball.r <= 0) {
          ball.vx = Math.abs(ball.vx);
        }

        //擦掉
        ctx.fillStyle = "white";
        ctx.fillRect(0, 0, surface.width, surface.height);

        //球移動 20 22 24 26 28...
        ball.x += ball.vx;
        ball.y += ball.vy;

        //不會重複畫 (重新計算路徑)
        ctx.beginPath();
        ctx.arc(ball.x, ball.y, ball.r, 0, Math.PI * 2); //畫球
        ctx.stroke();
      }, 1000 / 70);

下堂課接續

(2)啟用keyboard事件

    var key_flag = "none";

    document.onkeydown = function (e) {
        console.log(e);
        console.log(e.keyCode); //37左 38上 39右 40下
        switch (e.keyCode) {
          case 37:
            // 按左 提早轉向(*-1)
            // abs回傳一個數字的絕對值
            // ball.vx = Math.abs(ball.vx) * -1;
            // 雖然可以執行但是難維護

            //維護用
            key_flag = "left";
            break;

          case 38:
            key_flag = "up";
            break;

          case 39:
            key_flag = "right";
            break;

          case 40:
            key_flag = "down";
            break;
        }
   };

(3)撞到方向(上),按下按鈕要反彈(相反:下)

        if (ball.y + ball.r >= surface.height || key_flag == "up") {
          ball.vy = Math.abs(ball.vy) * -1;
        }
        // 上

        if (ball.y + ball.r <= 0 || key_flag == "down") {
          ball.vy = Math.abs(ball.vy);
        }

        // 右
        // if (ball.x + ball.r >= surface.width) {
        //   ball.vx = Math.abs(ball.vx) * -1;
        // }


        if (ball.x + ball.r >= surface.width || key_flag == "left") {
          ball.vx = Math.abs(ball.vx) * -1;
        }

        // 左
        if (ball.x + ball.r <= 0 || key_flag == "right") {
          ball.vx = Math.abs(ball.vx);
        }

(4)按完恢復原狀

        key_flag = "none";

4.canvas 對 focus 無效 所以 無反應

鍵盤按下時 事件
canvas 對 focus 無效 所以 無反應

    <canvas id="surface" height="400" width="600" style="border: 1px solid gray">
    </canvas>

      surface.onkeydown = function (e) {
         console.log(e);
       };

修改為document

      document.onkeydown = function (e) {
        console.log(e);
      };

5.不要用setinterval偵測是否按下按鍵,請使用事件onkeydown
不管設定多少時間偵測一次,都會有遺漏

      setInterval(function () {
      }, 1000); 1s


      document.onkeydown = function (e) {
        console.log(e);
        console.log(e.keyCode); //37左 38上 39右 40下
        switch (e.keyCode) {
          case 37:
            key_flag = "left";
            break;

          case 38:
            key_flag = "up";
            break;

          case 39:
            key_flag = "right";
            break;

          case 40:
            key_flag = "down";
            break;
        }
     };

6.關於圓周率、sin、cos...三角函數 詳見JS_API影片03(死亡)


7.ChartJS - 直線圖 (Lab_ChartJS_01 > lab.html)
https://www.chartjs.org/

(1)安裝 / 引用 Chart.js

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0/dist/Chart.min.js"></script>

(2)建立畫布、畫筆

        <canvas id="chartCanvas"></canvas>

        var cityPopulationList = [3800, 2570, 2374, 2106, 1859];
        var cityPopulationList2030 = [3719, 3606, 3075, 2344, 1988];

        var cityNameList = ["Tokyo", "Delhi", "Shanghai", "Sao Paulo", "New York"];

(3)畫畫
https://www.chartjs.org/docs/latest/api/interfaces/ChartTypeRegistry.html

        var populationChart = new Chart(ctx, {
          type: "bar", //"bar"物件
          data: {
            labels: cityNameList, // X 軸項目清單
            //datasets 陣列
            datasets: [
              {
                label: "population",
                data: cityPopulationList, //陣列
                // 著色:
                backgroundColor: "rgba(14,72,100,0.2)",
                borderColor: "rgba(14,72,100,1.0)",
                borderWidth: 1,
              },
              {
                label: "population",
                data: cityPopulationList, //陣列
                // 著色:
                backgroundColor: "rgba(14,72,100,0.5)",
                borderColor: "rgba(14,72,100,0.5)",
                borderWidth: 10,
              },
            ],
          },
        });


7.ChartJS - 直線圖 (Lab_ChartJS_02 > lab.html)

     type: "line"

8.ChartJS - pie圓餅 + doughnut甜甜圈 (Lab_ChartJS_03 > lab.html)

     type: "doughnut"

        var pieChart = new Chart(ctx, {
          type: "doughnut", //"pie"
          data: {
            labels: cityNameList,
            datasets: [
              {
                data: cityPopulationList,
                backgroundColor: ["#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9", "#c45850"],
              },
              //第二圈
              {
                data: cityPopulationList2030,
                backgroundColor: ["#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9", "#c45850"],
              },
            ],
          },
          options: {
            title: {
              display: true,
              text: "Population",
            },
            cutoutPercentage: 30, //粗細
          },
        });

9.ChartJS - scatter散佈圖 + bubble氣泡圖 (Lab_ChartJS_04 > lab.html)

     var dataList = [];
        for (let i = 1; i <= 10; i++) {
          let dataItem = {
            x: Math.floor(Math.random() * 100),
            y: Math.floor(Math.random() * 100),
            r: Math.floor(Math.random() * 20), //半徑
          };
          dataList.push(dataItem);
        }
        // console.log(JSON.stringify(dataList));

        var ctx = document.getElementById("chartCanvas");
        var labChart = new Chart(ctx, {
          type: "bubble", // bubble使用到r ; scatter
          data: {
            datasets: [
              {
                label: "random X-Y",
                data: dataList,
                backgroundColor: "rgba(14,72,100,0.2)",
                borderColor: "rgba(14,72,100,1.0)",
                borderWidth: 1,
              },
            ],
          },
        });

10.three.js (Lab_Three.js > lab.html)
https://threejs.org/

(1)引用

   <script src="js/three.min.js"></script>

(2)製作畫布

    <div id="cinema"></div>

(3)畫布 加入 canvas 元素

      const renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight);
      document.getElementById("cinema").appendChild(renderer.domElement);

(4)建立 Scene (場景)

      var scene = new THREE.Scene();
      scene.background = new THREE.Color(0x000000);

(5)建立 Camera (照相機)
相機參數

https://www.script-tutorials.com/webgl-with-three-js-lesson-9/

      const camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 0.1, 10000);
      camera.position.set(0, 0, 500);
      scene.add(camera);

(6)拍照
https://www.script-tutorials.com/webgl-with-three-js-lesson-9/

      const camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 0.1, 10000);
      camera.position.set(0, 0, 500); //距離遠近
      scene.add(camera);

      var sphere = new THREE.SphereGeometry(200, 50, 50);
      var material = new THREE.MeshNormalMaterial();
      var mesh = new THREE.Mesh(sphere, material);
      mesh.position.z = -300;
      scene.add(mesh);

(7)照片放到畫布上
Render(輸出/算圖/描繪/渲染) 影像,呼叫 Renderer 描繪出作品:

      renderer.render(scene, camera); 

(8)包地球外皮,材質下載

      var loader = new THREE.TextureLoader();
      loader.load("images/earth.jpg", function (texture) {
        mesh.material = new THREE.MeshBasicMaterial({ map: texture, overdraw: 0.5 });
        renderer.render(scene, camera);
      });

(9)轉動

自己轉轉 似setInterval/setTimeout每秒動

      requestAnimationFrame(doRender);
      function doRender() {
        try {
          mesh.rotation.y += 0.01;
        } catch (e) {}
        renderer.render(scene, camera);
        requestAnimationFrame(doRender);
      }

鍵盤轉轉

      document.onkeydown = function (e) {
        switch (event.keyCode) {
          case 38: // up
            mesh.rotation.x -= 0.2;
            break;
          case 40: // down
            mesh.rotation.x += 0.2;
            break;
          case 37: // left
            mesh.rotation.y -= 0.2;
            break;
          case 39: // right
            mesh.rotation.y += 0.2;
            break;
        }
        event.preventDefault();
      };

滑鼠轉轉

      var lastMove = {
        x: window.innerWidth / 2,
        y: window.innerHeight / 2,
      };

      var isMouseDown = false;

      document.onmousedown = function () {
        isMouseDown = true;
        lastMove.x = event.clientX;
        lastMove.y = event.clientY;
      };

      document.onmouseup = function () {
        isMouseDown = false;
      };

      document.onmousemove = function () {
        if (isMouseDown == false) {
          return;
        }
        var moveX = event.clientX - lastMove.x;
        var moveY = event.clientY - lastMove.y;

        mesh.rotation.y += moveX * 0.0002;
        mesh.rotation.x += moveY * 0.0002;

        lastMove.x = e.clientX;
        lastMove.y = e.clientY;
      };

11.WebCam - 拍照 (WebCam > lab.html)

(1)引用webcam

    <script src="webcam.min.js"></script>

(2)WebCam 啟動程式

    Webcam.set({
        width: 320,
        height: 240,
        image_format: 'jpeg',
        jpeg_quality: 90
    });
    Webcam.attach('#cameraDiv');

(3)照片怎麼存

        //製作畫布
        var viewContext = viewPort.getContext('2d')

        Webcam.snap(function (snappedImage) {
            // console.log(snappedImage);
            let bufferImage = new Image();
            bufferImage.src = snappedImage;
            bufferImage.onload = function () {
              viewContext.drawImage(bufferImage, 0, 0, 320, 240);

            }

        });  // End of Webcam.snap

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言