- 微信小程序UI组件库合集
UI组件库合集,大家有遇到好的组件库,欢迎留言评论然后加入到文档里。 第一款: 官方WeUI组件库,地址 https://developers.weixin.qq.com/miniprogram/dev/extended/weui/ 预览码: [图片] 第二款: ColorUI:地址 https://github.com/weilanwl/ColorUI 预览码: [图片] 第三款: vantUI(又名:ZanUI):地址 https://youzan.github.io/vant-weapp/#/intro 预览码: [图片] 第四款: MinUI: 地址 https://meili.github.io/min/docs/minui/index.html 预览码: [图片] 第五款: iview-weapp:地址 https://weapp.iviewui.com/docs/guide/start 预览码: [图片] 第六款: WXRUI:暂无地址 预览码: [图片] 第七款: WuxUI:地址https://www.wuxui.com/#/introduce 预览码: [图片] 第八款: WussUI:地址 https://phonycode.github.io/wuss-weapp/quickstart.html 预览码: [图片] 第九款: TouchUI:地址 https://github.com/uileader/touchwx 预览码: [图片] 第十款: Hello UniApp: 地址 https://m3w.cn/uniapp 预览码: [图片] 第十一款: TaroUI:地址 https://taro-ui.jd.com/#/docs/introduction 预览码: [图片] 第十二款: Thor UI: 地址 https://thorui.cn/doc/ 预览码: [图片] 第十三款: GUI:https://github.com/Gensp/GUI 预览码: [图片] 第十四款: QyUI:暂无地址 预览码: [图片] 第十五款: WxaUI:暂无地址 预览码: [图片] 第十六款: kaiUI: github地址 https://github.com/Chaunjie/kai-ui 组件库文档:https://chaunjie.github.io/kui/dist/#/start 预览码: [图片] 第十七款: YsUI:暂无地址 预览码: [图片] 第十八款: BeeUI:git地址 http://ued.local.17173.com/gitlab/wxc/beeui.git 预览码: [图片] 第十九款: AntUI: 暂无地址 预览码: [图片] 第二十款: BleuUI:暂无地址 预览码: [图片] 第二十一款: uniydUI:暂无地址 预览码: [图片] 第二十二款: RovingUI:暂无地址 预览码: [图片] 第二十三款: DojayUI:暂无地址 预览码: [图片] 第二十四款: SkyUI:暂无地址 预览码: [图片] 第二十五款: YuUI:暂无地址 预览码: [图片] 第二十六款: wePyUI:暂无地址 预览码: [图片] 第二十七款: WXDUI:暂无地址 预览码: [图片] 第二十八款: XviewUI:暂无地址 预览码: [图片] 第二十九款: MinaUI:暂无地址 预览码: [图片] 第三十款: InyUI:暂无地址 预览码: [图片] 第三十一款: easyUI:地址 https://github.com/qq865738120/easyUI 预览码: [图片] 第三十二款 Kbone-UI: 地址 https://wechat-miniprogram.github.io/kboneui/ui/#/ 暂无预览码 第三十三款 VtuUi: 地址 https://github.com/jisida/VtuWeapp 预览码: [图片] 第三十四款 Lin-UI 地址:http://doc.mini.talelin.com/ 预览码: [图片] 第三十五款 GraceUI 地址: http://grace.hcoder.net/ 这个是收费的哦~ 预览码: [图片] 第三十六款 anna-remax-ui npm:https://www.npmjs.com/package/anna-remax-ui/v/1.0.12 anna-remax-ui 地址: https://annasearl.github.io/anna-remax-ui/components/general/button 预览码 [图片] 第三十七款 Olympus UI 地址:暂无 网易严选出品。 预览码 [图片] 第三十八款 AiYunXiaoUI 地址暂无 预览码 [图片] 第三十九款 visionUI npm:https://www.npmjs.com/package/vision-ui 预览码: [图片] 第四十款 AnimaUI(灵动UI) 地址:https://github.com/AnimaUI/wechat-miniprogram 预览码: [图片] 第四十一款 uView 地址:http://uviewui.com/components/quickstart.html 预览码: [图片] 第四十二款 firstUI 地址:https://www.firstui.cn/ 预览码: [图片]
2023-01-10 - 小程序与公众号下发统一消息接口调整通知
各位开发者: 下发统一消息 接口曾支持小程序与公众号统一的模板消息下发。由于小程序模板消息能力已于 2020 年 1 月下线(详见 小程序模板消息能力调整通知),当前下发统一消息能力仅限于公众号范畴。为了优化开发体验,避免多个同一功能接口对开发者造成困扰,微信团队将对下发统一消息接口进行如下调整: 自 2023 年 9 月 20 日起(以下简称 “生效期”),下发统一消息接口将被收回。自生效期起,调用下发统一消息接口将会显示 “45109” 错误码,无法下发小程序模板消息与公众号模板消息。如业务需下发公众号模板消息,请使用 公众号模板消息能力 满足能力需求,具体适配操作可参考下方适配指引。 注意点: 1、下发统一消息接口与公众号模板消息接口的差异对比如下: [图片] 2、本次接口回收仅影响使用旧的下发统一消息接口的方式下发模板消息的情况,不代表公众号模板消息能力被收回,使用 公众号模板消息接口 下发公众号模板消息的能力不受影响。例如小程序 A、B 当前正使用不同接口下发公众号模板消息: [图片] 3、小程序订阅消息能力不受本次接口回收的影响。 4、请已使用下发统一消息接口的开发者尽快适配。若 2023 年 9 月上旬仍未适配,官方团队将分阶段通过站内信、微信开发者工具通知等方式同步告知指引修改。 适配指引: [图片] 检查当前调用下发统一消息接口的用户身份信息: 1、若当前下发模板消息的用户身份信息为公众号 openid,按照 公众号模板消息接口文档 适配 2、若当前下发模板消息的用户身份信息为小程序 openid,检查 微信开放平台 是否将小程序与公众号绑定在同一个主体 a) 若小程序与公众号绑定在同一个主体下,按照 公众号模板消息接口文档 适配 b) 若小程序与公众号没有绑定在同一个主体下,先完成绑定工作,再按照 公众号模板消息接口文档 适配 微信团队 2023年8月22日
2023-09-18 - 小程序用户头像昵称获取规则调整公告
更新时间:2022年11月9日由于 PC/macOS 平台「头像昵称填写能力」存在兼容性问题,对于来自低于2.27.1版本的访问,小程序通过 wx.getUserProfile 接口将正常返回用户头像昵称,插件通过 wx.getUserInfo 接口将正常返回用户头像昵称。 更新时间:2022年9月28日考虑到近期开发者对小程序用户头像昵称获取规则调整的相关反馈,平台将接口回收的截止时间由2022年10月25日延期至2022年11月8日24时。 调整背景在小程序内,开发者可以通过 wx.login 接口直接获取用户的 openId 与 unionId 信息,实现微信身份登录,支持开发者在多个小程序或其它应用间匿名关联同一用户。 同时,为了满足部分小程序业务中需要创建用户的昵称与头像的诉求,平台提供了 wx.getUserProfile 接口,支持在用户授权的前提下,快速使用自己的微信昵称头像。 但实践中发现有部分小程序,在用户刚打开小程序时就要求收集用户的微信昵称头像,或者在支付前等不合理路径上要求授权。如果用户拒绝授权,则无法使用小程序或相关功能。在已经获取用户的 openId 与 unionId 信息情况下,用户的微信昵称与头像并不是用户使用小程序的必要条件。为减少此类不合理的强迫授权情况,作出如下调整。 调整说明自 2022 年 10 月 25 日 24 时后(以下统称 “生效期” ),用户头像昵称获取规则将进行如下调整: 自生效期起,小程序 wx.getUserProfile 接口将被收回:生效期后发布的小程序新版本,通过 wx.getUserProfile 接口获取用户头像将统一返回默认灰色头像,昵称将统一返回 “微信用户”。生效期前发布的小程序版本不受影响,但如果要进行版本更新则需要进行适配。自生效期起,插件通过 wx.getUserInfo 接口获取用户昵称头像将被收回:生效期后发布的插件新版本,通过 wx.getUserInfo 接口获取用户头像将统一返回默认灰色头像,昵称将统一返回 “微信用户”。生效期前发布的插件版本不受影响,但如果要进行版本更新则需要进行适配。通过 wx.login 与 wx.getUserInfo 接口获取 openId、unionId 能力不受影响。「头像昵称填写能力」支持获取用户头像昵称:如业务需获取用户头像昵称,可以使用「头像昵称填写能力」(基础库 2.21.2 版本开始支持,覆盖iOS与安卓微信 8.0.16 以上版本),具体实践可见下方《最佳实践》。小程序 wx.getUserProfile 与插件 wx.getUserInfo 接口兼容基础库 2.27.1 以下版本的头像昵称获取需求:对于来自低版本的基础库与微信客户端的访问,小程序通过 wx.getUserProfile 接口将正常返回用户头像昵称,插件通过 wx.getUserInfo 接口将正常返回用户头像昵称,开发者可继续使用以上能力做向下兼容。对于上述 3,wx.getUserProfile 接口、wx.getUserInfo 接口、头像昵称填写能力的基础库版本支持能力详细对比见下表: [图片] *针对低版本基础库,兼容处理可参考 兼容文档 请已使用 wx.getUserProfile 接口的小程序开发者和已使用 wx.getUserInfo 接口的插件开发者尽快适配。小游戏不受本次调整影响。 最佳实践小程序可在个人中心或设置等页面使用头像昵称填写能力让用户完善个人资料: [图片] 微信团队 2022年5月9日
2023-09-26 - 小程序滑动日历
需求 做项目的时候需要用到一种日历,看完设计师的设计稿总结成:可以左右滑动切换显示的日历,能够在某一个日期下显示文字和标签,并且提供选择某一个范围内的日期和单选两种功能。 刚开始看到,想着这种组件网上也是一大堆。然而,查找了一番才知道大部分的日历组件都是上下滚动类型的,能够符合项目需求的组件不多。当然也有一些复杂的日历组件,但是我不想学习使用方法(懒),又因为偶然间看到了日历的简单实现思路,自己花了点时间写这个组件 解析原件 根据项目需求,我得先清楚我的日历应该具备哪些信息: [代码]1. 标题,旨在说明日历的用途,如选择购票时间,选择团期等 2. 副标题,用来显示当前的年月 3. 左右切换按钮,用来翻阅日历 4. 星期(日-六) 5. 一个月的天数的排列,通过循环,只要设置好每个格子的大小,就可以按照顺序排下去,但是我们得知道几点: 5.1)每月的1号是星期几,即从哪个位置开始排 5.2)每月有多少天,即要排多少个格子 6. 按照这种排列,肯定会出现前面几个格子是空白的,后面几个格子是空白的,即上下月的残余天数 6.1)上个月的最后一天是几号,有多少 6.2)下个月的残余天数有多少 7. 底部是否存在按钮,用来操作 [代码] 分析出上面的几点,基本上可以确定为自己的日历应该是张什么样子 [图片] 分析日历的显示: [代码]1. 可以显示文字和标签,因为日历每个日期相当于一个块,所以利用定位可以很快解决显示的问题,颜色也可以根据传过来的属性进行自定义 2. 可以选择日期,从这可以分析出每一个块至少有三种颜色变化:没有选中状态,选中状态以及中间状态 [代码] 从上面的分析可以知道,我们的数据结构应该长成这样子(展示部分): [代码]/** * 日历副标题 */ subTitle: { year: '' month: '' } /** * 日历信息 */ calendarInfo: { last: { year: -1, month: -1, list: [], swiperHeight: 999 }, cur: { year: -1, month: -1, day: -1, select: -1, //选中的时间,位置 swiperHeight: 999, //滚动框的高度 }, next: { year: -1, month: -1, list: [], swiperHeight: 999 } }, /** * 提示信息 */ tipData: [ { value: '2020-10-1', text: '国庆节', type: 'text', //文本类型 color: 'red' //文本颜色 }, { vlaue: '2020-10-1', text: '休', type: 'tag', //标签类型 color: 'lightblue', //标签颜色 } ] [代码] 那么此时的日历应该是长成这样 [图片] 开始封装 首先我选择的组件是微信小程序的swiper 确定每个月的1号是星期几 [代码] /** * 获取某月1号是星期几 * @param {Object} date * @returns {Number} */ getFirstDayWeek(date) { return new Date(date.year, date.month - 1, 1).getDay() }, [代码] 确定每个月的天数 [代码] /** * 获取某年某月的总天数 * @param {Object} date * @returns {Number} totalDays */ getTotalDays(date) { return new Date(date.year, date.month, 0).getDate() }, [代码] 根据第二点和第三点可以轻松知道当前月份的上个月的残余天数和下个月的残余天数(日历上显示的总天数是7的倍数,且最多显示6行) [代码]/** * 根据这个月,计算上下两个月的残余天数 * @param {Object} date */ calculateResidualDays(date) { // 计算上月残余天数,需要知道1号是星期几(个数)且上月最后一天是几号(起始数值) let last_value = dateUtil.getTotalDays({ year: date.year, month: date.month - 1 }) for (let i = 0; i < date.firstDayWeek; i++) { date.list.unshift({ value: this.properties.showRemnantDays ? last_value - i : '', type: 'last' }) } // 计算下月残余天数,需要知道本月显示多少行 let total = Math.floor(date.list.length / 7) if (date.list.length % 7 > 0) { ++total } if (this.properties.fixRow) { // 设置了每月固定显示6行 total = 6 } let next_value = total * 7 - date.list.length // 设置滚动框的高度,设置变化的过渡动画 date.swiperHeight = total * 107 for (let i = 1; i <= next_value; i++) { date.list.push({ value: this.properties.showRemnantDays ? i : '', type: 'next' }) } // 格式化显示的提示信息 this.formatShowTip(date) }, [代码] 大致上日历已经显示出来了,配置显示的文字和标签 [代码] /** * 格式化文字标签 * @param {Object} date */ formatShowTip(date) { // 判断是否显示相关的节假日 if (this.properties.showHoliday) { this.formatHolidayTip(date) } // 循环遍历找出对应的要显示的文字日期 this.properties.dateText.forEach((item, index) => { date.list.forEach((arr, temp) => { let value = date.year + '-' + date.month + '-' + arr.value if (item.value === value && arr.type === 'cur') { arr.tip = item } }) }) }, [代码] 设置选中日期 点击按钮 最后 因为代码的篇幅比较大,所以没有粘贴全部,只是一部分,详细的代码可见小程序业务组件日历。 github里面的组件目前只是单纯的提供日历的显示,暂时还没有提供获取后端数据并且格式化的方法,这个可自行添加,也可以在切换月份的时候回调事件处理。 组件整体的效果变现为: [图片] 原文链接
2023-03-03 - 公众平台/小程序服务端API的access_token的内部设计
一、背景 对于使用过公众平台的API功能的开发者来说,access_token绝对不会陌生,它就像一个打开家门的钥匙,只要拿着它,就能使用公众平台绝大部分的API功能。因此,对于开发者而言,access_token的使用方式就变得尤其的重要。在日常API接口的运营中,经常遇到各种的疑问:为什么我的access_token突然非法了?为什么刚刚拿到的access_token,用了10min就过期了?对于这些疑问,我们提供出access_token的设计方案,便于开发者对access_token使用方式上的理解。 对于access_token的获取,可以参考公众平台的官方文档:auth.getAccessToken、获取Access token 二、access_token的内部设计 2.1 access_token的时效性 众所周知,access_token是通过appid和appsecret来生成的。内部设计的步骤如下: (1)开发者通过https请求方式: GET https://API.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET,传入appid及apppsecret的参数 (2)公众平台后台会校验appid和哈希(appsecret)是否与存储匹配,若匹配,结合当前时间戳,生成新的access_token。 (3)生成新的access_token的同时,会对老的access_token的过期时间戳更新为当前时间戳。 (4)返回新的access_token给开发者。 这里以图示的方式说明一下,新旧token交替过程: [图片] 从上图需要注意的几点: (1)公众平台存储层只会存储新老两个access_token,意味着假设开发者重复调用3次接口,则会导致最早的access_token立刻失效。 (2)虽然请求新的access_token后,老的access_token过期时间会更新为当前时间,但也不会立刻失效,原理请参考 【2.2 access_token 的逐渐失效性】 (3)出于信息安全考虑,公众平台并不会明文存储appsecret,仅存储appid以及appsecret的哈希值。因此开发者要妥善保管appsecret。当appsecret疑似泄露时,需要及时登录mp.weixin.qq.com重置appsecret。 2.2 access_token 的逐渐失效性 从【access_token的时效性】了解到,当开发者请求获取新的access_token时,老的access_token过期时间会被更新为当前时间,但此时不会立刻失效,因为公众平台会提供【5分钟的新老access_token交替缓冲时间】,因此也称为access_token 的逐渐失效性。 实现的原理是: 1. 由于老的access_token过期时间戳已被刷新,所以在API接口请求期间,带上的access_token解开后,过期时间戳会加上5分钟,然后和当前设备时间进行比对,若超过当前设备时间,判断为失效。 2. 公众平台的设备会保持时钟同步,但设备之间仍然可能会存在1-2分钟的时间差异,所以【5分钟】并非绝对的时间值。当开发者获取到新的access_token后应该尽快切换到新的access_token。 [图片] 从上图需要注意的几点: (1)由于存在设备时间同步的差异,可能会导致开发者遇到拿着老的access_token请求API接口,部分请求成功,部分请求失败的情况,建议开发者获取到新的access_token后尽快使用。 (2)通过理解两个图示,对开发者来说,access_token是相当关键且不能乱调的接口,建议开发者统一管理access_token,以免造成多次请求导致access_token失效。
2021-05-11 - 开源推荐|小程序数字滚动动效组件
上效果 [图片] 使用方法 组件介绍 两种组件类型: animateNumber: 范围内的所有数字连贯滚动,显示效果佳,但仅限于上下500内,否则页面卡顿 animateNumbers: 各个数位的数字单独滚动,0以上皆可 [代码]// animateNumber 使用示例 <animate-number value="{{value}}" min='{{-50}}' max='{{300}}' options='{{options}}'/> // 配置项如下 options: { during: 1, // (number) 动画时间 height: 40, // (number) 滚动行高 px width: '100%', // (string) 组件整体宽度 ease: 'cubic-bezier(0, 1, 0, 1)', // (string) 动画过渡效果 color: '#FF5837', // (string) 字体颜色 columnStyle: '', // (string) 字体单元 覆盖样式 } // animateNumbers 使用示例 <animate-numbers value="{{value}}" min='{{0}}' max='{{999}}' options='{{options}}'/> // 配置项如下 options: { during: 1, // (number) 动画时间 height: 40, // (number) 滚动行高 px cellWidth: 24, // (number) 单个数字宽度 px ease: 'cubic-bezier(0, 1, 0, 1)', // (string) 动画过渡效果 color: '#FF5837', // (string) 字体颜色 columnStyle: '', // (string) 字体单元 覆盖样式 } [代码] 使用代码 wxml代码 [代码]<!--index.wxml--> <view class="container"> <view class="userinfo"> <button class="btn" bindtap="onReset">重置</button> <input class="input" value="{{numberVal}}" type='number' bindinput="onInput" bindconfirm="onInput"></input> <button class="btn" type="primary" bindtap="onRun">运行</button> </view> <!-- 组件 --> <view class="title">单维数字阵列:</view> <view class="count-up"> <view>默认范围 0~100,配置项options</view> <animate-number value="{{numberVal}}" options='{{options}}'/> </view> <view class="count-up"> <view>设置最大值为 limit:200</view> <animate-number value="{{numberVal}}" max='{{limit}}' /> </view> <view class="count-up"> <view>设置范围为 -50~200</view> <animate-number value="{{numberVal}}" min='{{start}}' max='{{limit}}' /> </view> <view class="title">多维数字阵列:</view> <view class="count-up"> <view>配置同上</view> <animate-numbers value="{{numberVal}}" max='{{limit}}' options='{{options}}' /> </view> </view> [代码] js 代码 [代码]//index.js //获取应用实例 const app = getApp() Page({ data: { value: 0, numberVal: '', start: -50, limit: 200, options: { color: 'green', during: 2, height: 50, width: '100px', columnStyle: 'font-weight: normal', }, }, //事件处理函数 onReset: function() { this.setData({ numberVal: 0 }) }, onRun(){ this.setData({ numberVal: this.data.value }) }, onInput(e){ let value = e.detail.value this.setData({ value }) }, }) [代码] 源码分析 animateNumber 先从[代码]animateNumber[代码]组件开始,从js部分开始 先看常量属性部分分别是: CONFIG:作为默认样式配置 LOCK:最大值,上面有提到超过500会卡顿 问题:为什么超过500就卡顿呢? [代码]const CONFIG = { during: 1, // :number 动画时间 height: 40, // :number 滚动行高 px width: '100%', // 组件整体宽度 ease: 'cubic-bezier(0, 1, 0, 1)', // 动画过渡效果 color: '#FF5837', // 字体颜色 columnStyle: '', // 字体单元 覆盖样式 } const LOCK = 500 // 锁止 [代码] 再来看看属性列表分别是: value:需要滚动到的目标值,设置监听变化时调用[代码]run[代码]方法 max:最大值,设置监听变化时调用[代码]setRange[代码]方法 min:最小值,设置监听变化时调用[代码]setRange[代码]方法 问题:[代码]setRange[代码],[代码]run[代码]方法都是起到什么作用呢? [代码]/** * 组件的属性列表 */ properties: { value: { type: Number, value: 0, observer (n){ this.run(n) } }, max: { type: Number, value: 100, observer (){ this.setRange() } }, min: { type: Number, value: 0, observer (){ this.setRange() } }, options: { type: Object, value: {} }, }, [代码] 前面这些都是准备阶段,解析来才是重头戏,敲黑板! 页面创建时执行的时候调用了[代码]setRange[代码],[代码]renderStyle[代码]方法。 主要目的是初始化数据范围和页面样式。 [代码]setRange[代码]方法作用把所有目标值区间的数字都遍历生成出来。如:设置了200为最大值,[代码]columns[代码]数组里面就会有1-200的数字。 [代码]renderStyle[代码]方法作用把设置的一些基础样式。 [代码]run[代码]设置具体当前显示的数字 [代码] /** * 内存数据 */ data: { columns: [], key: 0, _options: JSON.parse(JSON.stringify(CONFIG)), }, // 页面创建时执行 attached(){ this.setRange() this.renderStyle() }, /** * 组件的方法列表 */ methods: { setRange(){ let { max,min } = this.properties let arr = [] min = parseInt(min) max = parseInt(max) if(max - min < 0){ max = min }else if(max - min > LOCK){ max = min + LOCK } for(let i = min; i<= max; i++){ arr.push(i) } this.setData({ columns: arr, max, min, }) // 范围调整后,修正当前 value this.run(this.properties.value) }, run(n){ let { max,min } = this.data let index; n = parseInt(n) n = n<min ? min : n>max ? max : n index = this.data.columns.indexOf(n) this.setData({ key: index>-1 ? index : 0 }) }, renderStyle(){ /** * color, * columnStyle, * width, * height, * during, * ease, */ let options = this.properties.options, _options = this.data._options; // console.log('options:',options) Object.keys(options).map(i=>{ let val = options[i] switch (i) { case 'during': case 'height': if(parseInt(val) || val === 0 || val === '0'){ _options[i] = val } break; default: val && (_options[i] = val); break; } }) this.setData({ _options }) }, } [代码] wxml代码 [代码]<view class="count-box" style="width:{{_options.width}};"> <view class="viewport" style="height:{{_options.height}}px;"> <view class="column-wrap" style="transform: translate3d(0, -{{key * _options.height}}px, 0); transition-duration:{{_options.during}}s; transition-timing-function:{{_options.ease}}"> <view wx:for="{{columns}}" wx:key="index" class="item" style="color:{{_options.color}};height:{{_options.height}}px;line-height: {{_options.height}}px;{{_options.columnStyle}}">{{item}}</view> </view> </view> </view> [代码] css代码 [代码]/* components/animateNumber/index.wxss */ .count-box{ /* width: 100%; */ height: 100%; display: flex; justify-content: center; align-items: center; } .viewport{ width: 100%; overflow: hidden; } .column-wrap{ width: 100%; transform: translate3d(0, 0, 0); transition: all 1s cubic-bezier(0, 1, 0, 1); } .item{ width: 100%; text-align: center; font-size: 40px; font-weight: bold; } [代码] [代码]columns[代码]是所有区间内的值,然后布局会[代码]wx:for="{{columns}}"[代码]通过全部渲染出来,这里也就是为什么上限设置了500,因为一个页面显示的元素过多就会导致卡顿。 [图片] 那么遍历出了200个为什么看不到了?因为通过[代码]overflow:hidden[代码]属性做到只显示当前数字,如果把去掉这个属性就是这样的:[图片] 滚动的效果是通过改变[代码]translate3d[代码]的[代码]y[代码]轴实现的,[代码]y[代码]的值是通过-[代码]key * _options.height[代码]计算出来的,[代码]height[代码]好理解就是一个数字的高度,而[代码]key[代码]就是具体当前要显示的数字。如:我输入数字2,每个高度是50px,那么就是2*50=100px。 [图片] 那么这个时候你肯定会有个疑问,很多时候我们会有超过500的数字,那怎么办呢?这个问题好解决可以用[代码]animateNumbers[代码]组件。 animateNumbers animateNumber 和 animateNumbers 大同小异,很多内容都是一样除了一个地方。不一样的地方在于单维数字阵列和多维数字阵列。如:value为100,animateNumber是一个内容为100的view,animateNumbers是三个view组合而成一个内容为1的view和两个内容为0的view。 [图片] 再看看wxml布局代码,采用的是双重循环。 [代码]<view class="count-box"> <view class="viewport" wx:for="{{columns}}" wx:key="index" style="width:{{_options.cellWidth}}px;height:{{_options.height}}px;"> <view class="column-wrap" style="transform: translate3d(0, -{{keys[index] * _options.height}}px, 0);transition-duration:{{_options.during}}s; transition-timing-function:{{_options.ease}}"> <view wx:for="{{item}}" wx:for-item="row" wx:for-index="idx" wx:key="idx" class="item" style="color:{{_options.color}};height:{{_options.height}}px;line-height: {{_options.height}}px;{{_options.columnStyle}}">{{row}}</view> </view> </view> </view> [代码] 再看看js代码 注:同样的js代码就不重复解释了,主要看看不一样的地方。 [代码]initColumn[代码]把数字进行了分割,如:最大值100获取100的长度为3,那么就变成了3个数组,每个数组都是1-9的数字。 [代码]run[代码]方法里面按位分别计算[代码]key[代码]值放入放到[代码]keys[代码]中 [代码]setRange(){ let { max,min } = this.properties min = parseInt(min) >= 0 ? parseInt(min): 0 max = parseInt(max) > min ? parseInt(max): min let columns = this.initColumn(max); this.setData({ columns, max, min, }) // 范围调整后,修正当前 value if(this.properties.value) { this.run(this.properties.value) } }, initColumn(n){ let digit = (n + '').length, arr = [], rows = [' ', '0','1','2','3','4','5','6','7','8','9']; for(let i = 0; i< digit; i++){ if(i) { arr.unshift(rows) }else{ arr.unshift( rows.slice(1) ) } } return arr }, run(n){ let { max,min } = this.data; let value = parseInt(n); value = value<min ? min : value>max ? max : value; let valueArr = value.toString().split(''), lengths = this.data.columns.length, indexs = []; while(valueArr.length){ let figure = valueArr.pop(); if(indexs.length){ indexs.unshift(parseInt(figure) +1) }else{ indexs.unshift(parseInt(figure)) } } while( indexs.length < lengths ){ indexs.unshift(0) } this.setData({ keys: indexs }) }, [代码] 源码地址 源码地址:https://github.com/Lyuing/wxAnimateNumber
2021-06-08 - css 毛玻璃效果
[图片] css width: 100rpx; height: 130rpx; background: linear-gradient(to right bottom, rgba(44,44,69,0.6), rgba(44,44,69,0.3), rgba(44,44,69,0.2)); backdrop-filter: blur(9px); border-top: 2rpx solid rgba(44,44,69,0.8); border-left: 2rpx solid rgba(44,44,69,0.8); border-radius: 30rpx; padding: 20rpx; box-shadow: 0 9px 15px 0 rgba(25,21,40,0.39),0 -9px 15px 0 rgba(25,21,40,0.39);
2021-04-26 - 关于小程序ios端android webview一直缓存问题的解决方案
// 只要配置服务端http的 Cache-Control Expires Pragma 即可 //php配置 header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); header("Pragma: no-cache"); //php nginx 选择一个地方配置了就行 //nginx 配置 if 路径 { expires -1; } 如何验证:在chrome中打开控制台,查看network,点击请求,查看resposne,如下图所示 [图片]
2022-02-17