Shinkai005

V1

2022/04/23阅读:32主题:红绯

canvas学习第二天啦

canvas学习第二天

留的坑

  • [ ] vscode 怎么写方法不自动添加 ()

    • [ ] 我还想让他把必须参数自己加.
    • [ ] 找个插件看看,没有试着自己实现个

图像组合

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue.js</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <link rel="stylesheet" href="style.css" />
    <script src="vue.js"></script>
  </head>
  <body onload="draw()">
    <div id="vue-app"></div>
    <canvas id="canvas1" width="300" height="300"></canvas>
    <canvas id="canvas2" width="300" height="300"></canvas>
    <canvas id="canvas3" width="300" height="300"></canvas>
    <canvas id="canvas4" width="300" height="300"></canvas>
    <canvas id="canvas5" width="300" height="300"></canvas>
    <canvas id="canvas6" width="300" height="300"></canvas>
    <canvas id="canvas7" width="300" height="300"></canvas>
    <canvas id="canvas8" width="300" height="300">
      你这浏览器不支持这玩意啊
    </canvas>
    <script src="app.js"></script>
    <script>
      //创建画布,返回画笔画布
      const createCanvas = function (id{
        /** @type {HTMLCanvasElement} */
        const canvas = document.getElementById(id)
        let ctx = ''
        if (canvas.getContext) {
          ctx = canvas.getContext('2d')
        }

        return { ctx, canvas }
      }

      function draw({
        // 让vscode可以显示canvas智能提示
        /**
         * 四个画布来并行比较 
         */

        //想在优化可以用循环传个数组进去.
        const { ctx: ctx1, canvas: canvas1 } = createCanvas('canvas1')
        const { ctx: ctx2, canvas: canvas2 } = createCanvas('canvas2')
        const { ctx: ctx3, canvas: canvas3 } = createCanvas('canvas3')
        const { ctx: ctx4, canvas: canvas4 } = createCanvas('canvas4')
        const { ctx: ctx5, canvas: canvas5 } = createCanvas('canvas5')
        const { ctx: ctx6, canvas: canvas6 } = createCanvas('canvas6')
        const { ctx: ctx7, canvas: canvas7 } = createCanvas('canvas7')
        const { ctx: ctx8, canvas: canvas8 } = createCanvas('canvas8')

        //操作第一个
        ctx1.beginPath()
        ctx1.globalCompositeOperation = 'source-over'

        ctx1.fillStyle = 'red'
        ctx1.fillRect(5050100100)
        
        ctx1.fillStyle = 'green'
        ctx1.arc(150150500Math.PI * 2)
        ctx1.fill()
        /**
         * 我这块用的和老师讲法不一样的
         * 我看的mdn的解释.
         * 等最后我全部解释下.
         * 并不是简单的换source和destination就是换上下.
         */

        //操作第二个
        ctx2.beginPath()
        ctx2.fillStyle = 'red'
        ctx2.fillRect(5050100100)
        ctx2.globalCompositeOperation = 'destination-over'

        ctx2.fillStyle = 'green'
        ctx2.arc(150150500Math.PI * 2)
        ctx2.fill()

        // 操作第三个
        ctx3.beginPath()
        ctx3.fillStyle = 'red'
        ctx3.fillRect(5050100100)
        ctx3.globalCompositeOperation = 'source-atop'

        ctx3.fillStyle = 'green'
        ctx3.arc(150150500Math.PI * 2)
        ctx3.fill()

        // 操作第四个
        ctx4.beginPath()
        ctx4.fillStyle = 'red'
        ctx4.fillRect(5050100100)
        ctx4.globalCompositeOperation = 'destination-atop'

        ctx4.fillStyle = 'green'
        ctx4.arc(150150500Math.PI * 2)
        ctx4.fill()

        // 操作第五个
        ctx5.beginPath()
        ctx5.fillStyle = 'red'
        ctx5.fillRect(5050100100)
        ctx5.globalCompositeOperation = 'source-in'

        ctx5.fillStyle = 'green'
        ctx5.arc(150150500Math.PI * 2)
        ctx5.fill()
        // 操作第六个
        ctx6.beginPath()
        ctx6.fillStyle = 'red'
        ctx6.fillRect(5050100100)
        ctx6.globalCompositeOperation = 'destination-in'

        ctx6.fillStyle = 'green'
        ctx6.arc(150150500Math.PI * 2)
        ctx6.fill()
        // 操作第七个
        ctx7.beginPath()
        ctx7.fillStyle = 'red'
        ctx7.fillRect(5050100100)
        ctx7.globalCompositeOperation = 'source-out'

        ctx7.fillStyle = 'green'
        ctx7.arc(150150500Math.PI * 2)
        ctx7.fill()
        // 操作第八个
        ctx8.beginPath()
        ctx8.fillStyle = 'red'
        ctx8.fillRect(5050100100)
        ctx8.globalCompositeOperation = 'destination-out'

        ctx8.fillStyle = 'green'
        ctx8.arc(150150500Math.PI * 2)
        ctx8.fill()
      }
      /**
       * 所有的解释
       * 所有的都是先生成 "红色"  -> 声明 -> "绿色"
       * 1357全是source,2468全是destination
       * 
       * 大家观察1357,全部是绿在上.  
       * 看2468 红在上. 
       * => 结论1. source开头的 颜色会是最后一个.之后的都在原图案上.
       * => 推论1  destination开头的 颜色会是第一个,之后的都在原图案下.
       * 
       * source-over  
       * source-atop
       * source-in
       * source-out
        */

    
</script>
  </body>
</html>


我已经优化了一下代码了在优化狠点.其实上面的可读性就蛮不错了.小改一下

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue.js</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <link rel="stylesheet" href="style.css" />
    <script src="vue.js"></script>
  </head>
  <body onload="draw()">
    <div id="vue-app"></div>
    <!-- 别惹我惹我我就扔vue里vue-for生成了 -->
    <canvas id="canvas1" width="300" height="300"></canvas>
    <canvas id="canvas2" width="300" height="300"></canvas>
    <canvas id="canvas3" width="300" height="300"></canvas>
    <canvas id="canvas4" width="300" height="300"></canvas>
    <canvas id="canvas5" width="300" height="300"></canvas>
    <canvas id="canvas6" width="300" height="300"></canvas>
    <canvas id="canvas7" width="300" height="300"></canvas>
    <canvas id="canvas8" width="300" height="300">
      你这浏览器不支持这玩意啊
    </canvas>
    <script src="app.js"></script>
    <script>
      //创建画布,返回画笔画布
      const createCanvas = function (id,operation{
        /** @type {HTMLCanvasElement} */
        const canvas = document.getElementById(id)
        let ctx = ''
        if (canvas.getContext) {
          ctx = canvas.getContext('2d')
        }
        ctx.beginPath()
        ctx.fillStyle = 'red'
        ctx.fillRect(5050100100)
        ctx.globalCompositeOperation = operation
        ctx.fillStyle = 'green'
        ctx.arc(150150500Math.PI * 2)
        ctx.fill()

        return { ctx, canvas }
      }

      function draw({
        // 让vscode可以显示canvas智能提示
        /**
         * 四个画布来并行比较 
         */

        //想在优化可以用循环传个数组进去.
        const { ctx: ctx1, canvas: canvas1 } = createCanvas('canvas1','source-over')
        const { ctx: ctx2, canvas: canvas2 } = createCanvas('canvas2','destination-over')
        const { ctx: ctx3, canvas: canvas3 } = createCanvas('canvas3','source-atop')
        const { ctx: ctx4, canvas: canvas4 } = createCanvas('canvas4','destination-atop')
        const { ctx: ctx5, canvas: canvas5 } = createCanvas('canvas5','source-in')
        const { ctx: ctx6, canvas: canvas6 } = createCanvas('canvas6','destination-in')
        const { ctx: ctx7, canvas: canvas7 } = createCanvas('canvas7','source-out')
        const { ctx: ctx8, canvas: canvas8 } = createCanvas('canvas8','destination-out')
    
</script>
  </body>
</html>


我还可以优化

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue.js</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <link rel="stylesheet" href="style.css" />
    <script src="vue.js"></script>
  </head>
  <body onload="draw()">
    <div id="vue-app"></div>
    <!-- 别惹我惹我我就扔vue里vue-for生成了 -->
    <canvas id="canvas1" width="300" height="300"></canvas>
    <canvas id="canvas2" width="300" height="300"></canvas>
    <canvas id="canvas3" width="300" height="300"></canvas>
    <canvas id="canvas4" width="300" height="300"></canvas>
    <canvas id="canvas5" width="300" height="300"></canvas>
    <canvas id="canvas6" width="300" height="300"></canvas>
    <canvas id="canvas7" width="300" height="300"></canvas>
    <canvas id="canvas8" width="300" height="300">
      你这浏览器不支持这玩意啊
    </canvas>
    <script src="app.js"></script>
    <script>
      //创建画布,返回画笔画布
      const createCanvas = function (ids,operations{
        /** @type {HTMLCanvasElement} */
        if(ids.length!==operations.length)return "给爷滚,数据都给错了"
        for (let i = 0; i < ids.length; i++) {
        const canvas = document.getElementById(ids[i])
        let ctx = ''
        if (canvas.getContext) {
          ctx = canvas.getContext('2d')
        }
        ctx.beginPath()
        ctx.fillStyle = 'red'
        ctx.fillRect(5050100100)
        ctx.globalCompositeOperation = operations[i];
        ctx.fillStyle = 'green'
        ctx.arc(150150500Math.PI * 2)
        ctx.fill()
        }
      }

      function draw({
        const arr=[];
        let str=''
        for (let i = 1; i <= 8; i++) {
           str = `canvas${i}`
           arr.push(str)
        }
        console.log(arr);
        createCanvas(arr,['source-over','destination-over','source-atop','destination-atop','source-in','destination-in','source-out','destination-out'])
      }
    
</script>
  </body>
</html>


完了好烦看着div也想改了,不说了dom操作一波.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue.js</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <link rel="stylesheet" href="style.css" />
    <script src="vue.js"></script>
  </head> 
  <body onload="createContains('canvas',8),draw()">
    <div id="vue-app"></div>
    <div id="canvasBox"></div>
    <script src="app.js"></script>
    <script>
      const createCanvas = function (ids, operations{
        /** @type {HTMLCanvasElement} */
        if (ids.length !== operations.length) return '给爷滚,数据都给错了'
        for (let i = 0; i < ids.length; i++) {
          const canvas = document.getElementById(ids[i])
          let ctx = ''
          if (canvas.getContext) {
            ctx = canvas.getContext('2d')
          }
          ctx.beginPath()
          ctx.fillStyle = 'red'
          ctx.fillRect(5050100100)
          ctx.globalCompositeOperation = operations[i]
          ctx.fillStyle = 'green'
          ctx.arc(150150500Math.PI * 2)
          ctx.fill()
        }
      }

      function draw({
        const arr = []
        let str = ''
        for (let i = 1; i <= 8; i++) {
          str = `canvas${i}`
          arr.push(str)
        }
        // console.log(arr)
        createCanvas(arr, [
          'source-over',
          'destination-over',
          'source-atop',
          'destination-atop',
          'source-in',
          'destination-in',
          'source-out',
          'destination-out',
        ])
      }

      function createContains(element, number{
        console.log('执行这里')
        let html = ''
        for (let i = 1; i <= number; i++) {
          html += `<${element} id="canvas${i}" width="300" height="300"></${element}>`
        }
        document.getElementById('canvasBox').innerHTML = html
      }
    
</script>
  </body>
</html>


VScode-html检查插件-htmlhint

{
  //标签名必须小写
  "tagname-lowercase"true,
  //属性名必须小写
  "attr-lowercase"true,
  //属性值必须放在双引号中
  "attr-value-double-quotes"true,
  //属性值一定不可为空
  "attr-value-not-empty"false,
  //属性值一定不可重复
  "attr-no-duplication"true,
  //Doctype必须是 HTML 文档的第一行
  "doctype-first"true,
  //标签必须成对
  "tag-pair"true,
  //标签必须自封闭
  "tag-self-close"true,
  //特殊字符必须
  "spec-char-escape"true,
  //ID 属性必须唯一
  "id-unique"true,
  //src 属性一定不可为空
  "src-not-empty"true,
  //title 属性必须出现在标签中
  "title-require"false,
  //img 标签必须包含 alt 属性
  "alt-require"true,
  //Doctype 必须是 HTML5
  "doctype-html5"true,
  //ID 和 Class 的命名规则必须统一
  "id-class-value""dash",
  //不该使用样式标签
  "style-disabled"true,
  //不该使用行内样式
  "inline-style-disabled"false,
  //不该使用行内脚本
  "inline-script-disabled"false,
  //空格和制表符一定不可混合在行前
  "space-tab-mixed-disabled""space2",
  //ID 和 Class 一定不可使用广告关键词
  "id-class-ad-disabled"true,
  //href 必须是绝对路径或者相对路径
  "href-abs-or-rel"false,
  //属性值一定不可使用不安全字符
  "attr-unsafe-chars"true,
  //script 标签不该使用在头部
  "head-script-disabled"false
}



最初


{
  "tagname-lowercase"true,
  "attr-lowercase"true,
  "attr-value-double-quotes"true,
  "attr-value-not-empty"false,
  "attr-no-duplication"true,
  "doctype-first"true,
  "tag-pair"true,
  "tag-self-close"true,
  "spec-char-escape"true,
  "id-unique"true,
  "src-not-empty"true,
  "title-require"false,
  "alt-require"true,
  "doctype-html5"true,
  "id-class-value""dash",
  "style-disabled"true,
  "inline-style-disabled"true,
  "inline-script-disabled"true,
  "space-tab-mixed-disabled""space4",
  "id-class-ad-disabled"true,
  "href-abs-or-rel"false,
  "attr-unsafe-chars"true,
  "head-script-disabled"true
}

矩形直线运动+反弹效果

代码如下

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue.js</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <link rel="stylesheet" href="style.css" />
    <script src="vue.js"></script>
  </head>
  <body onload="draw()">
    <div id="vue-app"></div>
    <canvas id="canvas" width="400" height="300">
      你这浏览器不支持这玩意啊
    </canvas>
    <script src="app.js"></script>
    <script>
      function draw() {
        // 让vscode可以显示canvas智能提示
        /** @type {HTMLCanvasElement} */
        const canvas = document.getElementById('canvas')
        if (canvas.getContext) {
          const ctx = canvas.getContext('2d')
          /**
           * canvas 动画原理
           * 1.绘制图像
           * 2.清除图像
           * 3.更新位置
           * 4.重绘
           */
          let x = 0,
            y = 0,
            width = 10,
            height = 10
          ctx.fillRect(x, y, width, height)
          // x+=20
          // y+=20
          // ctx.fillRect(x, y, width, height)


          //速度
          let speedX = 20
          let speedY = 20

          setInterval(function(){
            // 2.清除图像
            ctx.clearRect(0, 0, canvas.width, canvas.height)
            // 3.更新位置
            x += speedX
            if (x > canvas.width - width) {
              // rebound
              speedX *= -1
            } else if(x<0) {
              speedX *= -1
            }

            y += speedY
            if (y > canvas.height - height) {
              // rebound
              speedY *= -1
            } else if (y<0) {
              speedY *= -1
            }

            // 4.绘制图像
            ctx.fillRect(x, y, width, height)
          
          },60)
          //添加弹回动画

          
          }
        }
      
    </script>
  </body>
</html>

想要实现多个怎么操作? 下面代码千万别运行,会笑死你.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue.js</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <link rel="stylesheet" href="style.css" />
    <script src="vue.js"></script>
  </head>
  <body onload="draw()">
    <div id="vue-app"></div>
    <canvas id="canvas" width="500" height="500">
      你这浏览器不支持这玩意啊
    </canvas>
    <script src="app.js"></script>
    <script>
      function draw({
        // 让vscode可以显示canvas智能提示
        /** @type {HTMLCanvasElement} */
        const canvas = document.getElementById('canvas')
        if (canvas.getContext) {
          const ctx = canvas.getContext('2d')
          /**
           * canvas 动画原理
           * 1.绘制图像
           * 2.清除图像
           * 3.更新位置
           * 4.重绘
           */

          let width = 10,
            height = 10

          // 写个函数自动生成xy
          function createAxis(elements, num{
            for (let i = 0; i < num; i++) {
              //随机生成位置
              elements[i] = {
                //Math.floor(Math.random() * (max - min + 1) ) + min;
                //10-290
                xMath.floor(Math.random() * (canvas.width-width -width + 1) + width),
                yMath.floor(Math.random() * (canvas.height-width-height + 1) + height),
              }
            }
          }
          const elements = []
          createAxis(elements, 2)
          console.log('old', elements)
          //渲染最初图像
          renderEle(elements)
          //绘制图像
          function renderEle(elements{
            const colors = ['blue','yellow','green','lightgreen','lightblue''darkred']
            for (let i = 0; i < elements.length; i++) {
              ctx.fillStyle = colors[Math.floor(Math.random()*(colors.length-1+1)+1)]
              ctx.fillRect(elements[i].x, elements[i].y, width, height)
            }
          }

          //速度
          // let speedX = 10,
          //   speedX1 = 15
          // let speedY = 10,
          //   speedY1 = 15
          randomSpeed(elements,4)
          function randomSpeed(elements,max{
            for (let i = 0; i < elements.length; i++) {
              //随机生成速度
              elements[i].speedX = Math.floor((Math.random()*max)+1);
              elements[i].speedY = Math.floor((Math.random()*max)+1);
            }
          }
          // console.log(elements)
          setInterval(function ({
            // 2.清除图像
            // ctx.clearRect(0, 0, canvas.width, canvas.height)
            // 3.更新位置
            for (let i = 0; i < elements.length; i++) {
              elements[i].speedX = determineXPosition(
                elements[i].x,
                elements[i].speedX
              )
              elements[i].x += elements[i].speedX

              elements[i].speedY = determineYPosition(
                elements[i].y,
                elements[i].speedY
              )
              elements[i].y += elements[i].speedY

            }
            // console.log('new',elements)
            function determineYPosition(axis, orientation{
              if (axis > canvas.height - height) {
                // rebound
                orientation *= -1
              } else if (axis < 0) {
                orientation *= -1
              }
              return orientation
            }
            function determineXPosition(axis, orientation{
              if (axis > canvas.width - width) {
                // rebound
                orientation *= -1
              } else if (axis < 0) {
                orientation *= -1
              }
              return orientation
            }

            // 4.绘制图像
            renderEle(elements)
          }, 30)
        }
      }
    
</script>
  </body>
</html>


小bug

image-20220422093912071
image-20220422093912071

这个后面不可以写(),因为并不是立即执行的

好看点的+优化啦

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue.js</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <link rel="stylesheet" href="style.css" />
    <script src="vue.js"></script>
  </head>
  <body onload="draw()">
    <div id="vue-app"></div>
    <canvas id="canvas" width="500" height="500">
      你这浏览器不支持这玩意啊
    </canvas>
    <script src="app.js"></script>
    <script>
      function draw({
        // 让vscode可以显示canvas智能提示
        /** @type {HTMLCanvasElement} */
        const canvas = document.getElementById('canvas')
        if (canvas.getContext) {
          const ctx = canvas.getContext('2d')
          /**
           * canvas 动画原理
           * 1.绘制图像
           * 2.清除图像
           * 3.更新位置
           * 4.重绘
           */


          //矩形小球宽高不变
          let width = 10,height = 10
          //创建小球
          const elements = []
          createAxis(elements, 8)
          renderEle(elements)
          randomSpeed(elements, 4)
          // 随机生成xy
          function createAxis(elements, num{
            for (let i = 0; i < num; i++) {
              //随机生成位置
              elements[i] = {
                //Math.floor(Math.random() * (max - min + 1) ) + min;
                //10-290
                xMath.floor(
                  Math.random() * (canvas.width - width - width + 1) + width
                ),
                yMath.floor(
                  Math.random() * (canvas.height - width - height + 1) + height
                ),
              }
            }
          }
          // 随机生成速度
          function randomSpeed(elements, max{
            for (let i = 0; i < elements.length; i++) {
              elements[i].speedX = Math.floor(Math.random() * max + 1)
              elements[i].speedY = Math.floor(Math.random() * max + 1)
            }
          }
          //绘制图像
          function renderEle(elements{
            const colors = [
              'blue',
              'yellow',
              'green',
              'lightgreen',
              'lightblue',
            ]
            for (let i = 0; i < elements.length; i++) {
              ctx.fillStyle =
                colors[Math.floor(Math.random() * (colors.length - 1 + 1) + 1)]
              ctx.fillRect(elements[i].x, elements[i].y, width, height)
            }
          }
          // 开始移动
          /* setInterval(function () {
            // 2.清除图像
            ctx.clearRect(0, 0, canvas.width, canvas.height)
            // 3.更新位置
            for (let i = 0; i < elements.length; i++) {
              elements[i].speedX = determineXPosition(
                elements[i].x,
                elements[i].speedX
              )
              elements[i].x += elements[i].speedX

              elements[i].speedY = determineYPosition(
                elements[i].y,
                elements[i].speedY
              )
              elements[i].y += elements[i].speedY
            }
            // 判断y坐标是否超越边界
            function determineYPosition(axis, orientation) {
              if (axis > canvas.height - height) {
                // rebound
                orientation *= -1
              } else if (axis < 0) {
                orientation *= -1
              }
              return orientation
            }
            // 判断x坐标是否超越边界
            function determineXPosition(axis, orientation) {
              if (axis > canvas.width - width) {
                // rebound
                orientation *= -1
              } else if (axis < 0) {
                orientation *= -1
              }
              return orientation
            }

            // 4.绘制图像
            renderEle(elements)
          }, 30) */

          function optimize({
            // 2.清除图像
            ctx.clearRect(00, canvas.width, canvas.height)
            // 3.更新位置
            for (let i = 0; i < elements.length; i++) {
              elements[i].speedX = determineXPosition(
                elements[i].x,
                elements[i].speedX
              )
              elements[i].x += elements[i].speedX

              elements[i].speedY = determineYPosition(
                elements[i].y,
                elements[i].speedY
              )
              elements[i].y += elements[i].speedY
            }
            // 判断y坐标是否超越边界
            function determineYPosition(axis, orientation{
              if (axis > canvas.height - height) {
                // rebound
                orientation *= -1
              } else if (axis < 0) {
                orientation *= -1
              }
              return orientation
            }
            // 判断x坐标是否超越边界
            function determineXPosition(axis, orientation{
              if (axis > canvas.width - width) {
                // rebound
                orientation *= -1
              } else if (axis < 0) {
                orientation *= -1
              }
              return orientation
            }

            // 4.绘制图像
            renderEle(elements)
            //递归调用
            window.requestAnimationFrame(optimize);
        }
        optimize()
      }
    }
    
</script>
  </body>
</html>


圆形小球动画

面向对象版本的

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue.js</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <link rel="stylesheet" href="style.css" />
    <script src="vue.js"></script>
  </head>
  <body onload="draw()">
    <div id="vue-app"></div>
    <canvas id="canvas" width="400" height="300">
      你这浏览器不支持这玩意啊
    </canvas>
    <script src="app.js"></script>
    <script>
      function draw({
        // 让vscode可以显示canvas智能提示
        /** @type {HTMLCanvasElement} */
        const canvas = document.getElementById('canvas')
        if (canvas.getContext) {
          const ctx = canvas.getContext('2d')
          // 圆形碰撞反弹
          function Ball(x, y, r, speedX, speedY, color{
            // 设置属性
            this.x = x
            this.y = y
            this.r = r
            this.speedX = speedX
            this.speedY = speedY
            this.color = color
            // 设置方法
            this.draw = function ({
              ctx.beginPath()
              ctx.fillStyle = this.color
              ctx.arc(this.x, this.y, this.r, 0Math.PI * 2)
              ctx.fill()
            }
            this.move = function ({
              this.x += this.speedX
              if (this.x > canvas.width - this.r) {
                this.speedX *= -1
              } else if (this.x < this.r) {
                this.speedX *= -1
              }
              this.y += this.speedY
              if (this.y > canvas.height - this.r) {
                this.speedY *= -1
              } else if (this.y < this.r) {
                this.speedY *= -1
              }
            }
          }
          const ball = new Ball(1001005022'blue')
          //1. 绘制图像
          ball.draw()
          //2. 删除图像 3. 更新图像 4. 绘制图像
          begin()
          function begin({
            ctx.clearRect(00, canvas.width, canvas.height)
            ball.draw()
            ball.move()
            window.requestAnimationFrame(begin)
          }
        }
      }
    
</script>
  </body>
</html>


水平全景滚动

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue.js</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <link rel="stylesheet" href="style.css" />
    <script src="vue.js"></script>
  </head>
  <body onload="draw()">
    <div id="vue-app"></div>
    <canvas id="canvas" width="320" height="565">
      你这浏览器不支持这玩意啊
    </canvas>
    <script src="app.js"></script>
    <script>
      function draw({
        // 让vscode可以显示canvas智能提示
        /** @type {HTMLCanvasElement} */
        const canvas = document.getElementById('canvas')
        if (canvas.getContext) {
          const ctx = canvas.getContext('2d')
          let y = 0
          function bgMove({
            ctx.save()
            ctx.clearRect(00, canvas.width, canvas.height)
            ctx.translate(0, y)
            //两幅图片的原因是俩图片收尾相接,然后向左,然后到最左边瞬间重置是看不出来的.
            ctx.drawImage(bgImage, 00)
            ctx.drawImage(bgImage, 0, -canvas.height)

            // 判断x的偏移量
            y++
            if (y >= canvas.height) {
              y = 0
            }
            ctx.restore()
            window.requestAnimationFrame(bgMove)
          }
          const bgImage = new Image()
          bgImage.src = 'background.png'
          bgImage.onload = function ({
            bgMove()
          }
        }
      }
    
</script>
  </body>
</html>


restore&save

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue.js</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <link rel="stylesheet" href="style.css" />
    <script src="vue.js"></script>
  </head>
  <body onload="draw()">
    <div id="vue-app"></div>
    <canvas id="canvas" width="800" height="600">
      你这浏览器不支持这玩意啊
    </canvas>
    <script src="app.js"></script>
    <script>
      function draw({
        // 让vscode可以显示canvas智能提示
        /** @type {HTMLCanvasElement} */
        const canvas = document.getElementById('canvas')
        if (canvas.getContext) {
          const ctx = canvas.getContext('2d')
          /**
           * 看看save和restore做了什么
          */

          //第一个矩形
          ctx.beginPath()
          ctx.fillStyle = 'blue'
          ctx.save()
          ctx.fillRect(100,100,150,150);
          ctx.closePath()
          //第二个矩形
          ctx.beginPath()
          ctx.fillStyle = 'red'
          ctx.save()
          ctx.fillRect(100,400,150,150);
          ctx.closePath()
          //第三个矩形
          ctx.beginPath()
          ctx.restore()
          ctx.fillRect(400,100,150,150)
          ctx.closePath()
          //第四个矩形
          ctx.beginPath()
          ctx.restore()
          ctx.fillRect(400,400,150,150);
          ctx.closePath()
        }
      }
    
</script>
  </body>
</html>


只需要记得 save使用栈数据结构存的, 后进先出

矩形碰撞

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Vue.js</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <link rel="stylesheet" href="style.css" />
    <script src="vue.js"></script>
  </head>
  <body onload="draw()">
    <div id="vue-app"></div>
    <canvas id="canvas" width="800" height="600">
      你这浏览器不支持这玩意啊
    </canvas>
    <script src="app.js"></script>
    <script>
      function draw({
        // 让vscode可以显示canvas智能提示
        /** @type {HTMLCanvasElement} */
        const canvas = document.getElementById('canvas');
        if (canvas.getContext) {
          const ctx = canvas.getContext('2d');
          /**
           * 用面向对象方式写
           */

          // Rectangle类
          function Rect(x, y, width, height, color, speed{
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
            this.color = color;
            this.speed = speed;
            // 绘制方法
            Rect.prototype.draw = function ({
              ctx.beginPath();
              ctx.fillStyle = this.color;
              ctx.fillRect(this.x, this.y, this.width, this.height);
              ctx.closePath();
            };
            //移动
            Rect.prototype.move = function ({
              this.x += this.speed;
              if (this.x >= canvas.width - this.width) {
                this.speed *= -1;
              } else if (this.x < 0) {
                this.speed *= -1;
              }
              // this.y += this.speed;
              // if (this.x >= canvas.height - this.height) {
              //   this.speed *= -1;
              // } else if (this.x < 0) {
              //   this.speed *= -1;
              // }
            };
          }
          const rect1 = new Rect(0100100100'red'4);
          const rect2 = new Rect(700100100100'blue'-2);
          rect1.draw();
          rect2.draw();
          function animate({
            ctx.clearRect(00, canvas.width, canvas.height);
            rect1.move();
            rect2.move();
            rect1.draw();
            rect2.draw();
            //判断是否碰撞
            if (isRectHit(rect1, rect2)) {
              rect1.speed *= -1;
              rect2.speed *= -1;
            }
            //递归调用
            window.requestAnimationFrame(animate);
          }
          function isRectHit(rect1, rect2{
            // 获取矩形的最小x和最大x
            const min1 = rect1.x;
            const min2 = rect2.x;
            const max1 = rect1.x + rect1.width;
            const max2 = rect2.x + rect2.width;
            const min3 = Math.max(min1, min2);
            const max3 = Math.min(max1, max2);
            if (min3 < max3) {
              return true;
            } else {
              return false;
            }
          }
          animate();
        }
      }
    
</script>
  </body>
</html>


分类:

前端

标签:

JavaScript

作者介绍

Shinkai005
V1

公众号:深海笔记Shinkai