- 解锁小程序中使用SVG新姿势
SVG 的优势 清晰度: 可以进行放大,而不失真 更小的文件体积 可扩展性,可以动态颜色 动效 可以添加动效 在小程序中使用 目前小程序 的image标签已经支持了 svg 的显示 [代码] <image src="./xx.svg"/> [代码] 如何动态的改变 svg 属性呢? 大体思路:把svg转成 base64 然后通过 image标签 src设置图片,再动态赋值svg颜色 把svg转成base64 如下一个svg 代码文件 [代码]<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="24 24 48 48"><animateTransform attributeName="transform" type="rotate" repeatCount="indefinite" from="0" to="360" dur="1400ms"></animateTransform><circle cx="48" cy="48" r="20" fill="none" stroke="#eeeeee" stroke-width="2" transform="translate\(0,0\)"><animate attributeName="stroke-dasharray" values="1px, 200px;100px, 200px;100px, 200px" dur="1400ms" repeatCount="indefinite"></animate><animate attributeName="stroke-dashoffset" values="0px;-15px;-125px" dur="1400ms" repeatCount="indefinite"></animate></circle></svg> [代码] 转成base64,其实就是 对这个svg进行 encodeURIComponent 得到 如下代码 [代码]%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%2224%2024%2048%2048%22%3E%3CanimateTransform%20attributeName%3D%22transform%22%20type%3D%22rotate%22%20repeatCount%3D%22indefinite%22%20from%3D%220%22%20to%3D%22360%22%20dur%3D%221400ms%22%3E%3C%2FanimateTransform%3E%3Ccircle%20cx%3D%2248%22%20cy%3D%2248%22%20r%3D%2220%22%20fill%3D%22none%22%20stroke%3D%22%23eeeeee%22%20stroke-width%3D%222%22%20transform%3D%22translate%5C(0%2C0%5C)%22%3E%3Canimate%20attributeName%3D%22stroke-dasharray%22%20values%3D%221px%2C%20200px%3B100px%2C%20200px%3B100px%2C%20200px%22%20dur%3D%221400ms%22%20repeatCount%3D%22indefinite%22%3E%3C%2Fanimate%3E%3Canimate%20attributeName%3D%22stroke-dashoffset%22%20values%3D%220px%3B-15px%3B-125px%22%20dur%3D%221400ms%22%20repeatCount%3D%22indefinite%22%3E%3C%2Fanimate%3E%3C%2Fcircle%3E%3C%2Fsvg%3E [代码] 拼接base64 [代码] data:image/svg+xml;charset=utf-8,encodeURIComponent后的代码 [代码] 在对应svg属性上动态设置颜色,比如这里用到的是填充颜色 在js文件 data中定义 color 状态 在wxml中动态渲染 [代码] <image src="data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%2224%2024%2048%2048%22%3E%3CanimateTransform%20attributeName%3D%22transform%22%20type%3D%22rotate%22%20repeatCount%3D%22indefinite%22%20from%3D%220%22%20to%3D%22360%22%20dur%3D%221400ms%22%3E%3C%2FanimateTransform%3E%3Ccircle%20cx%3D%2248%22%20cy%3D%2248%22%20r%3D%2220%22%20fill%3D%22none%22%20stroke%3D%22%23{{color}}%22%20stroke-width%3D%222%22%20transform%3D%22translate%5C(0%2C0%5C)%22%3E%3Canimate%20attributeName%3D%22stroke-dasharray%22%20values%3D%221px%2C%20200px%3B100px%2C%20200px%3B100px%2C%20200px%22%20dur%3D%221400ms%22%20repeatCount%3D%22indefinite%22%3E%3C%2Fanimate%3E%3Canimate%20attributeName%3D%22stroke-dashoffset%22%20values%3D%220px%3B-15px%3B-125px%22%20dur%3D%221400ms%22%20repeatCount%3D%22indefinite%22%3E%3C%2Fanimate%3E%3C%2Fcircle%3E%3C%2Fsvg%3E" /> [代码] [代码]注意:这里的颜色 由于是已经被编码了,所以# 已经被转义了 %23, 直接写颜色数字即可[代码] 当然你也可以 去掉%23 自己实现一个内部方法 [代码] if (color && color.startsWith('#')) { return `%23${color.slice(1)}`; } [代码] 这样其实就实现了 svg的动态渲染,可是这种写法,写在wxml中 不是特别的优雅,那么如何重构下让我们的代码看起来更优雅呢? 把 svg 单独存放 支持动态返回 动态赋值 image src 属性 svg 动态函数 loading.svg.js 文件 [代码]export const loadingSvg = (color='#ddd') =>{ const svgXml = `<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="24 24 48 48"><animateTransform attributeName="transform" type="rotate" repeatCount="indefinite" from="0" to="360" dur="1400ms"></animateTransform><circle cx="48" cy="48" r="20" fill="none" stroke="${color}" stroke-width="2" transform="translate\(0,0\)"><animate attributeName="stroke-dasharray" values="1px, 200px;100px, 200px;100px, 200px" dur="1400ms" repeatCount="indefinite"></animate><animate attributeName="stroke-dashoffset" values="0px;-15px;-125px" dur="1400ms" repeatCount="indefinite"></animate></circle></svg>` return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgXml)}` } [代码] 逻辑层引入,setData [代码] onLoad(){ const { loadingSvg } = require('./loading.svg.js') const svgImg = loadingSvg('#eee') this.setData({svgImg}) }, [代码] 渲染层使用 [代码] <image src="{{svgImg}}"/> [代码] github 使用案例 demoFormpSvg
2022-04-30 - minium 用例有失败,有错误的,为什么生成的报告全是成功的?
[图片] [图片]
2021-05-10 - 生命周期在wx:if下触发时机Bug
子组件在标有wx:if的情况下子组件的触发是立即触发,而不是等条件成立后触发! 如以下代码示例,子组件的attached应该在2s后才会触发,但结果却立即触发。 代码片段:https://developers.weixin.qq.com/s/cjbrRum477kF 部分代码示例 // component/test.js Component({ /** * 组件的属性列表 */ properties: { name: { type: String, value: 1 } }, /** * 组件的初始数据 */ data: { show: false }, lifetimes: { attached() { console.log('test component attached: ' + this.data.name + ' ' + Date.now()) setTimeout(() => { this.setData({ show: true }) }, 2000) }, }, // 兼容 attached() { console.log('test component attached: ' + this.data.name + ' ' + Date.now()) setTimeout(() => { this.setData({ show: true }) }, 2000) }, }) // test.wxml <slot wx:if="{{show}}" ></slot> // 使用 <test name="1"> <test name="2"> 嵌套测试 </test> </test>
2020-09-19 - selectQuery获取canvas对应的node,返回为Null?,请微信官方尽快解决问题
<canvas class="covercanvas" type="webgl" id="covercanvas" style="width: 100%; height: 100%;position: absolute;top: 0;" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd" ></canvas> 调试模式下正常,预览或者发布出去的版本node为null 代码片段: const query = wx.createSelectorQuery().in(this); query.select('#covercanvas') .fields({ node: true, context: true, id: true, dataset: true, rect: true, size: true, scrollOffset: true }) .exec((res) =>{console.log(res[0]);}) 返回的值: bottom: 320 dataset: Object height: 320 id: "webgl" left: 0 node: null nodeCanvasType: "webgl" right: 414 scrollHeight: 0 scrollLeft: 0 scrollTop: 0 scrollWidth: 0 top: 0 width: 414 可以看见,返回得node值为null。这个只有在发布或者预览的版本上有,调试模式下没有。@微信官方,请解决一下。
2020-11-18 - 小程序自定义tabbar踩坑记
小程序为什么要用自定义tabbar? 我们是为了实现小程序中多个tabbar的效果的。用户进首页的时候,是一个tabbar,在进入到另外的页面的时候,底部的tabbar显示的是另外的一个。这样可以更好的让用户浏览到不同的内容。有点类似于一个主小程序中嵌套了一个子小程序。 现有的一些方案 我们在做这个之前,是有看过其它小程序做的一些效果的。比如小米lite和携程的小程序。 他们的实现的方式是一样的,就是做一个tabbar的自定义组件,然后跳转每个页面的时候用wx.navigateTo方法去跳转。这样是能实现多个tabbar的,当然也是有一些问题的,因为 navigateTo和switchTab的页面加载效果是不一样的。navigateTo是有一个页面的过渡效果的,有一个新页面整体从右侧滑出的动画。但是switchTab是直接出页面的。因为在tabbar上的页面,往往就是需要经常打开的页面,如果有一个跳转页面的滑出动画是会影响用户体验的。所以我们把这个方案做为了一个备选方案。 我们采用的方案 其实微信官方是有一个自定义tabbar的,我们的方案是基于官方的自定义tabbar完成的。 自定义tabbar的地址:https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html (在看下面的文章之前,可以先看一下这个例子) 刚开始看,感觉实施起来并不难,而且官方还提供了一个简单的代码片段,但是在这个过程中,遇到了一些问题,以下是记录遇到的问题和解决方法。 我们新建一个js文件用来管理多个tabbar的状态。在router层做了判断,当进入需要显示另一个tabbar的时候,改变这个全局的状态,并且setdata让新的tabbar显示在视图层上。就是要中心化的管理tabbar的状态。 遇到的问题与解决方法 必须在根目录下的指定文件夹 这个自定义tabbar组件必须放在根目录的custom-tab-bar 文件夹下。这样才能被识别。 tabbar上下跳动 当我第一次把官方的例子稍加修改,移植到我们的小程序上的时候,发现tabbar会在真机上,在点击tabbar上图标的时候,上下跳动。当时也差点因为这个原因放弃这个方案。然后在之后的摸索中发现,官方的例子用的是<cover-view>和<cover-image>,改成<view>和<image>标签以后,就没有这种跳动了。当然换为view和image的后,层级会变低,所以要记得给tabbar设置高的层级,否则会被别的内容挡到。 iphonex以上手机底部tab适配 iphonex以上手机因为底部有一个小横条,所以iPhonex以上手机的tabbar的高度是比较高和其它的手机是不一样的。微信小程序原生的tabbar是有这个高度适配的,但是如果换成自定义的tabbar就需要自己适配了。需要自己做一下高度的适配。而且要注意一下开发者工具和真实机型的差距。开发者工具显示iphonex上的tabbar的样子并不是真实机型中看到的,需要注意一下。 tabbar上item数量或小红点 以前在用原生tabbar的时候,有微信的api可以全局的改变某个item上面的数字和小红点。这样在做像购物车上小红点数量改变的时候就可以用这个api。但是在使用了自定义tabbar的时候,就需要自己更新item上的数量或小红点了。而且是全局更新,因为可能在没有tabbar的页面也需要更新。为了实现全局更新,开始没有想到很好的办法,最开始是把tabbar这个组件的setdata方法存到app.js中,然后在需要更新的时候调用setdata。但是这个方法不太好,之后在跟组长讨论后,提示可以用eventhub了。在tabbar的js中来监听数量的改变,在需要改变数量的地方,触发这个event,这样就实现了全局的数量更新。 switchtab加参数 因为我们的页面在tabbar上面,只能用switchtab的方法去跳转到这个页面,但是小程序的switchtab方法是无法带参数的(我其实不太理解为什么不能带参数,但是从二维码或者分享进入tabbar上的页面,又是可以带参数的),我们采用的方法是我们有一个router工具,当检测到要跳到需要带参数的页面的时候,就把解析到的参数加到storage中,然后在页面的onshow的方法中获取。 小程序的基础库问题 自定义tabbar支持的小程序基础库版本是2.5.0,所以我们需要注意一下老基础库版本的兼容性问题。在低基础库的小程序上,自定义tabbar是可以在小程序的后台设置最低的基础库要求。 tabbar闪动 因为在切换tab的时候,必须setdata,所以肯定有闪动的,这个目前还没有找到很好的办法。 最后 小程序自定义tabbar这个特性,感觉使用的小程序也不是很多。我们先进行了一些踩坑,也希望可以帮到使用这个特性的小程序。
2020-12-25 - 上传前预处理时序bug,实际处理是上传完以后
project.config.json "scripts": { "beforeCompile": "", "beforePreview": "", "beforeUpload": "npm run prod" }, 然后npm run prod是用node去替换测试域名为线上域名等。 用微信开发者工具上传完以后的确看到对应的文件域名的确修改了,但是使用上传完以后的小程序体验版发现,域名却还是测试环境的。 初步认为是beforeUpload的执行时机有问题,很明显是上传完以后才执行导致的。
2020-04-22