Day 53、54 (JS_API)

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/[email protected]/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

<<:  第39天~

>>:  在 Debian 11 上直接用 Fcitx 5 与呒虾米

【Day 16】for 回圈

在写程序时,我们可能需要重复执行某些程序,总不可能每行程序一直复制贴上,这时候就会用到我们的回圈(l...

Day23 vue.js 自订 api (fastapi)

延续昨日 今天来讲讲我们要做的新功能 叫做功能测试 这个功能的目的是 我们公司的大佬希望能够把 测试...

爬虫怎麽爬 从零开始的爬虫自学 DAY21 python网路爬虫开爬-3我已满18岁(cookie)

前言 各位早安,书接上回我们已经能够成功抓到整页的文章标题了,今天我们要来破解 PTT 某些版上的是...

【Day28】Git 版本控制 - GitBook 简介

今天来介绍一个酷东西:GitBook 图片取自 GitBook 官网 GitBook GitBook...

成为 Scrum Master:更基本的部分

前言 接着昨天分享的话题,针对成为 Scrum Master 的经历与想法再进行补充。 大家从标题「...