- 小程序蓝牙打印爬坑之旅
因为公司要在小程序上加蓝牙打印标签功能,所以就开始接触小程序的蓝牙打印,看文档还是蛮详细的,而且还有demo,顺着demo,一步一步下来还是蛮顺畅的,原以为很快就能完成。没想到坑来了,由于demo中writeBLECharacteristicValue只是写入了一个16进制的数据,而现实中是需要发送字符串的,而且小程序必须要是arrayBuffer,就必须将字符串转arrayBuffer了,好,网上搜下,准备打印了吱吱吱咦,怎么有乱码啊,怎么中文都乱码了。。这下可糟了!于是就去各种找答案。最后知道问题了:原来是因为我们公司用的打印机是智能支持GB2312编码格式的二进制的,但是字符串是utf-8,诶,又得爬坑。经过一天的努力,终于找到解决方法啦,感谢csdn的大大们。实现的代码如下 //计算arraybuffer的长度 sumStrLength(str) { var length = 0; var data = str.toString(); for (var i = 0; i < data.length; i++) { if (this.isCN(data[i])) { //是中文 length += 2; } else { length += 1; } } return length; }, //混杂 hexStringToBuff(str) { //str=‘中国:WXHSH’ const buffer = new ArrayBuffer((this.sumStrLength(str)) + 1); const dataView = new DataView(buffer) var data = str.toString(); var p = 0; //ArrayBuffer 偏移量 for (var i = 0; i < data.length; i++) { if (this.isCN(data[i])) { //是中文 //调用GBK 转码 var t = gbk.$URL.encode(data[i]); for (var j = 0; j < 2; j++) { var temp = parseInt(t[j * 2] + t[j * 2 + 1], 16) dataView.setUint8(p++, temp) } } else { var temp = parseInt(data.charCodeAt(i).toString(16), 16) dataView.setUint8(p++, temp) } } console.log(String.fromCharCode.apply(null, new Uint8Array(buffer))); return buffer; }, //js正则验证中文 isCN(str) { if (/[1]+$/.test(str)) { return true; } else { return false; } }, 将中文转化为GB2312编码格式再转成arrayBuffer就大功告成啦,把这个文章记录下来,希望可以帮助到其他小程程们。如有需要,加我Q:786914253 \u3220-\uFA29 ↩︎
2019-03-19 - 【干货】微信内置浏览器缓存清理
之前做过很多公众号的项目,项目写完后给客户看项目,客户一而再再而三的修改元素向左挪1px,向右挪2px。改好之后让客户看,客户说我特泽发克,你啥都没有修改,你竟然骗我!!! 这其实就是微信内置浏览器的缓存在作祟啦,那么如何清理微信内置浏览器的缓存呢? 你们是否知道 ios版微信 和 android版微信 的内置浏览器的内核是不一样的呢? android版微信内置浏览器(X5内核) 在安卓版微信内打开链接 http://debugx5.qq.com 拉到调试页面的最底端,勾选上所有的缓存项目,点击清除。 [图片] 点击确定之后即可完成清除微信浏览器缓存的操作。 ios版微信内置浏览器(WKWebView) ios版微信内置浏览器内核并不是 X5内核,而是使用的ios的浏览器内核WKWebView,所以安卓手机的那种方案对ios手机用户不生效,因为那个链接压根打不开 只要微信用户退出登录,然后重新登录,ios版微信内置浏览器内核即可清除,不行的话,你们回来打我 有人说了:“IOS中 设置—通用----存储空间 就会看到“正在计算空间”计算完了会清理一点清理即可”,这种办法当然也可以,但是这种办法不光是清理微信内置浏览器的缓存,同时也清理其他的一些数据,比如朋友圈的视频图片和聊天记录等等缓存,而且容易误删某些想留下的数据,对于开发而言,我认为退出重新登录是最好的解决办法。
2020-01-08 - 微信小程序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 - (16)小游戏渲染
《跳一跳》小游戏在 2017年12月28日正式发布,一周内 DAU 突破一亿,为小游戏开放生态赢得口碑。它操作简单,节奏轻快,凭借着快速复活机制以及强大的社交属性掀起了一股全民潮流。 其实,这个小游戏里仅有两个元素,黑色小人和各色基座。游戏规则也很简单,起跳前,小黑人压缩自己的身体来蓄力,根据蓄力时间决定距离来跳到下一个基座上。 今天的小故事,想要跟大家分享小游戏的渲染能力,我们以跳一跳唱片机为例,简要介绍一下如何展现一个三维物体~ ( 3D渲染引擎选用 Three.js ) [图片] 步骤一 创建一个场景 Scene 游戏的容器,用来放置光源,照相机和唱片机。 let scene = new THREE.Scene() 步骤二 选择合适的照相机 Camera 抽象来说,照相机定义了三维空间到二维屏幕的投影方式。 因投影方式不同,相机又分为透视投影相机和正交投影相机。 透视投影中的四棱柱和正交投影中的立方体被称为视景体,它是三维世界里屏幕上可见的区域,也就是照相机的视野。 视景体外的物体会被剪裁掉不参与渲染。透视投影更接近真实世界,有近大远小的感觉。而正交投影将物体以原比例平行投影到近剪裁面上,不会有大小缩放。 在跳一跳中我们使用了正交投影相机。 [图片] let camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, near, far ) 步骤三 创建光源 light let ambientLight = new THREE.AmbientLight(0xffffff, 0.8); let directionalLight = new THREE.DirectionalLight(0xffffff, 0.28); 创建一个环境光和直射光, 环境光没有特定光源,它将光线均匀照射在场景中。直射光模拟真实世界太阳光。 步骤四 定义几何体 Geometry, 材质 Material,合成 Mesh Geometry 几何体,定义了一个物体的形状,包含顶点,线,面和法向量等信息。 let boxGeometry = new THREE.BoxGeometry(2, 2, 2) 对于唱片机我们创建了三个几何体,两个长方体和一个圆柱体。 [图片] Material 材质,定义了一个物体的外观,例如颜色,透明度,光照属性,融合模式。 顶部透明盖子,底座和唱片的使用的Lambert材质,这种材质只考虑漫反射而不考虑镜面反射, 通常用于创建较暗淡无高光的物体, 其中 texture 是纹理贴图,我们通过纹理映射将这个二维图像贴到三维的方块上。 let transparentMaterial = new THREE.MeshLambertMaterial({ color: ‘white’, transparent: true, opacity: 0.5, map: texture }) 最后我们通过 Mesh 我们将材质应用到几何体上。 let box = new THREE.Mesh(boxGeometry, transparentMaterial) 步骤五 使用渲染器 Renderer 渲染整个场景 最后我们将 box,camera 设置合适的位置后加入到场景中,再使用 Three.js 的渲染器 renderer 之后就可以看到音乐盒了~ renderer.render(scene, camera) 至此,我们完成了一个 3D 场景渲染到 2D 屏幕的渲染流水线中的应用程序阶段,这个阶段我们将渲染所需的几何信息(点,线,面,法线等信息)传递到渲染流水线的后续阶段。后续的小故事我们会介绍调用渲染器 render 方法后 GPU 是如何处理几何信息并最终渲染图像到屏幕上的。 QA&共性问题 Q 一般的 3D 游戏 HUD 层(平视显示器)采用 DOM 来显示,例如排行榜,交互按钮。或者使用另一个 canvas 叠在游戏 canvas 上。但是小游戏只支持一个可见 canvas,并且不支持 DOM。这种情况在小游戏里面,应该如何处理呢? A 可以封装 HUD 层并将其放在游戏 canvas 中,将整个HUD画在了一张离屏 canvas 中,然后将该 canvas 转化为纹理贴图,再将其贴在游戏的 3D 平面模型上。 后续的小故事会介绍如何将 HUD 分解为 3D 组件的形式来开发。
2018-08-17 - (18)微信3D小游戏下HUD绘制的经验分享
平视显示器(head up display)简称HUD。游戏经常在三维场景上叠加文本或二维图形信息,如弹窗,血量条等,同时需要保证它们在屏幕上的位置和大小不变。 传统的H5游戏可以使用dom,或是在原本的webgl上面盖一个新的2D canvas(画布)做为HUD来实现,同时使用其接口就可以画出HUD所需要的内容。 但微信小游戏只支持一个画布,无法和传统H5游戏的绘制方式一样。因此,要在3D世界中实现HUD就必须在这个唯一的画布上实现。 我们在后台收到了许多反馈:如何用小游戏的框架来实现HUD的绘制。这一期的小故事,我们跟大家分享如何在微信3D小游戏中绘制HUD: 本文的内容包括: 1.微信小游戏只支持一个画布 2.如何使用三维平面模拟HUD? 3.相机变化导致HUD产生位移缩放 4.如何用图形渲染管线解决上述问题? 5.绘制场景时视点变化与投影阶段的问题 6.如何使用顶点着色器解决上述问题? 微信小游戏只支持一个画布 与浏览器不同,微信客户端只有一个画布,并且不能使用html。 普通H5游戏会使用html,或是创建一个新的2D canvas标签,定位在原本的webgl canvas上面,同时使用2D canvas的接口就可以画出HUD的内容。但微信小游戏不支持这样做。所以在三维世界中要实现HUD,需要在一个画布上实现。 所以在三维世界中要实现HUD,则必须在这个唯一的画布上实现。 如何使用三维平面模拟HUD? 对于图像,webgl可以通过纹理贴图来展示图像。开发者可将图片作为的纹理贴图,贴在一个三维矩形平面上,使平面一直正对相机,来模拟HUD。 [图片] 对于文字,微信小游戏三维的canvas是使用webgl作为context的。但是webgl却无法像2D的context能直接画文字。开发者如果直接用webgl画出文字,需要导入文字模型的顶点数据,但由于文字比较复杂,顶点数量多,相当于渲染了一个复杂的3D物体,这种方式无论是从文件大小还是性能上,都会有损体验。 [图片] 那么是否可以使用2D canvas 绘好文字,再作为纹理贴在三维平面上呢? 虽然微信小游戏只能渲染一个canvas,但是开发者可以创建多个的canvas实例。 Step1:开发者可创建一个离屏的2D canvas,再使用2D的接口绘制文字、图片等; Step2:开发者可将这个离屏canvas传给webgl,当成一个texture,贴到一个三维的平面物体上,使其永远都在相机的正前方,通过这样模拟HUD 。 补充 webgl支持直接将canvas作为纹理; void gl.texImage2D(target, level, internalformat, format, type, HTMLCanvasElement? pixels)。 [图片] 相机变化导致HUD产生位移缩放 游戏场景中的相机是会改变的,比如说吃鸡游戏中的第一人称和第三人称视角转化。我们发现了一个问题:当相机的可视范围变化的时候,HUD就会发生形变。 [图片] 那是因为视野看的越广,映射到屏幕上的时候,同一个物体就显得越小。 我们需要保证HUD在任何视角下位置大小都是正确无误的。那么如何才能做到呢? 要解决这个问题就需要明白计算机是如何把三维场景画到二维的屏幕上的。这个画的过程也就是计算机图形渲染管线帮我们完成的。 如何用图形渲染管线解决上述问题? 画一个三维物体到二维平面可以分为三个阶段: ●“准备数据” (应用程序阶段) ●“画点” (几何阶段) ●“画像素” (光栅化阶段) [图片] 一个HUD实际上是一个矩形的平面物体,通过矩形的4个顶点就可以描述出来一个平面的位置、大小。为了让平面的位置,大小看起来没问题,我们需要修改“画点”阶段的逻辑。这个阶段又可以进行如下的细分。 [图片] 与摄影机相关的逻辑,是视点变换还有投影阶段。我们可以通过修改这两者的逻辑来达到我们的目的。 绘制场景时视点变化与投影阶段的问题 1.视点变化阶段的问题 我们需要绘制摄像机看到的世界,而摄像机可以处在任意位置观察这个世界。视点变化本质是就是根据摄像机看的方向来旋转物体,从而让三维空间的物体正确旋转到观察者看到的样子。原本是摆正放的物体,由于观察者的视角问题(歪着看),所以显示出来物体最终也是歪的。 [图片] 通过在应用程序阶段定义相机的视点、观察目标点以及上方向等数据,我们可以得到一个叫做视图矩阵(View Matrix)的矩阵。把这个矩阵与物体的位置做矩阵乘法就可以得到物体变化后的新位置。 因为游戏世界中,摄像机的位置是不停变化的,而我们的物体却需要一直出现在摄像机正前方。所以游戏场景中的视觉矩阵(View Matrix)在每一帧的渲染中,可能都在变化。这里我们只要将HUD原本一直在变化的视觉矩阵(View Matrix)替换为我们需要的,并且保持不变就好了。 2.投影阶段的问题 投影其实是把透视摄像机原本的可视范围,压缩成一个单位立方体。 [图片] 再通过屏幕映射,就会出现如下的效果出来。 [图片] 这一个过程中,会通过摄像机定义的数据(比如长宽比,视场,近截面,远截面),来生成一个叫做投影矩阵(Projection Matrix)的矩阵。将这个矩阵与位置信息进行矩阵乘法,再进行一些归一化操作,就会得到单位立方体内的位置。 和视觉矩阵(View Matrix)一样,对于HUD的物体,我们也不能使用透视摄像机生成的矩阵,否则就会可能导致大小变化。我们替换成正视摄像机的矩阵。这样算出来的位置就是永远都是正常的,不需要担心游戏中更新了相机的数据。 如何使用顶点着色器解决上述问题? 现在我们要用顶点着色器来修改视点变换还有投影的逻辑。 顶点着色器与片元着色器都是 webgl 提供给我们用来操作渲染管线的能力。让我们可以使用glsl 这种编程语言来对 GPU 的能力进行编程。 [图片] 顶点着色器运行在“画点”阶段(几何阶段),也就是对每个三维物体的顶点进行计算。片元着色器运行在“画像素”阶段(光栅化阶段),把顶点围起来的像素(其实是片元)画上颜色。 我们可以通过顶点着色器,修改视点变换与投影的逻辑,最后达到我们的效果。 总结 由于微信小游戏支持一个单独的画布,开发者想要在任何游戏场景下绘制正常的HUD,可以通过顶点着色器的能力,去修改视点变换与投影的所用到的矩阵,最终来解决这个问题。 微信小游戏还有很多与H5游戏、客户端游戏不一样的设计理念与特点,我们会在后续的文章里继续分享微信小游戏背后的小故事。 历史文章回顾 :小程序•小故事 如果大家有想了解的小程序相关能力的故事,欢迎在评论区留言,我们后续会考虑将这些能力背后的故事分期分享给大家。
2018-08-17