- 授权发起页域名填什么
授权发起页域名 授权发起页域名指公众号/小程序在登录授权给第三方平台时的授权回调域名,在公众号/小程序进行登录授权流程中,必须从本域名内网页跳转到登录授权页,才可完成登录授权。 授权成功后会回调授权时提供的 URI,公众平台会检查 URI,必须保证 URI 所属域名与服务申请时提供的授权域名保持一致
2020-09-09 - 微信开放平台-代公众号发起网页授权教程
[图片] 回调地址需要配置公众号开发域名内,多个以英文;隔开。切忌不要配置在登录授权的发起页域名内,否则会报错redirect_uri 10003。 回调地址需要配置公众号开发域名内,多个以英文;隔开。切忌不要配置在登录授权的发起页域名内,否则会报错redirect_uri 10003。 回调地址需要配置公众号开发域名内,多个以英文;隔开。切忌不要配置在登录授权的发起页域名内,否则会报错redirect_uri 10003。
2019-04-11 - picker多列选择器滚动未停止时点击确定按钮会出现数据不对的bug?
问题跟这个贴子一模一样,但是没有官方的解答,请问有大神有好的解决办法么?https://developers.weixin.qq.com/community/develop/doc/000ec25c0906d042cd77e73fb53400?highLine=picker%2520%25E7%25A1%25AE%25E5%25AE%259A 机型一加8,安卓10,微信版本7.0.18.1740,版本库2.13.0 复现地址:https://developers.weixin.qq.com/s/pZb21cmH6qYX 复现步骤:多列选择器那块的第一列,切换第一列的瞬间点确定,之后发现外面的数据的第二列和第三列是旧数据来着,没有更新,导致提交数据的父子级错乱了。
2020-09-16 - 微信 schema 跳转之非官方文档
微信“应该”是最近开放了 schema 跳转小程序 的能力,大大方便了短信、邮件、外部网页等唤起微信小程序。 schema 链接格式大体是这样:[代码]weixin://dl/business/?ticket=l69894d682fa8dbafe724a0ca3950741e[代码],但是这段文本在安卓端无法识别。小规模测试结果如下: [图片] 后来想到用一个正常能够识别的网页地址,内容是重定向到指定的 schema 链接。这就是擅长的领域了,query 参数上带上 schema 链接,location.href 一下不就行了。这里就不 show 代码了,能看到文章的你一定行。 但是,发现在部分安卓手机下(如小米)还是没反应,原来简单的 schema 跳转水这么深的,于是百度谷歌了一下,找到了下面两份关键材料: H5唤起APP进行分享的尝试 AlanZhang001/H5CallUpNative: H5端唤醒移动客户端程序 看源码也不多,总结下来,因不同系统和浏览器对 schema 规范的理解不同,还有一些商业因素,不同环境下面需要用不同的方式进行跳转,甚至有的环境你根本就跳不了。 时间紧,任务重。简单处理吧,不同方式都来一遍,谁好使就用谁。所以简单总结了下,能用的几种方式: location 跳转 a 链接跳转 iframe 跳转 以上三种方式,逐一试用,最后实在不行就不行吧,简单处理,看有没有大神补充的。 相关代码如下: location [代码]location.href = "weixin://dl/business/?ticket=l69894d682fa8dbafe724a0ca3950741e"; [代码] a 链接跳转 [代码]var aLink = document.createElement("a"); aLink.className = 'call_up_a_link'; aLink.href = "weixin://dl/business/?ticket=l69894d682fa8dbafe724a0ca3950741e"; aLink.style.cssText = "display:none;width:0px;height:0px;"; document.body.appendChild(aLink); aLink.click(); [代码] iframe [代码]var iframe = document.createElement('iframe'); iframe.className = 'call_up_iframe'; iframe.src = "weixin://dl/business/?ticket=l69894d682fa8dbafe724a0ca3950741e"; iframe.style.cssText = "display:none;width:0px;height:0px;"; document.body.appendChild(iframe); [代码] 以上代码均可从参考资料中找到出处,感谢 是直接一进来就执行,还是事件触发,都可以。或者是一开始进来就执行,失败了显示几个可选跳转按钮让用户手动触发跳转。 但是关键问题还有一个,如何判断是可以成功唤起了呢?上述 github 代码里提到了一个根据页面 hidden 状态,但不够精准,如果用户没有选择跳转到微信呢?这是另一个需要深究的问题。 出于时间考虑,先以业务交付优先,如果有朋友知道的也可以一起讨论下。 另行文时间短,以技术交流为主,若有瑕疵,欢迎指出。 附上 vue 版本源码:微信 schema 跳转 参考链接: 微信官方文档:urlscheme.generate H5唤起APP进行分享的尝试 AlanZhang001/H5CallUpNative: H5端唤醒移动客户端程序 安卓端,微信schema无法跳转微信小程序?
2021-01-04 - 微信小程序新能力:URL Scheme,可从短信跳转小程序
最近小程序上线了一个超级流量的新入口:URL Scheme。通过小程序页面的URL Scheme,可以在短信、邮件或微信外部的网页中打开小程序。 那么如何实现呢?官方文档已经写的很清楚啦,这里简单介绍一下。 首先,获取URL Scheme,通过服务端接口可以获取打开小程序任意页面的URL Scheme,支持生成到期失效和永久有效的URL Scheme。 [图片] 然后,通过短信群发平台将获取的URL Scheme + 营销文案发送到用户的手机上。 最后,用户收到短信后,直接点击URL Scheme唤起微信,跳转到对应小程序页面,就是这么简单。 除此之外,还可以通过邮件或外部浏览器打开跳转小程序。 由于部分操作系统仍不支持直接识别URL Scheme,因此直接将Scheme发送给用户可能存在无法打开小程序的情况。 为此,我们可以先准备一个H5页面,再从H5页面跳转到URL Scheme实现打开小程序。 [代码]location.href = 'weixin://dl/business/?ticket= *TICKET*' [代码] H5的示例代码我已经更新到Github,可以复用起来,基于官方的案例做了些改动,增加PC端打开时生成二维码方便手机扫码使用。 这次新能力的更新将使微信小程序不再局限于微信内部的流量,天花板被掀开啦。 而且短信和邮件营销的触达成本非常低,营销成本的压低也会催生出很多新的流量玩法,我们敬请期待吧。
2021-01-08 - FileSystemManager.readFile 如何获取读取的数据?
[图片] 使用该程序获得了一个文件的数据,怎么获取数据里面的内容,比如我想获得[[int8array]]下的第一个数“100” [图片] 代码片段和打印数据如图,求大佬帮忙 Orz Orz ..... 补充下图片 [图片] [图片] 补充解决图片 感谢大佬的回复 [图片] [图片]
2019-12-07 - swiper用flex:1来适应高度时,swiper-item高度继承默认150
代码大概如下 [代码]<[代码][代码]view[代码] [代码]class[代码][代码]=[代码][代码]"container"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]view[代码] [代码]class[代码][代码]=[代码][代码]"nav"[代码][代码]></[代码][代码]view[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]swiper[代码] [代码]class[代码][代码]=[代码][代码]"swiper"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]swiper-item[代码][代码]></[代码][代码]swiper-item[代码][代码]>[代码][代码] [代码][代码]</[代码][代码]swiper[代码][代码]>[代码][代码]</[代码][代码]view[代码][代码]>[代码][代码].container {[代码][代码] [代码][代码]width[代码][代码]: [代码][代码]100%[代码][代码];[代码][代码] [代码][代码]height[代码][代码]: [代码][代码]100%[代码][代码];[代码][代码] [代码][代码]display[代码][代码]: flex;[代码][代码] [代码][代码]flex-[代码][代码]direction[代码][代码]: column;[代码][代码] [代码][代码]justify-[代码][代码]content[代码][代码]:flex-start;[代码][代码]}[代码][代码].nav {[代码][代码] [代码][代码]width[代码][代码]: [代码][代码]100%[代码][代码];[代码][代码] [代码][代码]min-height[代码][代码]: [代码][代码]160[代码][代码]rpx;[代码][代码]}[代码][代码].swiper {[代码][代码] [代码][代码]flex: [代码][代码]1[代码][代码];[代码][代码]}[代码]然后swiper-item的高度100%就是默认的150px了,无法做到自适应。这情况只在ios出现,android并不会。
2017-06-30 - 关于小程序中swiper组件设置flex属性在IOS上的问题(解决方案)
小程序的swiper组件设置flex属性后,它的子组件swiper-item在IOS上会显示为默认的150px值,实验了各种方法,今天终于解决了问题,给大家分享一下! wxml代码: [代码]<[代码][代码]view[代码] [代码]id[代码][代码]=[代码][代码]"shelfMain"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]swiper[代码] [代码]id[代码][代码]=[代码][代码]"shelfGoods"[代码] [代码]current[代码][代码]=[代码][代码]"{{selectIndex}}"[代码] [代码]catchchange[代码][代码]=[代码][代码]"swiperChange"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]block[代码] [代码]wx:for[代码][代码]=[代码][代码]"{{shelfData}}"[代码] [代码]wx:for-item[代码][代码]=[代码][代码]"goods"[代码] [代码]wx:for-index[代码][代码]=[代码][代码]"shelfIndex"[代码] [代码]wx:key[代码][代码]=[代码][代码]"shelf"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]swiper-item[代码] [代码]class[代码][代码]=[代码][代码]"shelfItem"[代码] [代码]class[代码][代码]=[代码][代码]"swiperItem"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]template[代码] [代码]is[代码][代码]=[代码][代码]"shelfList"[代码] [代码]data[代码][代码]=[代码][代码]"{{goods,shelfIndex,orderList}}"[代码][代码]></[代码][代码]template[代码][代码]>[代码][代码] [代码][代码]</[代码][代码]swiper-item[代码][代码]>[代码][代码] [代码][代码]</[代码][代码]block[代码][代码]>[代码][代码] [代码][代码]</[代码][代码]swiper[代码][代码]>[代码][代码] [代码][代码]</[代码][代码]view[代码][代码]>[代码] 开始只在swiper设置flex布局,然后在真机测试中安卓手机是没有任何问题的,但是IOS出现了问题,就是IOS只显示了150px,就是swiper-item的高度; 1.第一步解决思路是在外层报上shelfMain 设置上flex 然后设置但swiper设置 width: 100%; height: 100%; 但是进入真机测试的话,只有IOS11以上可以正常显示,而低版本的IOS直接没有任何显示内容(其他的方法也是尝试了无数,哭哭哭) 2.祭出大招:使用一种css方式将其充满shelfMain的flex布局 [代码]#shelfMain {[代码][代码] [代码][代码]width[代码][代码]: [代码][代码]100%[代码][代码];[代码][代码] [代码][代码]flex: [代码][代码]1[代码][代码];[代码][代码] [代码][代码]position[代码][代码]: [代码][代码]relative[代码][代码];[代码][代码]}[代码] [代码]#shelfGoods {[代码][代码] [代码][代码]width[代码][代码]: [代码][代码]100%[代码][代码];[代码][代码] [代码][代码]height[代码][代码]: [代码][代码]100%[代码][代码];[代码][代码] [代码][代码]position[代码][代码]: [代码][代码]absolute[代码][代码];[代码][代码] [代码][代码]left[代码][代码]: [代码][代码]0[代码][代码];[代码][代码] [代码][代码]top[代码][代码]:[代码][代码]0[代码][代码];[代码][代码] [代码][代码]bottom[代码][代码]: [代码][代码]0[代码][代码];[代码][代码] [代码][代码]right[代码][代码]: [代码][代码]0[代码][代码]; [代码][代码]}[代码]使用这段CSS发现,神奇的事情发生了,直接全部OK,swiper充满了shelfMain的flex布局的所有地方,然后再IOS和安卓上都没有了任何问题 将这种解决方法提供出来,让大家避免坑
2017-07-14 - 小技巧!CSS 整块文本溢出省略特性探究
今天的文章很有意思,讲一讲整块文本溢出省略打点的一些有意思的细节。 文本超长打点 我们都知道,到今天(2020/03/06),CSS 提供了两种方式便于我们进行文本超长的打点省略。 感兴趣的小伙伴点击链接,了解详情~ http://github.crmeb.net/u/yi 对于单行文本,使用单行省略: { width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } [图片] 而对于多行文本的超长省略,使用 [代码]-webkit-line-clamp[代码] 相关属性,兼容性也已经非常好了: { width: 200px; overflow : hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } [图片] CodePen Demo -- inline-block 实现整块的溢出打点 问题一:超长文本整块省略 基于上述的超长打点省略方案之下,会有一些变化的需求。譬如,我们有如下结构: Sb Coco FEUIUX Designer前端工程师 [图片] 对于上述超出的情况,我们希望对于超出文本长度的整一块 -- 前端工程师,整体被省略。 如果我们直接使用上述的方案,使用如下的 CSS,结果会是这样,并非我们期待的整块省略: .person-card__desc { width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } [图片] 将 [代码]display: inline[代码] 改为 [代码]display: inline-block[代码] 实现整块省略 这里,如果我们需要实现一整块的省略,只需要将包裹整块标签元素的 [代码]span[代码] 的 [代码]display[代码] 由 [代码]inline[代码] 改为 [代码]inline-block[代码] 即可。 .person-card__desc span { display: inline-block; } [图片] 这样,就可以实现,基于整块的内容的溢出省略了。完整的 Demo,你可以戳这里: CodePen Demo - 整块超长溢出打点省略 问题二:iOS 不支持整块超长溢出打点省略 然而,上述方案并非完美的。经过实测,上述方案在 iOS 和 Safari 下,没能生效,表现为这样: [图片] 查看规范 - CSS Basic User Interface Module Level 3 - text-overflow,究其原因,在于 [代码]text-overflow[代码] 只能对内联元素进行打点省略。(Chrome 对此可能做了一些优化,所以上述非 iOS 和 Safari 的场景是正常的) 所以猜测是因为经过了 [代码]display: inline-block[代码] 的转化后,已经不再是严格意义上的内联元素了。 解决方案,使用多行省略替代单行省略 当然,这里经过试验后,发现还是有解的,我们在开头还提到了一种多行省略的方案,我们将多行省略的代码替换单行省略,只是行数 [代码]-webkit-line-clamp: 2[代码] 改成一行即可 [代码]-webkit-line-clamp: 1[代码]。 .person-card__desc { width: 200px; white-space: normal; overflow : hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; } .person-card__desc span { display: inline-block; } 这样,在 iOS/Safari 下也能完美实现整块的超长打点省略: [图片] CodePen Demo -- iOS 下的整块超长溢出打点省略方案 值得注意的是,在使用 [代码] -webkit-line-clamp[代码] 的方案的时候,一定要配合 [代码]white-space: normal[代码] 允许换行,而不是不换行。这一点,非常重要。 这样,我们就实现了全兼容的整块的超长打点省略了。 当然,[代码] -webkit-line-clamp[代码] 本身也是存在一定的兼容性问题的,实际使用的时候还需要具体去取舍。 最后 好了,本文到此结束,一个简单的 CSS 小技巧,希望对你有帮助 :) 感兴趣的小伙伴点击链接,了解详情~ http://github.crmeb.net/u/yi 作者:chokcoco
2021-03-15 - 微信小程序内嵌h5,在安卓手机中<video>标签没有声音。
h5用的是uniapp写的,就是<video>标签,任意端打开页面播放视频都可以播放且有声音。但内嵌在微信小程序webview中则没有声音。 测试视频链接:https://www.txkcr.com/api3/file/playNormalVideo?path=cwinfo/old/video/A4D8A7CCC8B0A9A05F957AED5F88C103D343B8E4.mp4 tips:链接只是举例,所有的视频链接皆是有相同原因。 补充描述:单独在微信打开h5不存在安卓播放没有声音问题,目前就是安卓手机存在小程序内嵌h5播放视频没声音。测试了华为,小米8,10等手机。
2021-04-26 - IOS新版canvas2d绘制圆形问题,不够圆像菊花
[图片]
2020-10-03 - canvas绘制圆以及其他图形在真机上变形,如何解决?
这个我刚开始以为是个bug,纠结了很多天。后来了解到原因有可能是因为手机设备的像素比的原因。直接上图。 [图片] 这个是模拟器上的图片! [图片] 这个是真机上的图片。 都变形了,各位大佬知道怎么解决吗? 网上的找不到解决方法
2020-09-26 - 低功耗蓝牙使用API设计封装函数模式示例
var bluetooth = { RESET: function(){ // 基础数据配置 this.btName = ""; this.deviceId = ""; this.serviceId = ""; this.write_characteristicId = ""; this.read_characteristicId = ""; clearTimeout(this.sendTimer); this.sendTimer = null; }, START: async function () { // 启动蓝牙,判断用户蓝牙是否已开启 }, SEARCH: async function () { // 搜索设备是否在附近,wx.onBluetoothDeviceFound 记得GPS权限,切勿频繁先调用GPS获取用户地理位置再搜索 await this.START(); return new Promise((reslove, reject)=>{ reslove(); }) }, CONNECT: async function () { // 连接设备 // if(self.btName == device.btName) let sameName = self.btName == device.btName ? true : false; // 记录蓝牙连接是否多次同时快速触发 if(this.waitConnect && sameName){ console.log("正在连接,请稍等...") return; } this.waitConnect = true; await this.SEARCH(); return new Promise((reslove, reject)=>{ this.waitConnect = false; reslove(); }) }, SEND: async function (device, data, callback) { // 发送数据 this.passCheck = device.passCheck //这样写,可以兼容连接设备中,发送指令1,但是连接过程中,又发送指令2,那么连接成功后,处理指令2 this.data= device.data this.callback = device.callback await this.CONNECT(); return new Promise((reslove, reject)=>{ device.sendEnd(); callback(); }) }, receiveDataCallback: function(){ // 接收设备返回的数据到前台 callback(value) }, CLOSE: async function () { // 关闭蓝牙线程 }, DISCONNECT: function(){ // 断开指定设备连接 }, STOP: function(){ // 停止搜索监听 }, ERROR: function(){ /*** * ERROR 错误 * err @params {} * err.ercode @params Number * 0 ok 正常 * 10000 not init 未初始化蓝牙适配器 * 10001 not available 当前蓝牙适配器不可用 * 10002 no device 没有找到指定设备 * 10003 connection fail 连接失败 * 10004 no service 没有找到指定服务 * 10005 no characteristic 没有找到指定特征值 * 10006 no connection 当前连接已断开 * 10007 property not support 当前特征值不支持此操作 * 10008 system error 其余所有系统上报的异常 * 10009 system not support Android 系统特有,系统版本低于 4.3 不支持 BLE * 10012 operate time out 连接超时 * 10013 invalid_data 连接 deviceId 为空或者是格式不正确 */ }, } var device = { btName: "btName", deviceId: "AB:CD:EF:00:00:01", // 实践中设备端地址请勿以 00 开头 00:00:00:AB:CD:EF passCheck: new Date().getTime(), // 记录触发跟设备返回是否为同一事件 sendEnd: function(res){ // 用于记录发送数据给设备成功后,设备一直未返回执行相关命令 clearTimeout(bluetooth.sendTimer); bluetooth.sendTimer = setTimeout(() => { clearTimeout(bluetooth.sendTimer); bluetooth.CLOSE(); }, timeout); }, onBLEConnectionStateChange: function(res){ // 用于监听蓝牙设备操作过程中,设备主动断开(例如:突然把设备断电或手动断开蓝牙捕获异常处理) // if(device.passCheck == ) }, capture: function(err){ // 用于获取操作过程中,蓝牙未启动,操作过程中连接失败或连接操作过程中出现的异常 // if(device.passCheck == ) } } // 使用示例 let data = "00 11 22"; bluetooth.START(device); bluetooth.SEARCH(device); bluetooth.CONNECT(device); bluetooth.SEND(device, data, function (value) { console.log("value=>",value) // 用于收到设备返回数据回调处理 if(value){ bluetooth.passCheck = ""; bluetooth.CLOSE(); } }) 针对连接问题,方法推荐: // timeout 针对特殊手机,如果发现首次连接铁定失败,或首次连接超时较多,可以将时间首次连接改到小于一秒,这样第二次连接timeout=10s, // 成功率较多, // 这种做法可以减少因差手机第一次连太久出现用户手动关闭的情况。毕竟一秒能连上的手机都是性能较好,安卓版本较高的手机。 var allowWaitTime = 15 * 1000; var timeout = 10 * 1000; var startCreateTime = new Date().getTime(); function createBLEConnection(){ wx.createBLEConnection({ // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接 timeout: timeout, // number 否 超时时间,单位ms,不填表示不会超时 deviceId: self.deviceId, // serial: false, // 会闪退的 success(res) { // console.log("createBLEConnection res=>",res) }, fail(err) { // console.log("createBLEConnection err=>",err) let useCreateTime = new Date().getTime() - startCreateTime; // 这样写正常情况下都会按时返回的,例如,请问你的蓝牙 // 连设备多长时间后超时,你可以根据timeout 回答。但这种误差可能造成你无法提供解释的情况,无奈下推荐写个时间计算器, // 时间一到,不管成功与否都弹出失败提示。哪怕最后一秒连上了,也弹出失败。(无奈,无奈,无奈)可以减少与非同行讲解误差。 if (err.errCode == 10012) { // 连接超时,可能 if(useCreateTime >= allowWaitTime) { self.ERROR(err); self.CLOSE(); }else{ setTimeout(()=>{ createBLEConnection(); }, t ); // t 根据测试数据,效果来定 } }else { // (err.errCode == 10003) // (err.errCode == -1) // 10003 底层蓝牙失败,处理大体思路 CLOSE(); START(); CREATE(); } }); } createBLEConnection(); 代码片段示例 https://developers.weixin.qq.com/s/qJ6lORmy7LpS github https://github.com/synctimes163/wxapp-bluetooth
2021-04-26 - @keyframes 动画在ios上没效果,安卓和工具ok
用css3动画做了一个倒计时,本来以为找到了比较简单的方法完成了,但是发现在ios上没有效果,在工具和安卓机都是可以的,求解! [图片]
2019-09-19 - 如何获取到音频文件是时长,duration获得是0
this.innerAudioContext.src = data.sound; let duration = this.innerAudioContext.duration; console.log(duration) 输出来的是0
2019-06-06 - 解决小程序中webview页面多层history返回问题
小程序开发中遇到的问题:小程序中嵌套了一个webview页面,webview页面中有静默授权(A1页面静默授权后重定向到A2页面),点小程序原生的返回按钮会返回到A1页面,然后页面就会反复静默授权 预期表现:点小程序原生的返回按钮后返回到小程序上个页面 解决方案:通过[代码]history.pushState[代码]添加历史记录名目,[代码]history.onpopstate[代码]监听历史记录条目发生变化时,调用小程序API[代码]wx.navigateBack[代码] [代码]window.addEventListener('popstate', (event) => { wx.miniProgram.navigateBack(); }); const code = getSearch('code'); // 伪代码,获取查询参数 if (!code) { // 页面A1 if (isWeixin()) { // 微信环境 const redirectUrl = window.location.href + '&code=1'; window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize' + '?appid=' + appId + '&redirect_uri=' + encodeURIComponent(redirectUrl) + '&response_type=code&scope=snsapi_userinfo' + '#wechat_redirect'; // 静默授权伪代码 } else { alert('当前不是微信环境'); } } else { // 页面A2 history.pushState({page: 1}, null, window.location.href); } [代码] 刚开始想的解决办法是用localStorage,跳转到A2时存储一个值,返回到A1时获取这个值,如果有值就清除这个值并且回退到小程序页面。听起来似乎也可行,但小程序的缓存和微信的缓存是同步的,如果在微信环境中直接访问A1页面,重定向到A2会存值,如果直接关闭页面,不会被清除,那么在小程序中访问时就直接回退了。
2019-08-19 - 微信小程序webview长按图片无法唤起微信的保存图片选项
问题描述: 小程序出现长按小程序webview的图片唤起不了微信的保存图片,如下图: [图片]。 正常情况如下: [图片] 用户设备信息如下: [图片] 注意:据说是韩版的iphone 目前无法预知会影响到多少用户
2020-04-30 - 小程序取消橡皮筋回弹效果解决方案及坑总结
提到ios系统的橡皮筋效果,作为开发者是又爱又恨,有想要这个效果又有不想要的,无奈的是却没有一个简单的开关来设置这个效果是否开启。 最近在开发小程序时也遇到有关于ios橡皮筋回弹的问题,这里分两部分(取消橡皮筋回弹效果和因为这个效果遇到的坑)和大家分享一下。 取消IOS橡皮筋回弹效果的解决方案 1) 页面无滚动区域时,可通过页面json配置文件设置disableScroll:true禁止整个页面滚动,从而取消橡皮筋效果。 [代码]{ "disableScroll":true } [代码] 测试代码:https://github.com/YuniorZen/minicode-debug/tree/master/minicode01/pages/demo1 2) 页面有滚动区域,滚动区域通过view模拟实现,然后在页面json配置文件设置disableScroll:true禁止整个页面滚动,从而取消橡皮筋效果。 [代码]json文件配置 { "disableScroll":true } view元素模拟实现滚动样式 { height: calc(100vh - 120rpx); //高度必须是固定的值 overflow-y: auto; } [代码] 不足之处在于view元素模拟的滚动区域滚动时不够连贯,没有scroll-view那种原生丝滑般的感觉。 测试代码:https://github.com/YuniorZen/minicode-debug/tree/master/minicode01/pages/demo2 3) 页面有滚动区域,滚动区域使用scroll-view,这时通过disableScroll则无法实现,尝试设置一下scroll-view的scroll-y="{{false}}",上拉或下拉时居然不再触发橡皮筋的回弹啦,当然滚动区域也不能滚动。 小脑袋动一动,解决方法有啦! 通过设置一个变量scrollY动态控制滚动区域的滚动从而阻止回弹。 监听bindscrolltoupper\bindscrolltolower当scroll-view区域滚动到顶部或底部时候设置scrollY:false来关闭页面滚动,从而阻止回弹。 监听bindtouchstart\bindtouchmove 当用户反方向滑动的时候设置scrollY:true,再次开启页面滚动。 [代码]wxml滚动区域属性和事件处理,具体实现请点击测试代码链接 <scroll-view scroll-y="{{scrollY}}" class="list" upper-threshold="5" lower-threshold="5" bindscrolltoupper="bindscrolltoupper" bindscrolltolower="bindscrolltolower" bindtouchstart="touchstart" bindtouchmove="touchmove"> <view class="list-item" wx:for="{{list}}" wx:key="{{index}}">{{item}}</view> </scroll-view> [代码] 相对view模拟实现滚动区域,scroll-view滚动更丝滑,不过每次滚动到底部或顶部的时候,再反向滑动时由于再次开启scroll-view滚动会有操作卡顿的感觉,暂时没想到好的解决方法,有解决的大佬希望提供一下想法,一起学习下。 测试代码:https://github.com/YuniorZen/minicode-debug/tree/master/minicode01/pages/demo3 IOS橡皮筋效果遇到的坑 1) 操作左滑删除组件时上下移动,会触发橡皮筋效果导致页面抖动的问题 这个坑的严重程度看设计师的意愿了,反正我们团队目前是需要解决的,方案类似取消橡皮筋解决方案的第三种 在左滑的时候关闭scroll-view的滚动,取消时再次开启滚动 2) 如果页面顶部有置顶的横向滚动区域scroll-view,当页面滚动到底部时继续上拉会导致置顶头部消失,松开回弹后头部又会出现。 坑是社区里的朋友提出来的,我借了个iphone x 一预览,我嚓,还是真是个奇坑! 微信官方回复已复现正在解决中… 不想继续等下去的,暂时解决方法是 监听页面的滚动区域,当滚动到底部时设置顶部横向滚动scroll-view的scroll-x=false来解决。 写在最后 以上便是我在小程序开发中有关于ios橡皮筋回弹效果的分享,示例代码已上传github,可自行下载体验。 https://github.com/YuniorZen/minicode-debug/tree/master/minicode01 目前微信官方虽说已经着手解决(已两年)此类bug,但哪吒说 我命由我不由天,所以还是我们开发者多分享些解决方案自救来的快。 分享方案如有问题还望不吝指出,没有涉及到的坑也欢迎评论提出,一起学习和解决,后续也会基于此篇不断更新总结。
2021-01-14 - [打怪升级]小程序自定义头部导航栏“完美”解决方案
[图片] 为什么要做这个? 主要是在项目中,智酷君发现的一些问题 一些页面是通过扫码和订阅消息访问后,没有直接可以点击去首页的,需要添加一个home链接 需要添加自定义搜索功能 需要自定义一些功能按钮 [图片] 其实,第一个问题,在最近的微信版本更新中已经优化了,通过 小程序模板消息 过来的,系统会自动加上home按钮,但对于其他的访问方式则没有支持~ 一个不大不小的问题:两边ICON不对齐问题 [图片] 智酷君之前尝试了各种解决方法,发现有一个问题,就是现在手机屏幕太多种多样,有 传统头部、宽/窄刘海屏、水滴屏等等,无法八门,很多解决方案都无法解决特殊头部,系统**“胶囊按钮”** 和 自定义按钮在Android屏幕可能有 几像素不对齐 的问题(强迫症的噩梦)。 下面分享下一个相对比较完善的解决方案: [图片] 小程序代码段DEMO Link: https://developers.weixin.qq.com/s/cuUaCimT72cH ID: cuUaCimT72cH 智酷君做了一个demo代码段,方便大家直接用IDE工具查看源码~ [图片] 页面配置 1、页面JSON配置 [代码]{ "usingComponents": { "NavComponent": "/components/nav/common" //以插件的方式引入 }, "navigationStyle": "custom" //自定义头部需要设置 } [代码] 如果需要自定义头部,需要设置navigationStyle为 “custom” 2、页面代码 [代码]<!-- home 类型的菜单 --> <NavComponent v-title="自定义头部" bind:commonNavAttr="commonNavAttr"></NavComponent> <!-- 搜索菜单 --> <NavComponent is-search="true" bind:commonNavAttr="commonNavAttr"></NavComponent> [代码] 可以在自定义导航标签上添加属性配置来设置功能,具体按照实际需要来 3、目录结构 [代码]│ ├─components │ └─nav │ common.js │ common.json │ common.wxml │ common.wxss │ ├─images │ back.png │ home.png │ └─index index.js index.json index.wxml index.wxss search.js search.json search.wxml search.wxss [代码] 仅供参考 插件对应的JS部分 components/nav/common.js部分 [代码]const app = getApp(); Component({ properties: { vTitle: { type: String, value: "" }, isSearch:{ type: Boolean, value: false } }, data: { haveBack: true, // 是否有返回按钮,true 有 false 没有 若从分享页进入则没有返回按钮 statusBarHeight: 0, // 状态栏高度 navbarHeight: 0, // 顶部导航栏高度 navbarBtn: { // 胶囊位置信息 height: 0, width: 0, top: 0, bottom: 0, right: 0 }, cusnavH: 0, //title高度 }, // 微信7.0.0支持wx.getMenuButtonBoundingClientRect()获得胶囊按钮高度 attached: function () { if (!app.globalData.systeminfo) { app.globalData.systeminfo = wx.getSystemInfoSync(); } if (!app.globalData.headerBtnPosi) app.globalData.headerBtnPosi = wx.getMenuButtonBoundingClientRect(); console.log(app.globalData) let statusBarHeight = app.globalData.systeminfo.statusBarHeight // 状态栏高度 let headerPosi = app.globalData.headerBtnPosi // 胶囊位置信息 console.log(statusBarHeight) console.log(headerPosi) let btnPosi = { // 胶囊实际位置,坐标信息不是左上角原点 height: headerPosi.height, width: headerPosi.width, top: headerPosi.top - statusBarHeight, // 胶囊top - 状态栏高度 bottom: headerPosi.bottom - headerPosi.height - statusBarHeight, // 胶囊bottom - 胶囊height - 状态栏height (胶囊实际bottom 为距离导航栏底部的长度) right: app.globalData.systeminfo.windowWidth - headerPosi.right // 这里不能获取 屏幕宽度,PC端打开小程序会有BUG,要获取窗口高度 - 胶囊right } let haveBack; if (getCurrentPages().length != 1) { // 当只有一个页面时,并且是从分享页进入 haveBack = false; } else { haveBack = true; } var cusnavH = btnPosi.height + btnPosi.top + btnPosi.bottom // 导航高度 console.log( app.globalData.systeminfo.windowWidth, headerPosi.width) this.setData({ haveBack: haveBack, // 获取是否是通过分享进入的小程序 statusBarHeight: statusBarHeight, navbarHeight: headerPosi.bottom + btnPosi.bottom, // 胶囊bottom + 胶囊实际bottom navbarBtn: btnPosi, cusnavH: cusnavH }); //将实际nav高度传给父类页面 this.triggerEvent('commonNavAttr',{ height: headerPosi.bottom + btnPosi.bottom }); }, methods: { _goBack: function () { wx.navigateBack({ delta: 1 }); }, bindKeyInput:function(e){ console.log(e.detail.value); } } }) [代码] 解决不同屏幕头部不对齐问题的终极办法是 wx.getMenuButtonBoundingClientRect() 这个方法从微信7.0.0开始支持,通过这个方法我们可以获取到右边系统胶囊的top、height、right等属性,这样无论是水滴屏、刘海屏、异形屏,都能完美对齐右边系统默认的胶囊bar,完美治愈强迫症~ APP.js 部分 [代码]//app.js App({ /** * 加载页面 * @param {*} options */ onShow: function (options) { }, onLaunch: async function () { let self = this; //设置默认分享 this.globalData.shareData = { title: "智酷方程式" } // this.getSysInfo(); }, globalData: { //默认分享文案 shareData: {}, qrCodeScene: false, //二维码扫码进入传参 systeminfo: false, //系统信息 headerBtnPosi: false, //头部菜单高度 } }); [代码] 将获取的参数存储在一个全局变量globalData中,可以减少反复调用的性能消耗。 插件HTML部分 [代码]<view class="custom_nav" style="height:{{navbarHeight}}px;"> <view class="custom_nav_box" style="height:{{navbarHeight}}px;"> <view class="custom_nav_bar" style="top:{{statusBarHeight}}px; height:{{cusnavH}}px;"> <!-- 搜索部分--> <block wx:if="{{isSearch}}"> <input class="navSearch" style="height:{{navbarBtn.height-2}}px;line-height:{{navbarBtn.height-4}}px; top:{{navbarBtn.top+1}}px; left:{{navbarBtn.right}}px; border-radius:{{navbarBtn.height/2}}px;" maxlength="10" bindinput="bindKeyInput" placeholder="输入文字搜索" /> </block> <!-- HOME 部分--> <block wx:else> <view class="custom_nav_icon {{!haveBack||'borderLine'}}" style="height:{{navbarBtn.height}}px;line-height:{{navbarBtn.height-2}}px; top:{{navbarBtn.top}}px; left:{{navbarBtn.right}}px; border-radius:{{navbarBtn.height/2}}px;"> <view wx:if="{{haveBack}}" class="icon-back" bindtap='_goBack'> <image src='/images/back.png' mode='aspectFill' class='back-pre'></image> </view> <view wx:if="{{haveBack}}" class='navbar-v-line'></view> <view class="icon-home"> <navigator class="home_a" url="/pages/home/index" open-type="switchTab"> <image src='/images/home.png' mode='aspectFill' class='back-home'></image> </navigator> </view> </view> <view class="nav_title" style="height:{{cusnavH}}px; line-height:{{cusnavH}}px;"> {{vTitle}} </view> </block> </view> </view> </view> [代码] 主要是对几种状态的判断和定位的计算。 插件CSS部分 [代码]/* components/nav/test.wxss */ .custom_nav { width: 100%; background: #3a7dd7; position: relative; z-index: 99999; } .custom_nav_box { position: fixed; width: 100%; background: #3a7dd7; z-index: 99999; border-bottom: 1rpx solid rgba(255, 255, 255, 0.3); } .custom_nav_bar { position: relative; z-index: 9; } .custom_nav_box .nav_title { font-size: 28rpx; color: #fff; text-align: center; position: absolute; max-width: 360rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; top: 0; left: 0; right: 0; bottom: 0; margin: auto; z-index: 1; } .custom_nav_box .custom_nav_icon { position:absolute; z-index: 2; display: inline-block; border-radius: 50%; vertical-align: top; font-size:0; box-sizing: border-box; } .custom_nav_box .custom_nav_icon.borderLine { border: 1rpx solid rgba(255, 255, 255, 0.3); background: rgba(0, 0, 0, 0.1); } .navbar-v-line { width: 1px; margin-top: 14rpx; height: 32rpx; background-color: rgba(255, 255, 255, 0.3); display: inline-block; vertical-align: top; } .icon-back { display: inline-block; width: 74rpx; padding-left: 20rpx; vertical-align: top; /* margin-top: 12rpx; vertical-align: top; */ height: 100%; } .icon-home { /* margin-top: 8rpx; vertical-align: top; */ display: inline-block; width: 80rpx; text-align: center; vertical-align: top; height: 100%; } .icon-home .home_a { height: 100%; display: inline-block; vertical-align: top; width: 35rpx; } .custom_nav_box .back-pre, .custom_nav_box .back-home { width: 35rpx; height: 35rpx; vertical-align: middle; } .navSearch { width: 200px; background: #fff; font-size: 14px; position: absolute; padding: 0 20rpx; z-index: 9; } [代码] 总结: 通过微信API: getMenuButtonBoundingClientRect(),结果各类手机屏幕的适配问题 将算好的参数存储在全局变量中,一次计算全局使用,爽YY~ 往期回顾: [填坑手册]小程序PC版来了,如何做PC端的兼容?! [填坑手册]小程序Canvas生成海报(一) [拆弹时刻]小程序Canvas生成海报(二)
2021-09-13 - 安卓webview location.reload()无效?
小程序内嵌的H5网页,有个按钮是结束功能的,点击后执行ajax,成功后location.reload()刷新页面。ios能刷新,安卓不行。
2019-10-28 - 页面打开时动态设置scroll-view scroll-into-view的值
触发绑定的点击事件时,可以动态设置scroll-into-view的值,此时scroll-view可进行锚点滚动。但是如果是打开页面时想让scroll-view滚动到指定的位置,需要确定容器内列表数据完全渲染完成,因此需要在数据绑定后再设置scroll-into-view的值,比如代码如下: that.setData({ cates:list,//列表数据 toView: 'y' + id //滚动到指定元素的id的值,中文与数字开头不支持,因此需要英文字母开头 })
2018-05-16