- 【已解决】 在没有连接设备时,如何实时获取蓝牙设备的RSSI?
1、wx.getBLEDeviceRSSI 方法,实时获取蓝牙的RSSI,需要先建立设备连接后才能调用该方法。 2、那么如何在不连接蓝牙设备的情况下,实时获取搜索到的蓝牙设备的RSSI?
2023-11-11 - [开盖即食]小程序图表插件 ECharts 实战
[图片] H5时代用来做图表的插件有很多比如:[代码]ECharts[代码]、[代码]Bizcharts[代码]、[代码]JSCharts[代码]等,而这次的小程序本人选用了 ECharts 作为图表组件。 1、选择原因主要有3点: 官方某度在持续维护这个插件 官方推出了直接适配小程序的版本,且有demo,开盖即食,不用迁移 简单实用,覆盖面广且可通过配置控制包的大小,小程序毕竟大小有限制~ eCharts来自BAT中的B前端团队,对应的小程序版本为:echarts-for-weixin 官网地址 https://echarts.apache.org/ github地址 https://github.com/ecomfe/echarts-for-weixin 小程序demo地址 https://github.com/ecomfe/echarts-examples 2、用法 (1)官方教程 [代码]index.json[代码] 配置如下: [代码]{ "usingComponents": { "ec-canvas": "../../ec-canvas/ec-canvas" } } [代码] 这一配置的作用是,允许我们在 [代码]pages/bar/index.wxml[代码] 中使用 [代码]<ec-canvas>[代码] 组件。注意路径的相对位置要写对,如果目录结构和本例相同,就应该像上面这样配置。 [代码]index.wxml[代码] 中创建了一个 [代码]<ec-canvas>[代码] 组件: [代码]<view class="container"> <ec-canvas id="mychart-dom-bar" canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas> </view> [代码] 其中 [代码]ec[代码] 是一个我们在 [代码]index.js[代码] 中定义的对象,它使得图表能够在页面加载后被初始化并设置。 [代码]index.js[代码] 配置: [代码]function initChart(canvas, width, height, dpr) { const chart = echarts.init(canvas, null, { width: width, height: height, devicePixelRatio: dpr // 像素 }); canvas.setChart(chart); var option = { ... }; chart.setOption(option); return chart; } Page({ data: { ec: { onInit: initChart } } }); [代码] 这对于所有 ECharts 图表都是通用的,用户只需要修改上面 [代码]option[代码] 的内容,即可改变图表。[代码]option[代码] 的使用方法参见 ECharts 配置项文档。 官方demo里的一些用法指导: 如何延迟加载图表? 参见 [代码]pages/lazyLoad[代码] 的例子,可以在获取数据后再初始化数据。 如何在一个页面中加载多个图表? 参见 [代码]pages/multiCharts[代码] 的例子。 如何使用 Tooltip? 目前,本项目已支持 ECharts Tooltip,但是由于 ECharts 相关功能尚未发版,因此需要使用当前本项目中 [代码]ec-canvas/echarts.js[代码],这个文件包含了可以在微信中使用 Tooltip 的相关代码。目前在 ECharts 官网下载的 [代码]echarts.js[代码] 还不能直接替换使用,等 ECharts 正式发版后即可。 具体使用方法和 ECharts 相同,例子参见 [代码]pages/line/index.js[代码]。 如何保存为图片? 参见 [代码]pages/saveCanvas[代码] 的例子。 (2)本人实战操作 [图片] [代码]import * as echarts from '../ec-canvas/echarts'; const app = getApp(); let chart; function initChart(canvas, width, height, dpr) { chart = echarts.init(canvas, null, { width: width, height: height, devicePixelRatio: dpr // new }); canvas.setChart(chart); chart.setOption(option); return chart; } var option = { title: { text: '智酷君 echarts 切换效果测试', left: 'center' }, tooltip: { trigger: 'item', formatter: '{a} <br/>{b}: {c} ({d}%)' }, legend: { orient: 'vertical', left: 10, data: ['AAA', 'BBB', 'CCC', 'DDD', 'EEE'] }, series: [ { name: '访问来源', type: 'pie', radius: ['50%', '70%'], avoidLabelOverlap: false, label: { show: false, position: 'center' }, emphasis: { label: { show: true, fontSize: '30', fontWeight: 'bold' } }, labelLine: { show: false }, data: [ {value: 335, name: 'AAA'}, {value: 310, name: 'BBB'}, {value: 234, name: 'CCC'}, {value: 135, name: 'DDD'}, {value: 1548, name: 'EEE'} ] } ] }; Page({ data: { ec: { onInit: initChart } }, onLoad: function () {}, //单曲线 line() { let option2 = { title: { text: '同一canvas更新成折线图', left: 'center' }, xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }, yAxis: { type: 'value' }, series: [{ data: [820, 932, 901, 934, 1290, 1330, 1320], type: 'line' }] }; chart.setOption(option2) }, //切换柱状图 bar(){ let option3 = { title: { text: '直接更新数据,减少性能消耗', left: 'center' }, xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }, yAxis: { type: 'value' }, series: [{ data: [120, 200, 150, 80, 70, 110, 130], type: 'bar', showBackground: true, backgroundStyle: { color: 'rgba(220, 220, 220, 0.8)' } }] }; chart.setOption(option3) } }) [代码] 建议大家尽量使用同一个canvas对象来切换不同的图表效果,而不是初始加载多个不同的,我们可以将 [代码]chart[代码] 对象设置为全局,然后通过 [代码]chart.setOption()[代码] 的方法来更新配置数据,可以减少性能消耗避免闪退等 (3)代码片段 代码段:https://developers.weixin.qq.com/s/OOTwnsms7Cin 建议将IDE工具升级到 1.02.18以上,避免一些BUG [图片] 3、Tips (1)包大小可以配置 在线定制地址: https://echarts.apache.org/zh/builder.html [图片] [图片] 通过选择和配置想要的功能,可以大大减少原本JS包的尺寸。 (2)Canvas 2d 版本要求 最新版的 ECharts 微信小程序支持微信 Canvas 2d,当用户的基础库版本 >= 2.9.0 且没有设置 [代码]force-use-old-canvas="true"[代码] 的情况下,使用新的 Canvas 2d(默认)。 使用新的 Canvas 2d 可以提升渲染性能,解决非同层渲染问题,强烈建议开启 如果仍需使用旧版 Canvas,使用方法如下: [代码]<ec-canvas id="xxx" canvas-id="xxx" ec="{{ ec }}" force-use-old-canvas="true"></ec-canvas> [代码] (3)数据点过多造成闪退和卡死 本人简单测试了下,iphone7p手机在[代码]1500个[代码]左右数据点的时候,出现了小程序闪退,iphoneX 测试下来大概在[代码]2500个[代码]左右,猜测可能由于微信本身给小程序的内存有限,所以建议大家控制数据点的个数 (4)单页面图表canvas加载过多卡死 建议单页面图表加载不要超过[代码]5个canvas[代码],尽可能共用一个图表Canvas对象,通过动态更新数据的方式来展示内容(还有帅气的特效),如果一定要加载多个canvas的话,建议控制数量,提供复用性~ 看完觉得有帮助记得点个赞哦~ 你的赞是我继续分享的最大动力!^-^
2020-06-29 - onShow与onLoad的一些理解和实践
基本介绍onShow、onLoad与onReady都是小程序页面生命周期函数。 onLoad 在页面加载时调用,仅一次; onShow页面显示/切入前台时触发,两个生命周期非阻塞式调用。 onReady 是页面初始化数据已经完成后调用的,并不意味着onLoad和onShow执行完毕。 调用顺序是onLoad > onShow > onReady 根据对应的执行机制,我们预期有三种执行的逻辑 A. 页面每次出现都会执行 从其他页面返回手机锁屏唤醒,重新看到小程序页面把当前小程序页面重写切换到前台(多任务)B. 页面加载后只需执行一次(页面第一次载入) C. 只在页面非第一次执行时才执行(A情况的子集,页面非第一次展示时) 需求与问题逻辑1: 因为onLoad和onShow是非阻塞执行的,当我们有一个这样的需求:页面载入执行A方法,页面展示执行B、C、D方法时,A需要在BCD之前执行,此时把A放在onLoad中,BCD放在onShow中就无法实现需求 逻辑2: 还有一种需求是:页面第一次执行A,非第一次执行R-A,这里onLoad和onShow并没有非第一次的逻辑,需要手动判断。 一种实践方法下面是纯粹使用onShow代替onLoad,完成所有逻辑的示例,保证了业务逻辑的执行顺序可控。 options获取使用其他方式代替。 为了保持onShow中逻辑的清晰性,尽量使用EventChannel去替代原本onShow+globalData的逻辑。 data:{ first: true }, async onShow(){ //代替onLoad中的options的获取 const pages = getCurrentPages(); const currentPage = pages[pages.length - 1]; const options = currentPage.options; this.funD() // C2 页面每次都调用的逻辑 if(this.data.first){ this.data.first = false; await this.funA(); //A 仅在页面初次调用的逻辑(按需是否阻塞调用) }else{ await this.funB(); //B 仅在页面非初次时调用的逻辑 } await this.funC(); //C1 页面每次都调用的逻辑 } 另外一种使用实践data:{ first: true } onShow(){ this.funD() //页面每次都调用的逻辑(仅非阻塞) if(!this.data.first){ this.funC() //仅在页面非初次时调用的逻辑 } await this.funE() //页面每次都调用的逻辑(可阻塞,可非阻塞) }, onLoad(){ //仅在页面初次调用的逻辑 this.funA(); await this.funB(); } onReady(){ this.data.first = false; } 如有错误,恳请指出。
2022-09-23 - 微信小程序登录与注册验证码倒计时的效果实现(javascript实现倒计时)
我们在做手机登录和用户注册时,总会用到倒计时效果,今天就来给大家讲讲手机登录时验证码倒计时效果的实现。 老规矩,先看效果图 [图片] 可以看到,我们在点击获取验证码以后,就开始倒计时了,正常都是从60s倒计时的,这里为了演示方便,我从6s开始的。可以看到倒计时结束后,按钮又恢复了可以点击的状态。 一,index.wxml布局 [图片] 布局很简单,就是一个用户获取手机号输入,一个用来获取验证码输入,一个获取验证码按钮,一个登录按钮。 二,index.wxss样式 [代码].item { display: flex; flex-direction: row; margin-left: 20rpx; margin-top: 25rpx; padding-bottom: 25rpx; border-bottom: 1px solid gainsboro; } .tip { font-size: 0.5rem; color: red; } .tip2 { font-size: 0.8rem; color: black; } .btn { color: white; background: #0271c1; font-size: 0.9rem; width: 90%; margin-top: 60rpx; } .input { margin-left: 40rpx; } .input2 { width: 50%; } .plac { color: #aab2bd; font-size: 0.8rem; /* placeholder位置 *//* text-align: right; */ } /* 验证吗 */ .code { width: 160rpx; border: 1px solid #0271c1; font-size: 0.8rem; text-align: center; padding: 10rpx; position: absolute; right: 15rpx; } [代码] 样式我就不具体讲解了,重要的是下面的倒计时的js事件。 三,index.js实现倒计时效果 1,首先看下倒计时实现的部分。 [图片] 上图红框里是我们实现倒计时的核心代码,可以看到我们主要是用了setInterval 这个方法来实现每个1s的计时器。 这里我们定义一个countDownTime,初始值为6s,然后我们每隔1s,对countDownTime做减1操作,直到countDownTime的值小于2,也就是等于1时,我们用clearInterval方法取消计时器。 2,动态改变按钮文字颜色。 这里之前经常有同学问过,怎么在js里动态改变小程序组件的样式。其实小程序这点做的不如vue好,不能在js里获取到组件的实例。所以我们就要换个方式了。 [代码]<!-- 这里我们同在在wxml里写style来实现样式的动态改变 --> <text class="code" style="color:{{codeColor}};" >获取验证码</text> [代码] 这个时候我们在去看第一个,倒计时里写的下面这段代码。这里就是用来动态改变按钮上文字颜色的方法。 [代码] if (countDownTime < 2) { that.setData({ codeColor: "#0271c1", codeText: "获取验证码" }) } else { that.setData({ codeColor: "#e6252b", codeText: "60s" }) } [代码] 我们这里还有做一步处理,就是在倒计时过程中,用户不能再次点击获取验证吗的按钮,获取点击时要给用户提示。 [图片] 下面把index.js的完整代码贴出来给大家 [代码]//老师微信2501902696 let timeNum = 6 //60秒倒计时 let countDownTime = timeNum let timer; //计时器 Page({ data: { codeColor: "#0271c1", codeText: "获取验证码" }, //获取验证码 getCode() { if (countDownTime == timeNum) { this.setInterval() this.setData({ codeColor: "#e6252b", codeText: countDownTime + "s" }) } else { wx.showToast({ title: '请等待验证码', icon: "none" }) } }, // 计时器 setInterval: function() { const that = this timer = setInterval(function() { // 设置定时器 countDownTime-- if (countDownTime < 2) { clearInterval(timer) that.setData({ codeColor: "#0271c1", codeText: "获取验证码" }) countDownTime = timeNum } else { that.setData({ codeColor: "#e6252b", codeText: countDownTime + "s" }) } console.log(countDownTime + "s") }, 1000) }, }) [代码] 这样我们就能实现微信小程序在登录或者注册时实现验证码倒计时的效果了。 今天就先到这里,下一节给大家讲解手机号的校验,和验证码的随机生成。还有短信验证码的发送都会在后面的文章做讲解。敬请关注。
2019-09-06 - 收下这份指南,小程序蓝牙应用不再难
在移动互联网全民化发展的当下,蓝牙技术凭借着简便、安全、低成本的优势逐渐成为无线技术领域的中流砥柱。在共享单车领域,电子设备和单车锁通过蓝牙技术形成可靠且安全的连接,从而提升用户体验。 微信团队一直致力于 小程序蓝牙能力 的应用开发,提升小程序在无线技术领域的高效、安全、可靠应用。通过 滴滴青桔小程序 等项目落地验证,小程序蓝牙能力的合理应用能够实现搜索成功率、连接成功率、开锁成功率的全面提升。 [图片] 当前主流的蓝牙技术主要是经典蓝牙 (BR / EDR) 和低功耗蓝牙 (BLE),其中 BLE 凭借着与电子设备的简便互操作性,成为大部分共享单车蓝牙锁的重要技术选型。 在实际应用场景,小程序蓝牙技术与蓝牙锁之间进行以下技术交互,实现解锁。 Step 1:蓝牙扫描 扫描蓝牙广播,检查 Android 系统直连模式是否连接正常。 Step 2:生成通信帧 与锁建立 BLE 连接后,准备获取锁的 Token 通信帧,将传递信息 AES 加密并转化成 HexString 发送。 Step 3:获取锁的 Token 将传递信息 AES 解密后收到 Token 获取成功通信帧,同时截取相应位数的字节作为令牌 Token,准备开始解锁。 Step 4:等待解锁 发送解锁信息通信帧,利用 Password 还有 Token 同样将传递信息 AES 加密并转化成 HexString 以一定的规则发送,等待解锁。 Step 5:解锁成功 收到蓝牙返回的信息 AES 解密后得到解锁通信帧代表解锁成功。 [图片] 通过 滴滴青桔小程序 等项目的实践探索,合理应用小程序蓝牙技术能够实现解锁全链路的优化提升—— 提前搜索时机提升蓝牙搜索成功率 蓝牙技术在搜索耗时的原生限制导致单车锁-电子设备之间的搜索成功率偏低。因此在不增加用户功耗的前提下,适当提前搜索时机能够减少搜索设备的耗时,提升蓝牙搜索成功率。 [图片] 默认直连模式提升蓝牙连接成功率 大部分的 Android 系统手机均支持直连模式,建议针对 Android 系统,默认使用直连模式,加速蓝牙连接流程。如果直连模式失效,则重新搜索,连接附近设备。 [图片] 建立失败重试机制提升蓝牙开锁成功率 低功耗蓝牙的原生不稳定性要求开发者做好重连逻辑。建议建立失败重试机制,即在每个 API 回调失败后,允许失败重试 3 次,用于提升开锁成功率。 [图片] 在小程序蓝牙技术应用过程中,总结以下应用注意点,助力开发者更好地应用蓝牙能力。 连接前 开启 notify 功能:连接前必须调用 notifyBLECharacteristicValueChange 才能接收到设备推送的信息,否则只能发送数据,无法接收数据。注意 iOS 与 Android 的蓝牙应用区别[图片] 连接中 停止搜索以减少性能消耗:调用 onBluetoothDeviceFound 搜索设备成功,必须执行 stopBluetoothDevicesDiscovery 停止搜索,避免后台资源消耗性能。不使用 Android 1800 / 1801服务:在获取设备服务时,部分 Android 机型增加系统自带的 00001800 和 00001801 服务,请不要使用这 2 项服务。重装微信获取其他设备服务:部分 Android 机型通过 getBLEDeviceServices 仅得到系统自带的 00001800 和 00001801 服务,重装微信即可获取其他设备服务。 连接后 及时关闭连接及蓝牙设备:操作完成后,及时关闭连接及蓝牙设备,否则在 Android 系统下,出现设备搜索失败的情况。成对调用创建和关闭 BLE 连接:建议成对调用 createBLEConnection 和 closeBLEConnection 接口,否则在 Android 系统下,重复调用 createBLEConnection 接口,可能导致系统持有同一设备多个连接的实例,最终导致调用 closeBLEConnection 不能真正断开与设备的连接。 合理应用小程序蓝牙技术能够丰富小程序的应用场景,提升小程序性能表现,进一步优化用户体验。 如有其他小程序应用相关的问题,可在 微信开放社区小程序交流专区 发帖互动,技术专员将为大家解答及进行深度交流。
2022-07-12