- 使用npm安装了dayjs,require导入插件报错?
let dayjs = require('dayjs') let relativeTime = require('dayjs/plugin/relativeTime.js') dayjs.extend(relativeTime) npm安装的dayjs,构建都是成功的,但是在页面引入dayjs的插件,页面报错 Error: module 'pages/matters/dayjs/plugin/relativeTime.js' is not defined, require args is 'dayjs/plugin/relativeTime.js' require导入时,引入的路径变成了当前页面下的相对路径。要怎么处理好这个问题?
2023-06-28 - 自定义导航栏所有机型的适配方案
写在前面的话 大家看到这个文章时一定会感觉这是在炒剩饭,社区中已经有那么多分享自定义导航适配的文章了,为什么我还要再写一个呢? 主要原因就是,社区中大部分的适配方案中给出的大小是不精确的,并不能完美适配各种场景。 社区中大部分文章给到的值是 iOS -> 44px , Android -> 48px 思路 正常来讲,iOS和Android下的胶囊按钮的位置以及大小都是相同且不变的,我们可以通过胶囊按钮的位置和大小再配合 wx.getSystemInfo 或者 wx.getSystemInfoSync 中得到的 [代码]statusBarHeight[代码] 来计算出导航栏的位置和大小。 小程序提供了一个获取菜单按钮(右上角胶囊按钮)的布局位置信息的API,可以通过这个API获取到胶囊按钮的位置信息,但是经过实际测试,这个接口目前存在BUG,得到的值经常是错误的(通过特殊手段可以偶尔拿到正确的值),这个接口目前是无法使用的,等待官方修复吧。 下面是我经过实际测试得到的准确数据: 真机和开发者工具模拟器上的胶囊按钮不一样 [代码]# iOS top 4px right 7px width 87px height 32px # Android top 8px right 10px width 95px height 32px # 开发者工具模拟器(iOS) top 6px right 10px width 87px height 32px # 开发者工具模拟器(Android) top 8px right 10px width 87px height 32px [代码] [代码]top[代码] 的值是从 [代码]statusBarHeight[代码] 作为原点开始计算的。 使用上面数据中胶囊按钮的高度加 [代码]top[代码] * 2 上再加上 [代码]statusBarHeight[代码] 的高度就可以得到整个导航栏的高度了。 为什么 [代码]top[代码] * 2 ?因为胶囊按钮是垂直居中在 title 那一栏中的,上下都要有边距。 扩展 通过胶囊按钮的 [代码]right[代码] 可以准确的算出自定义导航的 [代码]左边距[代码]。 通过胶囊按钮的 [代码]right[代码] + [代码]width[代码] 可以准确的算出自定义导航的 [代码]右边距[代码] 。 通过 wx.getSystemInfo 或者 wx.getSystemInfoSync 中得到的 [代码]windowWidth[代码] - 胶囊按钮的 [代码]right[代码] + [代码]width[代码] 可以准确的算出自定义导航的 [代码]width[代码] 。 再扩展 wx.getSystemInfo 或者 wx.getSystemInfoSync 中得到的 [代码]statusBarHeight[代码] 每个机型都不一样,刘海屏得到的数据也是准确的。 如果是自定义整个页面,iPhone X系列的刘海屏,底部要留 [代码]68px[代码] ,不要问我为什么! 代码片段 https://developers.weixin.qq.com/s/Q79g6kmo7w5J
2019-02-25 - 微信小程序自定义导航栏组件(完美适配所有手机),可自定义实现任何你想要的功能
背景 在做小程序时,关于默认导航栏,我们遇到了以下的问题: Android、IOS手机对于页面title的展示不一致,安卓title的显示不居中 页面的title只支持纯文本级别的样式控制,不能够做更丰富的title效果 左上角的事件无法监听、定制 路由导航单一,只能够返回上一页,深层级页面的返回不够友好 探索 小程序自定义导航栏已开放许久>>了解一下,相信不少小伙伴已使用过这个功能,同时不少小伙伴也会发现一些坑: 机型多如牛毛:自定义导航栏高度在不同机型始终无法达到视觉上的统一 调皮的胶囊按钮:导航栏元素(文字,图标等)怎么也对不齐那该死的胶囊按钮 各种尺寸的全面屏,奇怪的刘海屏,简直要抓狂 一探究竟 为了搞明白原理,我先去翻了官方文档,>>飞机,点过去是不是很惊喜,很意外,通篇大文尽然只有最下方的一张图片与这个问题有关,并且啥也看不清,汗汗汗… 我特意找了一张图片来 [图片] 分析上图,我得到如下信息: Android跟iOS有差异,表现在顶部到胶囊按钮之间的距离差了6pt 胶囊按钮高度为32pt, iOS和Android一致 动手分析 我们写一个状态栏,通过wx.getSystemInfoSync().statusBarHeight设置高度 Android: [图片] iOS:[图片] 可以看出,iOS胶囊按钮与状态栏之间距离为:4px, Android为8px,是不是所有手机都是这种情况呢? 答案是:苹果手机确实都是4px,安卓大部分都是7和8 也会有其他的情况(可以自己打印getSystemInfo验证)如何快速便捷算出这个高度,请接着往下看 如何计算 导航栏分为状态栏和标题栏,只要能算出每台手机的导航栏高度问题就迎刃而解 导航栏高度 = 胶囊按钮高度 + 状态栏到胶囊按钮间距 * 2 + 状态栏高度 注:由于胶囊按钮是原生组件,为表现一致,其单位在各种手机中都为px,所以我们自定义导航栏的单位都必需是px(切记不能用rpx),才能完美适配。 解决问题 现在我们明白了原理,可以利用胶囊按钮的位置信息和statusBarHeight高度动态计算导航栏的高度,贴一个实现此功能最重要的方法 [代码]let systemInfo = wx.getSystemInfoSync(); let rect = wx.getMenuButtonBoundingClientRect ? wx.getMenuButtonBoundingClientRect() : null; //胶囊按钮位置信息 wx.getMenuButtonBoundingClientRect(); let navBarHeight = (function() { //导航栏高度 let gap = rect.top - systemInfo.statusBarHeight; //动态计算每台手机状态栏到胶囊按钮间距 return 2 * gap + rect.height; })(); [代码] gap信息就是不同的手机其状态栏到胶囊按钮间距,具体更多代码实现和使用demo请移步下方代码仓库,代码中还会有输入框文字跳动解决办法,安卓手机输入框文字飞出解决办法,左侧按钮边框太粗解决办法等等 胶囊信息报错和获取不到 问题就在于 getMenuButtonBoundingClientRect 这个方法,在某些机子和环境下会报错或者获取不到,对于此种情况完美可以模拟一个胶囊位置出来 [代码]try { rect = Taro.getMenuButtonBoundingClientRect ? Taro.getMenuButtonBoundingClientRect() : null; if (rect === null) { throw 'getMenuButtonBoundingClientRect error'; } //取值为0的情况 if (!rect.width) { throw 'getMenuButtonBoundingClientRect error'; } } catch (error) { let gap = ''; //胶囊按钮上下间距 使导航内容居中 let width = 96; //胶囊的宽度,android大部分96,ios为88 if (systemInfo.platform === 'android') { gap = 8; width = 96; } else if (systemInfo.platform === 'devtools') { if (ios) { gap = 5.5; //开发工具中ios手机 } else { gap = 7.5; //开发工具中android和其他手机 } } else { gap = 4; width = 88; } if (!systemInfo.statusBarHeight) { //开启wifi的情况下修复statusBarHeight值获取不到 systemInfo.statusBarHeight = systemInfo.screenHeight - systemInfo.windowHeight - 20; } rect = { //获取不到胶囊信息就自定义重置一个 bottom: systemInfo.statusBarHeight + gap + 32, height: 32, left: systemInfo.windowWidth - width - 10, right: systemInfo.windowWidth - 10, top: systemInfo.statusBarHeight + gap, width: width }; console.log('error', error); console.log('rect', rect); } [代码] 以上代码主要是借鉴了拼多多的默认值写法,android 机子中 gap 值大部分为 8,ios 都为 4,开发工具中 ios 为 5.5,android 为 7.5,这样处理之后自己模拟一个胶囊按钮的位置,这样在获取不到胶囊信息的情况下,可保证绝大多数机子完美显示导航头 吐槽 这么重要的问题,官方尽然没有提供解决方案…竟然提供了一张看不清的图片??? 网上有很多ios设置44,android设置48,还有根据不同的手机型号设置不同高度,通过长时间的开发和尝试,本人发现以上方案并不完美,并且bug很多 代码库 Taro组件gitHub地址详细用法请参考README 原生组件npm构建版本gitHub地址详细用法请参考README 原生组件简易版gitHub地址详细用法请参考README 由于本人精力有限,目前只计划发布维护好这2种组件,其他组件请自行修改代码,有问题请联系 备注 上方2种组件在最下方30多款手机测试情况表现良好 iPhone手机打电话和开热点导致导航栏样式错乱,问题已经解决啦,请去demo里测试,这里特别感谢moments网友提出的问题 本文章并无任何商业性质,如有侵权请联系本人修改或删除 文章少量部分内容是本人查询搜集而来 如有问题可以下方留言讨论,微信zhijunxh 比较 斗鱼: [图片] 虎牙: [图片] 微博: [图片] 酷狗: [图片] 知乎: [图片] [图片] 知乎是这里边做的最好的,但是我个人认为有几个可以优化的小问题 打电话或者开启热点导致样式错落,这也是大部门小程序的问题 导航栏下边距太小,看起来不舒服 搜索框距离2侧按钮组距离不对等 自定义返回和home按钮中的竖线颜色重了,并且感觉太粗 如果您看到了此篇文章,请赶快修改自己的代码,并运用在实践中吧 扫码体验我的小程序: [图片] 创作不易,如果对你有帮助,请移步Taro组件gitHub原生组件gitHub给个星星 star✨✨ 谢谢 测试信息 手机型号 胶囊位置信息 statusBarHeight 测试情况 iPhoneX 80 32 281 369 48 88 44 通过 iPhone8 plus 56 32 320 408 24 88 20 通过 iphone7 56 32 281 368 24 87 20 通过 iPhone6 plus 56 32 320 408 24 88 20 通过 iPhone6 56 32 281 368 24 87 20 通过 HUAWEI SLA-AL00 64 32 254 350 32 96 24 通过 HUAWEI VTR-AL00 64 32 254 350 32 96 24 通过 HUAWEI EVA-AL00 64 32 254 350 32 96 24 通过 HUAWEI EML-AL00 68 32 254 350 36 96 29 通过 HUAWEI VOG-AL00 65 32 254 350 33 96 25 通过 HUAWEI ATU-TL10 64 32 254 350 32 96 24 通过 HUAWEI SMARTISAN OS105 64 32 326 422 32 96 24 通过 XIAOMI MI6 59 28 265 352 31 87 23 通过 XIAOMI MI4LTE 60 32 254 350 28 96 20 通过 XIAOMI MIX3 74 32 287 383 42 96 35 通过 REDMI NOTE3 64 32 254 350 32 96 24 通过 REDMI NOTE4 64 32 254 350 32 96 24 通过 REDMI NOTE3 55 28 255 351 27 96 20 通过 REDMI 5plus 67 32 287 383 35 96 28 通过 MEIZU M571C 65 32 254 350 33 96 25 通过 MEIZU M6 NOTE 62 32 254 350 30 96 22 通过 MEIZU MX4 PRO 62 32 278 374 30 96 22 通过 OPPO A33 65 32 254 350 33 96 26 通过 OPPO R11 58 32 254 350 26 96 18 通过 VIVO Y55 64 32 254 350 32 96 24 通过 HONOR BLN-AL20 64 32 254 350 32 96 24 通过 HONOR NEM-AL10 59 28 265 352 31 87 24 通过 HONOR BND-AL10 64 32 254 350 32 96 24 通过 HONOR duk-al20 64 32 254 350 32 96 24 通过 SAMSUNG SM-G9550 64 32 305 401 32 96 24 通过 360 1801-A01 64 32 254 350 32 96 24 通过
2019-11-17 - 小程序中自定义tabbar的基本逻辑和三种实现思路
重要提示小程序中的tabbar默认可以在app.json中配置,参见全局配置 | 微信开放文档,请优先考虑使用官方配置,在使用上更简洁优雅。同时小程序也提供了自定义tabbar的方法,参见自定义 tabBar | 微信开放文档, 三种实现思路按简易程度排序。 1. 官方约定的自定义组件已基本优化图标闪烁问题,官方正在修复中,见此参照官方的教程步骤如下: app.json中声明tabBar中的custom: true,隐藏默认的tabBar,并补充完整的tab页面路径。按照约定,在根目录创建custom-tab-bar/index.js等作为自定义展示的tabBar然后在app.json中添加usingComponents或在对应的tab页面(可以是组件或页面)中添加usingComponents项(仅需key即可),微信会自动把该组件注册到对应的tab页面中。观察官方示例可以发现:在custom-tab-bar/index中通过cover-view + cover-image + fixed+padding-bottom: env(safe-area-inset-bottom) 让对应的tab显示在页面的最下方,并处理了安全边距的问题,点击不同的菜单时,首先会在组件内部触发跳转路由操作,使用wx.switchTab, 因为对应路径已经在app.json中已声明为tab页面。官方示例在tab组件的onShow中更新selected状态(通过this.getTabBar()获取自定义tabBar实例),同时在该tabBar的点击回调中更新selected,会出现闪烁问题,'该tabBar的点击回调中更新selected' 注释掉会优化闪烁问题。见代码示例 2. 一半约定,一般自定义组件的方式app.json中声明tabBar中的custom: true,隐藏默认的tabBar,并补充完整的tab页面路径。在components中创建自定义tabBar组件,在tab页面注册该组件并传递当前页面的selected值,点击时按配置的path进行switchTab路由切换本质1类似,但没有使用约定的目录和命名,并没有使用getTabBar,通过组件属性的方式实现菜单的激活选择 初次仍存在闪烁问题3. 在一个页面模拟多个页面,类似SPA的标签切换控制不同组件的方式大部分的UI库都是类似的方式,即tabBar仅仅是一个独立组件,具体显示由开发者控制 组件具体实现及使用参见TDesign、Vant Weapp - 轻量、可靠的小程序 UI 组件库,也可结合上述1、2使用。
2023-03-30 - 如何使用canvas绘制签名板?
场景分析在小程序业务中如需用户进行手写签名的场景如:寄快递,签约合同时需要在小程序中进行手写签名。 处理方法 实现原理运用 canvas 监听用户 touch 事件,然后在 canvas 上画出与 touch 事件相近的线模仿手写签名效果。 实现方法参考如下代码片段:https://developers.weixin.qq.com/s/MYDTQAmR7EIa [图片]
09-09 - 小程序自定义扫码界面, 附全部代码
一、需求: 小程序扫一扫wx.scanCode 这个api扫描不能自定义扫码界面, 如果你们有这种自定义扫码需求 这个时候就需要用camera 自定义扫描界面; camera文档传送门 : https://developers.weixin.qq.com/miniprogram/dev/component/camera.html --------------------------------------------------------------------------------------------------------------------------------------------- [图片] 二、效果图:(需要获取camera授权权限) [图片][图片][图片] 三、全部代码 <!-- 扫一扫按钮+scanResult扫描结果 --> <button wx:if="{{!canScan}}" type="primary" bindtap="scanShowClick">自定义扫一扫{{scanResult}}</button> <!-- 扫描框 --> <view class="scanBox" wx:if="{{canScan}}"> <camera class="camera" mode="scanCode" bindscancode="scancode" flash='{{flashBtn}}'> <image class="coverImg" src="{{iconScanBgGif}}"></image> </camera> <view style="text-align: center;margin: 80rpx 0 40rpx 0;"> <button class="cu-btn scancodePic" bindtap="changeflashBtn"> <image src="{{flashBtn=='on'?scancodeOpen:scancodeClose}}"></image> </button> </view> <view class="scanTip">请扫描大熊帅照</view> <!-- 关闭扫码页面 --> <view class="closeScan" bindtap="scanHideClick">关闭</view> </view> import { iconScanBgGif,scancodeOpen,scancodeClose } from "../../../utils/imgUrl/index"; const permisson = require("../../../utils/tools/permisson"); // 权限校验封装 const userCameraName = "scope.camera"; // 摄像头权限 const userCameraZhName = "手机摄像头"; // 摄像头权限对应的中文名称 Page({ /** * 页面的初始数据 */ data: { iconScanBgGif,scancodeOpen,scancodeClose, canScan: false, // 是否显示自定义扫码界面 flashBtn: 'off', // off关闭 on 打开手电筒 scanResult: '' // 扫描结果 }, /** * 生命周期函数--监听页面加载 */ onLoad() { }, /** * 生命周期函数--监听页面显示 */ onShow() { }, // 打开关闭手电筒 changeflashBtn(){ this.setData({ flashBtn:this.data.flashBtn=='off'?'on':'off' }) }, // 显示扫码界面(扫一扫) scanShowClick(){ // 校验权限, 必须开启摄像头权限 wx.getSetting({ success:async(res)=> { if(!res.authSetting['scope.camera']) { // 权限封装 permisson.permission_request(userCameraName, userCameraZhName); // 也可自己写,通过 wx.authorize 打开有关授权=>官方链接https://developers.weixin.qq.com/miniprogram/dev/api/open-api/authorize/wx.authorize.html } else { this.setData({ canScan:true }) // 顶部标题栏背景变黑 wx.setNavigationBarColor({ backgroundColor: '#000000', frontColor: '#ffffff', }); } } }) }, // 隐藏扫码界面 scanHideClick(){ this.setData({canScan:false}) // 顶部标题栏背景变白 wx.setNavigationBarColor({ backgroundColor: '#ffffff', frontColor: '#000000', }); }, // 扫一扫返回数据 scancode(e) { console.log(e.detail) const {result:scanResult} = e.detail; if(result) { this.setData({scanResult,canScan: false}) // 顶部标题栏背景变白 wx.setNavigationBarColor({ backgroundColor: '#ffffff', frontColor: '#000000' }); } } }) /* 扫码框---------------------------------------------- */ .scanBox { position: fixed; top: 0; width: 100%; height: 100vh; background-color: #000000; } .camera { position: relative; width: 70vw; height: 70vw; margin: 20vh auto 0; } .coverImg{ position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 99999; } .scanTip { padding: 20rpx 0 0 0; font-size: 32rpx; text-align: center; color: #fff; } /* 开关手电筒 */ .scancodePic{ background: transparent !important; width: 100rpx; height: 100rpx; padding: 0 !important; } .scancodePic>image{ width: 100%; height: 100%; } /* 关闭按钮 */ .closeScan{ position: absolute; bottom: 0; right: 0; padding: 20rpx 30rpx; z-index: 99999; background: #fff; } 四、页面资源 1. permisson.js=>权限校验封装请查看我这篇文https://www.cnblogs.com/520BigBear/p/16968820.html 2. 扫码框背景图,还有手电筒图片 [图片] 白色开灯图标 [图片] 白色关灯图标 [图片] 更多其他参考链接: https://www.cnblogs.com/L-xjco/p/15649832.html
2023-04-14