用vite命令搭个react移动端项目,实现canvas碰撞效果(按需导入antd-mobile,pxtorem适配)

前言

最近看见大家都在卷react源码,突然就心慌了。但是自己的操作水平还有待提高,现在看源码也需要循序渐进的,打算还是从写代码慢慢理解功能再去看源码。所以就尝试使用vite这个构建工具进行尝试构建一个react项目。因为是第一次使用,也是看着文档来操作的。下面展示一下效果。

效果

录屏软件生成gif的找到一个只能一次免费后面收费的,效果有点模糊。mac电脑,如果有比较好的,各位大佬推荐一下哈!!!

Vizard录屏_20220718_13_51_ (1).gif 放个截图

bigbig.png

实现步骤

一,项目搭建

  • 1,按照vite文档进行操作。
    • 目前require在vite项目中不能使用,导入用import
    • 兼容性注意:Vite 需要 Node.js 版本 >= 14.18.0。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。
  yarn create vite #yarn安装
  npm create vite@latest # npm安装
  • 2,按照上面步骤之后,我选择了npm安装,选择react搭建

    • 如图所示:npmpng.png
    • 其中vanilla js可以翻译为原生js,vite搭建vanilla运行地址
    • preact是React 的轻量级替代方案,体积仅有 3kB,并且拥有与 React 相同的 API。vite搭建preact运行地址
    • svelte中,应用程序由一个或多个 组件(components)  构成。组件是一个可重用的、自包含的代码块,它将 HTML、CSS 和 JavaScript 代码封装在一起并写入 .svelte 后缀名的文件中,vite搭建svelte运行地址
    • Lit 是一个简单的框架,用于构建快速、轻量级的 Web 组件。它提供反应状态、作用域样式和一个小巧、快速且富有表现力的声明性模板系统,vite搭建lit运行地址
  • 3,运行。cd到对应目录,然后查看package.json脚本显示dev

    yarn dev # yarn安装
    npm run dev # npm安装
    
  • 4,适配移动端

    • 安装插件
     yarn add postcss-pxtorem -D # yarn安装
     npm install postcss-pxtorem -D # npm安装
    
    • 在vite.config.js中进行配置,将+ 后面的添加到相应的位置
    import { defineConfig } from 'vite'  // defineConfig对vite进行配置
    import react from '@vitejs/plugin-react'
    
    + import postcss from 'postcss-pxtorem'
    //注意,这里和之前的不一样,将defineConfig({})中对像按照配置dev环境一样改成了箭头函数
    export default defineConfig((command, mode) => {
      return {
        plugins: [
          react(),
        ],
        // css模块适配移动端
       + css: {
          postcss: {
            plugins: [
              postcss({ // 把px单位换算成rem单位
                rootValue: 16, // 换算基数,默认100,这样的话把根标签的字体规定为1rem
                //为50px,这样就可以从设计稿上量出多少个px直接在代码中写多上px了。
                propList: ['*'], //属性的选择器,*表示通用
                unitPrecision: 5, // 允许REM单位增长到的十进制数字,小数点后保留的位数。
                exclude: /(node_module)/,  // 默认false,可以(reg)利用正则表达
                //式 排除某些文件夹的方法
                  })
                ]
              }
            }
          }
    })
    
  • 5,antd-mobile按需引入

    • 安装antd-mobile
    yarn add antd-mobile # yarn安装
    npm install yarn add antd-mobile # npm安装
    
    • 插件配置
    import { defineConfig } from 'vite'  // defineConfig对vite进行配置
    import react from '@vitejs/plugin-react'
    
    + import postcss from 'postcss-pxtorem'
    + import vitePluginImp from 'vite-plugin-imp' 
    
    export default defineConfig((command, mode) => {
       return {
         plugins: [
           react(),
           // antd按需引入样式
           + vitePluginImp({
              libList: [
                   {
                     libName: 'antd-mobile',
                     libDirectory: 'es/components',
                     style(name) {
                       return `antd-mobile/es/components/${name}/${name}.css`
                     },
                   },
                 ]
           })
         ],
     })
    
    
  • 6, 配置别名

import { defineConfig } from 'vite'  // defineConfig对vite进行配置
import react from '@vitejs/plugin-react'
import postcss from 'postcss-pxtorem'
import vitePluginImp from 'vite-plugin-imp' //vitePluginImp 是将 antd-mobile 进行按需加载


export default defineConfig((command, mode) => {
 return {
   plugins: [
     react(),
     // antd按需引入样式
     vitePluginImp({
       libList: [
         {
           libName: 'antd-mobile',
           libDirectory: 'es/components',
           style(name) {
             return `antd-mobile/es/components/${name}/${name}.css`
           },
         },
       ]
     })
   ],
   // 配置别名
   + resolve: {
     extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'],
     alias: {
       '@': '/src'
     }
   },
   css: {
     postcss: {
       plugins: [
         postcss({ // 把px单位换算成rem单位
           rootValue: 16, // 换算基数,默认100,这样的话把根标签的字体规定为1rem
           //为50px,这样就可以从设计稿上量出多少个px直接在代码中写多上px了。
           propList: ['*'], //属性的选择器,*表示通用
           unitPrecision: 5, // 允许REM单位增长到的十进制数字,小数点后保留的位数。
           exclude: /(node_module)/,  // 默认false,可以(reg)利用正则表达
           //式 排除某些文件夹的方法
             })
           ]
         }
       }
     }
  })

canvas碰撞效果

  • 1,初始化
import React, { useEffect } from 'react'

export default function
   (props) {
   // 全局变量
   let canvas
   // 将通过面相对象的小球push进去,后面调用才知道是哪一个小球在运动
   let ballArr = []
   // 定时器名字
   let timerC
   // 小球左边的文字
   let fireWords = '你的眼睛|像星星|一样美丽|无论冬夏|晴雨山川|一样灿烂|我的眼睛|因为|有你|所以更美'
   // 对文字做切割
   let textArr = fireWords.split('|')

   useEffect(() => {
       // 获取canvas标签
       canvas = document.getElementById('tutorial');
       // 生成canvas上下文,创建都用上这个
       let ctx = canvas.getContext('2d');
       // 调用函数绘画
       draw(ctx)
       // 切换页面取消定时器
       return () => { clearInterval(timerC) }
   }, [])

   return (
       <canvas id="tutorial" width="375" height="750">
           你的浏览器不支持canvas,请升级你的浏览器
       </canvas>
   )
}
  • 2,绘画draw()函数实现
    const draw = (ctx) => {
        // 创建10小球,小球个数可以更多
        for (let index = 0; index < 10; index++) {
           // 构造10个随机的小球参数对象
            var ball = new Ball()
            // 将每个对象push进去
            ballArr.push(ball)
        }
        // 通过定时器移动小球x,y坐标,实现小球的移动
        timerC = setInterval(() => {
            // 每次进行定时移动的时候,清除画布,不然图像会连在一块
            ctx.clearRect(0, 0, 375, 750)
            // 遍历ballArr,将所有参数取出来,通过show()创建小球
            for (let index = 0; index < ballArr.length; index++) {
                var ball = ballArr[index]
                // 创建小球
                show(ctx, ball, textArr[index])
                //二次循环,确定直线的位置
                for (let j = 0; j < index; j++) {
                    const preBall = ballArr[j]
                     // 画连接的直线
                    drawLine(ctx, preBall.x, preBall.y, ball.x, ball.y, ball.color)
                }
            }
        }, 20)
    }
  • 3,面相对象写法。创建不同小球的参数
 // 设置一个随机数
 const randMod = (number) => {
    return parseInt(Math.random() * number)
 }
 function Ball() {
       // 的this指向new Ball()这个对象
        this.w = 375 //画布的宽
        this.h = 750 //画布的宽
        this.x = randMod(5) + 60 //小球的x坐标
        this.y = randMod(5) + 60 //小球的y坐标
        this.r = randMod(50) + 10 //[10,60] //小球的半径
        // this.color = '#' + parseInt(Math.random() * 0xffffff).toString(16)
        //随机颜色
        this.color = "rgb(" + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ")"
        this.xSpeed = randMod(2) + 3// [3,5] // 每个小球的速度,按x轴移动
        this.ySpeed = randMod(3) + 1// [1,4] // 每个小球的速度,按y轴移动
    }
  • 4,画直线
 const drawLine = (ctx, x1, y1, x2, y2, color) => {
    ctx.beginPath()
    ctx.moveTo(x1, y1)
    ctx.lineTo(x2, y2)
    ctx.closePath()
    ctx.stroke();
    ctx.strokeStyle = color
}
  • 5,小球展示
    const show = function (ctx, ball, text) {
        // 每次展示的时候先运行一下
        run(ball)
        // 每次开始show被调用时,都要重新绘制路径,不然小球会连在一块儿
        ctx.beginPath()
        // 画小球
        ctx.arc(ball.x, ball.y, ball.r, 0, 2 * Math.PI, false)
        // 设置颜色
        ctx.fillStyle = ball.color
        ctx.fill()
        //描述文字
        text && drawText(ctx, text, ball.x, ball.y, ball.r, ball.color)
    }
  • 6,小球运行
    const run = function (ball) {
        if (ball.x - ball.r < 0 || ball.x + ball.r > ball.w) {
            ball.xSpeed = -ball.xSpeed
        }
        if (ball.y - ball.r < 0 || ball.y + ball.r > ball.h) {
            ball.ySpeed = -ball.ySpeed
        }
        ball.x = ball.x + ball.xSpeed
        ball.y = ball.y + ball.ySpeed
    }
  • 7,画文字
    const drawText = (ctx, text, x, y, r, color) => {
        //文字要显示在小球右边,所以用小球的水平位置坐标,加上小球半径,可以作为文字的初始坐标
        ctx.fillText(text, x + r, y)
        ctx.fillStyle = color
        ctx.textAlign = 'left'
    }

思考

这个例子的小球碰撞,有一些不完美,上面的炫酷文字是另一个页面的,切换过来没有消失。正在学习canvas,所以一起加油。学习后持续输出才能为自己赋能!!!

番外

我正在参加「创意开发 投稿大赛」详情请看:掘金创意开发大赛来了!

猜你喜欢

转载自juejin.im/post/7121604088021647368
今日推荐