- 小程序拖动浮窗组件的一种实现(可二次封装业务组件使用)
文档 Fab 浮动按钮 可拖动的悬浮窗按钮 Props 参数 说明 类型 可选值 默认值 position 距离对象 Boolean – {left:0,right:0,top:0,bottom:0} left 左边距离(无需单位) Number – 0 right 右边距离(无需单位) Number/String – 0 top 顶部距离(无需单位) Number/String – 0 bottom 底部距离(无需单位) Number/String – 0 h-margin 拖动后的水平方向最小边距(左右边距) Number/String – 10px v-margin 拖动后的垂直方向最小边距(上下边距) Number/String – 10px 注:rpx单位对应的是750的屏幕,上述属性取值使用375下的数值,如果是750设计稿在使用时需手动除2传入 浮动按钮位置仅推荐left、top / right 、bottom 两两使用,默认优先使用bottom、right配置 Slots name 说明 default 悬浮窗默认插槽,用户可自定义内容及大小 Events 无 Methods 无 使用示例 支持二次封装业务组件以复用 [代码]<!-- 375设计稿下位于右下10rpx、100rpx的浮动按钮 --> <c-fab bottom="100" right='10'> <view class="float" style="width:100rpx;height:100rpx;border-radius: 99em;background:#fad84c;color:#333;display:flex;align-items:center;justify-content: center;">活动</view> </c-fab> [代码] 完整实现代码 [代码]<movable-area> <movable-view bind:touchend="onTouchend" bind:touchmove="onTouchMove" bind:touchstart="addAnimation" animation="{{animation}}" style="width:{{elementWidth}}px;height:{{elementHeight}}px" x="{{x}}" y="{{y}}" direction="all"> <view class="float-box" > <slot></slot> </view> </movable-view> </movable-area> [代码] [代码]Component({ /** * 组件的属性列表 */ properties: { position: { type: Object, value: { left: 0, right: 0, bottom: 0, top: 0 } // left、top、right、bottom }, left: { type: Number, value: 0 }, right: { type: Number, value: 0 }, top: { type: Number, value: 0 }, bottom: { type: Number, value: 0 }, hMargin: { // 拖动后的水平方向最小边距(左右边距) type: Number, value: 10 }, vMargin: { // 拖动后的垂直方向最小边距(上下边距) type: Number, value: 10 } }, data: { x: 999, y: 999, windowWidth: wx.getSystemInfoSync().windowWidth, windowHeight: wx.getSystemInfoSync().windowHeight, elementWidth: 0, elementHeight: 0, animation: false, isMoved: false // 是否拖动 }, lifetimes: { attached() { // 初始化位置 wx.createSelectorQuery().in(this).select('.float-box').boundingClientRect().exec((res) => { console.log(233, res); this.data.elementWidth = res[0].width; this.data.elementHeight = res[0].height; if (this.properties.position.left || this.properties.left) { this.data.x = this.properties.position.left || this.properties.left; } if (this.properties.position.right || this.properties.right) { this.data.x = this.data.windowWidth - this.data.elementWidth - (this.properties.position.right ? this.properties.position.right : this.properties.right); } if (this.properties.position.top || this.properties.top) { this.data.y = this.properties.position.top || this.properties.top; } if (this.properties.position.bottom || this.properties.bottom) { this.data.y = this.data.windowHeight - this.data.elementHeight - (this.properties.position.bottom ? this.properties.position.bottom : this.properties.bottom); } this.setData({ elementWidth: this.data.elementWidth, elementHeight: this.data.elementHeight, x: this.data.x, y: this.data.y }); }); } }, /** * 组件的方法列表 */ methods: { onTouchend(e) { console.log(this.data.isMoved, this.data.x, e.changedTouches[0].clientX, this.data.elementWidth); if (!this.data.isMoved) return; const currentX = e.changedTouches[0].clientX; let currentY = e.changedTouches[0].clientY; if (currentY <= this.properties.vMargin) { currentY = this.properties.vMargin + this.data.elementHeight / 2; } if (currentY >= this.data.windowHeight - this.properties.vMargin) { currentY = this.data.windowHeight - this.properties.vMargin - this.data.elementHeight / 2; } if (currentX + this.data.elementWidth / 2 > this.data.windowWidth / 2) { this.setData({ x: this.data.windowWidth - this.properties.hMargin - this.data.elementWidth, y: currentY - this.data.elementHeight / 2 }); } if (currentX + this.data.elementWidth / 2 <= this.data.windowWidth / 2) { this.setData({ x: this.properties.hMargin, y: currentY - this.data.elementHeight / 2 }); } }, addAnimation() { this.data.isMoved = false; if (!this.data.animation) { this.setData({ animation: true }); } }, onTouchMove() { this.data.isMoved = true; } } }); [代码] [代码]movable-area { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 50; movable-view { pointer-events: auto; //可以点击 } .float-box { display: inline-block; } } [代码] [代码]{ "component": true, "usingComponents": {} } [代码]
2024-01-18 - 小程序设计规范总结
一、设计稿用二倍图 UI设计师都喜欢用一倍图,但为什么用一倍图,方便适配是表面现象,真正原因是开发用的开发工具支持一倍图开发,开发不用再换算数值了。而小程序的开发工具不支持一倍图开发,支持二倍图开发。小程序里的尺寸单位叫 rpx,可以根据屏幕宽度进行自适应。在750*1334的设计稿里,1px = 1rpx。 [图片] 如果你心疼你的开发小哥哥,让他少掉点头发,设计稿用750*1334的尺寸。但如果你的开发小哥哥之前老欺负你,那你就看着办吧,他都能搞定。 [图片] 二、切图只需切750的尺寸 设计稿用二倍图做的(750 * 1334), 只需给一倍的切片;如果是按一倍图设计的(375 * 667),只要给二倍的切图。真的不管其它尺寸吗?不是不想管,而是小程序的开发工具不支持。 三、导航栏不要自定义 标准高度:128rpx 小程序很轻量,同时也有很多限制。导航栏不能自定义就是其中之一,能改变的只有颜色。 [图片] 这是官方的意思,但是,要改也是可以的,需要客户端版本是6.6.0以上,而且下拉会使整个页面下拉,也不好维护。 [图片] 你会说这不有小程序已经使用了嘛,是,这个小程序叫汪卡,现在,他们已经改回来了。所以,你也别难为你的开发小哥哥了。 [图片] 四、标签栏爱素颜 这个标准名称叫:标签分页导航,标准高度:98rpx,简称标签栏。 1. 偷笑别人花了脸 又是一个安静的晚上,一个人窝在公司里设计,我承认这样真的很无奈,和其它小程序一样。听说你还在搞什么原创,加个投影来点渐变,自以为这样很棒简直无懈可击。结果开发小哥哥哭了,我相信是很美美的图,但是开发做不到啊,那种表情可以想象。 [图片] 虽然也可以,做点其它形态,那就拜托别让开发见到你。如果再能看到你,一定就是这么说,原生控件好处多多***能用它。不用担心出问题,不用维护怕麻烦。 2. 图标只要81rpx 还是一个安静的晚上,还是我在做设计,这次我真的按耐不住,和其它小程序一样。听说你又再搞什么原创,中间图标变大大,破形破形再破形,燃烧开发脑细胞。 [图片] 但是,要知道,图标只要81rpx,小于大于都变形,一定记得规格框。数量只能2至5,多了少了不算数,你只能去改图标,其它组件说了算。 五、弹窗不覆盖导航跟标签 在小程序里导航栏跟标签栏的层级是最高的,以至于享受惯最高待遇的弹窗在这里,也要臣服于他们。 [图片] 六、视频限时多 小程序对视频的支持不是特别的好,原则上在滚动控件里不能放视频,而且微信官方文档里是这样要求的。这点我也像我们开发小哥哥求证,确实是这样,优酷和腾讯视频都是将视频固定。 [图片] 但其实吧,这点已经被有些公司攻克了,比如开眼跟京东。攻克是攻克了,但是体验不怎么好。如果公司产品需要放视频,建议专门新开一个页面,视频部分***不要有左右滚动。 七、一稿适配 iPhone X 怎么办,安卓怎么办,这些都不用再设计了,开发小哥哥都能搞定,相信他们。 [图片] 八、关于设计资源 微信官方虽然有提供,但是更新时间停留在了2016年,没有现在新版的小程序样式,和现在的区别就在顶部导航栏上。
2019-08-05 - 微信网页授权能力调整公告
微信网页授权 能力是为了优化用户在微信内登录网站应用的体验而设计的。为进一步规范能力使用,保障用户合法权益,平台将对能力进行调整。 当开发者在网页中在不规范使用发起 snsapi_userinfo 网页授权时,微信将默认打开网页快照页模式进行基础浏览。能力调整将于 2022 年 7 月 12 日 24 时生效。 网页快照页模式介绍快照页将会默认对用户屏蔽网页授权弹窗,用户在快照页中仅可进行滑动浏览操作,其他交互将被限制,并提示用户 “该网页需获取个人信息才可使用完整服务,当前仅可浏览部分内容”。用户如需要使用完整网页服务,可轻触右下角 “使用完整服务” 按钮触发授权弹窗,用户确认后进入原网页。 开发者在快照页内所获取的头像、昵称、openId、unionId 均为虚拟账号数据;快照页与正常页面不共用缓存,快照页的缓存会在用户离开快照页时被清理;快照页内也无法使用微信其它 JS-SDK 的能力。 [图片] 微信网页授权规范授权流程需引导清晰、准确:在申请获取用户信息的弹窗出现前,应该清晰、准确地告知用户获取信息的范围及获取信息的目的;必要场景申请:在必须获取用户信息时才申请,而不是用户尚未了解服务前就强制弹窗。如使用医院挂号时才需要获取用户信息;不强制登录:提供游客模式,供用户了解网页提供的基础服务,不强制用户允许网页获取用户信息后才能使用网页服务。 常见的微信网页授权不规范使用案例强制登录:在用户打开网页时立即要求用户授权,用户拒绝后无法使用网页提供的服务;违规收集个人信息:未在网页提前告知使用个人信息的目的、方式和范围;非必要收集:非必要获取用户信息的网页,如文章、视频等,要求用户在浏览内容前登录;差别对待微信用户:同样的网页在浏览器内可以无需登录直接访问,在微信内却要求用户先登录才可访问。 微信团队 2022年5月9日
2022-05-10 - 网页授权快照bug
自从公众号平台当开发者在网页中在不规范使用发起 snsapi_userinfo 网页授权时,微信将默认打开网页快照页模式进行基础浏览。 能力调整将于 2022 年 7 月 12 日 24 时生效。这个功能上线以后,用户扫码登录模式就存在了快照模式,我们在系统实际运行过程中发现,IOS可以直接唤起授权弹窗提示,但是部分安卓手机没有弹窗,而是直接进入了快照模式,进入快照模式以后,微信端直接把虚拟用户数据回传到我们的服务器上了,但是我们在日志记录发现了一个问题,就是大量的快照模式用户,返回的虚拟用户的unionid不是唯一的,而是出现了重复,大量的扫码用户,扫码以后返回的同一个unionid,进而导致我们出现了大量微信出现串号的情况,出现了多人操作一个账号的情况,[图片]这个是我们的日志记录的微信返回数据的情况,这个unionid我们服务器已经接到了2天我们就接到77次微信回调(而且这个日志是我们刚刚加的),021YJDkl230dG94G6Ool2u3be32YJDkn这个是获取用户时间使用的access_token 获取的数据{"openid":"oiA3t0WXfhKSHk894Lo06lE30dK8","nickname":"\u5fae\u4fe1\u7528\u6237","sex":0,"language":"","city":"","province":"","country":"","headimgurl":"https:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/Q3auHgzwzM7uZ2A8XfpHpssIojTfnOPoJyALNYf9MTAibYoFbKjm8jV2ZGXKibHSQkozoyA9tpIczhfnHcLPYbOw\/132","privilege":[],"unionid":"oGPI3uI_drExcXUUDMY783kt4J0Q"}。我们使用的appid是wxe5ae19b322c2c83b 请问这个快照模式是否有问题,为什么多人扫码默认快照模式 返回的虚拟用户的unionid为什么不唯一? [图片]只要扫码出现了这个页面,我们的服务器就会收到微信端回调,回调的数据就是我以上反馈的unionid不唯一,这边还有大量的unionid不唯一的数据,希望官方大佬,尽快现身啊
2022-08-10 - swiper设置圆角在真机上不显示
在模拟器中的效果: [图片] 在真机上面的效果: [图片]
2018-07-09 - 小程序分享的卡片间隙性不能再次转发
- 问题描述:小程序里分享到群或者个人的卡片,长按卡片后,有时候可以出现 发送给朋友,有时候不出现 发送给朋友。 - 预期效果:发送到群或者个人的卡片,长安卡片后,出现 发送给朋友 ,发送后,长按该卡片,还可以 发送给朋友。
2019-02-19 - ios12下,h5页面在微信浏览器内,事件混乱
在ios12的系统的手机里,h5的移动端页面,在微信浏览器内打开后,会出现乱七八糟的bug问题,例如,点击文本框后输入文字后,其他的点击按钮就无法点击,点击输入框后悔触发羡慕的按钮事件,会偶尔突然整个页面的点击事件都无法触发,一大堆乱七八糟的问题,各种神奇的bug,不是这里不能点,就是点了这里触发哪里的事件,不然就是文本框无法输入
2018-12-13 - 运行小程序偶尔出现的错误提示TypeError: Cannot read pro
- 当前 Bug 的表现(可附上截图) - 预期表现 - 复现路径 - 提供一个最简复现 Demo 不总出现,四五次出现一次,怎么解决求助 TypeError: Cannot read property 'beforeAll' of undefined at WAService.js:12 at n (WAService.js:6) at e (appservice?t=1556594641410:1680) at r.registerCallback.t (appservice?t=1556594641410:1680) at u.forEach.t (appservice?t=1556594641410:1680) at Array.forEach (<anonymous>) at appservice?t=1556594641410:1680 at WebSocket.a.onmessage (appservice?t=1556594641410:1680)
2019-04-30 - 微信小程序三种授权登录的方式
经过一段时间对微信小程序的研发后 总结出以下三种授权登录的方式,我给他们命名为‘一次性授权’‘永久授权’‘不授权’ 1.一次性授权 常规写法,需要获取用户公开信息(头像,昵称等)时,判断调取授权登录接口,但是此方法如果不经处理的话 用户如果拒绝授权或者删除该微信小程序后 需要重新调取并获取用户公开信息(头像,昵称等),此方法用户体验较差,不建议使用; 2.永久授权 在不必要使用用户公开信息(头像,昵称等)时,不调取授权登录接口,只有在必要的时候再去判断调取授权登录接口并把获取到的用户公开信息存入数据库,这样在每次登录时直接先运行指定函数从数据库索取需要的用户公开信息(头像,昵称等)即可,此方法在删除小程序后不用再次去授权登录(因为在用户第一次授权登录时已经把用户的公开信息存入数据库了以后直接向数据库索取即可),建议使用; 3.不授权 不需要授权登录获取用户公开信息(头像,昵称等),使用wx.login获取用户code并传入后台,后台可以通过用户的code值向微信要一个值(具体需要问后台,我只是个小前端,后台的东西不是很懂,只是知道一些逻辑而且也已经成功实现)然后通过这个用code换取的值就可以识别到指定用户,如果需要的话,前端要显示的头像、昵称等这些信息可以使用自定义可编辑的功能,当然,也可以通过<open-data type=“userAvatarUrl”></open-data><open-data type=“userNickName”></open-data>小程序提供的这个组件显示用户的头像及昵称(不过这个组件只有显示功能),用户如果想直接使用自己的头像昵称,也可以自行授权(比如添加个引导按钮什么之类的),建议使用; [图片][图片] 文中使用的微信自带接口、组件及函数: <open-data type=“userAvatarUrl”></open-data> <open-data type=“userNickName”></open-data> wx.login({ success(res){ console.log(res.code) } }) 微信授权登录 以上三种方式可以灵活运用,也可以把需要的结合到一起,并不冲突; 当然,大佬很多,我也只是个小前端而已,第一次发表技术方面的帖子,希望互相学习,互相指导,如有说的不对的地方还望大佬们及时指出!!! 谢谢
2019-04-18