关于微信小程序:微信小程序-webview-问题

大家好,我是江辰,这篇文章记录一次在实在的线上环境中,对于 web-view 的问题,大家能够追随作者一起看看心路历程。 本文首发于微信公众号:家养程序猿江辰 欢送大家点赞,珍藏,关注 问题背景上半年最开始做的一版是展业大厅页面和互动白板页面(以下统称 web-view)拆散,前面因为腾讯那边对交互方式不称心,强调肯定要展业大厅页面和白板页面在同一个页面进行交互,最开始咱们没有思路,因为在小程序官网中的形容,web-view 页面不容许叠加任何组件,前面是产品找到一个 demo,发现能够叠加,我这边去翻了下他们的源码(renderingMode: 'seperated'),最终解决了该问题,也就导致前面很多问题的产生。 现存问题web-view 存在的状况安卓更新组件不失效,比方 tab 切换,tab1 切换到 tab2 ,不失效,内容不会更新安卓更新图片不失效安卓更新款式不失效cover-view 文字隐没按钮响应慢,机型性能低的手机比拟显著针对问题 2,目前的 hack 计划,先渲染一张通明的图片,而后再渲染其余图片,能够失效 针对问题 1、2、3,仅在安卓端呈现,苹果手机上没有发现,目前有一个比拟 hack 的计划,通过卸载组件,从新渲染,能够达到目标,然而产生的性能损耗比拟大,对交互体验不敌对,而且也导致了第四点问题的产生 针对问题 4 安卓复现频率比拟高,苹果呈现过一次 针对问题 5 安卓跟苹果都存在 web-view 不存在的状况都失常 尝试过的计划针对 cover-view 文字隐没 设置组件宽高设置字体色彩和背景色彩刷新以上计划,都不行,也没法在开发者工具上查看 DOM 视图 Console 元素的宽高都在,偏移地位也失常,就是文字隐没 DOM 无奈在开发者工具上查看 DOM 视图 景象失常 文字隐没 这个元素的宽高都在,就是文字隐没 微信小程序架构图 展业小程序架构图 解决方案所有人的视频流不再全副获取,而是只显示四路视频流,其余人员要显示,在成员列表进行切换显示重点⼯作中破费精⼒最多的是模块化解耦的重构、我简略说下背景。因为之前咱们代码共建的、 然而因为客户这边定制化的需要有很多,并且不是那么简略的能⽤形象的⽅式把这些⾮通⽤性能的性能实现的、所以咱们想进去的⽅案是:把⼩程序代码⾥划分重点模块,把每个模块都做成可插拔的,这样咱们只须要把差异化很多的局部抽出来齐全独⽴交给⾃⼰开发即可。同时这个⽅案实现好后,如果后续咱们要开发新状态的应⽤,能够通过实现模块的⽅式实现⼀套新的应⽤状态这些优化工作总共工夫大略花了一个月左右,实现之后,目前咱们的产品可能反对到 20+ 人同时进行音视频,这块理论测试过。对咱们的产品稳定性越来越好!

September 11, 2023 · 1 min · jiezi

关于微信小程序:PHP实现微信小程序状态检测违规暂停服务维护中正在修复

实现原理进入那些状态不失常的小程序会被重定向至一个Url,应用抓包软件抓取这个Url,剔除不必要参数,应用cURl函数申请网页取得HTML内容,依据内容解析出以后APPID的小程序的状态。 代码<?php // 编码 header('Content-type:application/json'); // 获取appid $appid = trim($_GET['appid']); // appid正则表达式验证规定 $appid_pattern = '/^wx[a-f0-9]{16}$/'; if($appid) { // 验证appid是否合乎规定 if(!preg_match($appid_pattern, $appid)) { $result = array( 'code' => 201, 'msg' => 'appid不合乎规定' ); }else { // 指标URL $url = 'https://mp.weixin.qq.com/mp/waerrpage?appid='.$appid.'&type=offshelf'; // 初始化cURL会话 $ch = curl_init(); // 设置cURL选项 curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 执行cURL并获取页面内容 $response = curl_exec($ch); // 敞开cURL会话 curl_close($ch); // 获取前面的内容 $str1 = substr($response, strripos($response, "weui-msg__title")); // 获取后面的内容 $str2 = substr($str1, 0, strrpos($str1, "weui-msg__desc")); // 不失常的类型 $close_type_1 = '小程序因违规已暂停服务'; $close_type_2 = '小程序系统故障,开发者正在修复'; $close_type_3 = '小程序已暂停服务'; $close_type_4 = '小程序零碎更新保护中'; // 判断 if(preg_match("/因违规已暂停服务/", $str2)) { $result = array( 'code' => 201, 'msg' => $close_type_1 ); }else if(preg_match("/正在修复/", $str2)) { $result = array( 'code' => 201, 'msg' => $close_type_2 ); }else if(preg_match("/小程序已暂停服务/", $str2)) { $result = array( 'code' => 201, 'msg' => $close_type_3 ); }else if(preg_match("/更新保护中/", $str2)) { $result = array( 'code' => 201, 'msg' => $close_type_4 ); }else{ $result = array( 'code' => 200, 'msg' => '小程序失常' ); } } }else { $result = array( 'code' => 201, 'msg' => '请传入appid' ); } // 输入 echo json_encode($result,JSON_UNESCAPED_UNICODE);?>应用上传miniProgramStatusCheck.php至服务器; ...

September 1, 2023 · 1 min · jiezi

关于微信小程序:微信小游戏关键词搜索优化策略赢得更多流量的秘诀

引言随着挪动互联网的迅速倒退,微信小游戏已成为人们生存中不可或缺的一部分。然而,市场竞争强烈,如何在泛滥小游戏中怀才不遇,吸引更多的用户成为每位开发者都面临的挑战。在本文中,咱们将分享一些要害的关键词搜寻优化策略,帮忙您在微信小游戏平台上取得更多的流量。 关键词钻研和抉择在进行关键词搜寻优化之前,首先须要进行充沛的关键词钻研。理解用户的搜寻习惯、爱好以及与您的小游戏相干的热门话题。借助一些关键词钻研工具,如Google关键词布局工具、百度指数等,您能够取得无关关键词的搜寻量、竞争水平等信息。抉择那些与您的小游戏内容相干且搜寻量适中的关键词。 通过百度指数查看关键词热度: 游戏题目和形容优化游戏的题目和形容是用户首次接触您的小游戏的中央,也是搜索引擎辨认关键词的重要依据。确保您的游戏题目蕴含次要关键词,同时要天然晦涩,不要过分堆砌关键词。游戏形容应该清晰地介绍游戏的玩法、特点以及与关键词相干的内容,吸引用户点击进一步理解。 上面给大家列举一下相干会影响到小游戏被搜寻的设置: 小游戏名称、头像和介绍。在MP后盾-设置-根本设置-根本信息: 小游戏封面图、游戏简介、宣传语、宣传视频、宣传图。在MP后盾-游戏经营工具箱-根底经营素材-经营素材配置: 好友排行榜搜寻展现。在MP后盾-游戏经营工具箱-排行榜设置: 游戏圈。相似贴吧,游戏用户个体分享和交换的中央。在MP后盾-游戏经营工具箱-游戏圈: 明确上述元素展示的中央下面有绝对比拟多的元素,咱们要清晰分明地晓得每个元素将会在哪里并且以什么模式展示到玩家背后。重点给大家解说一下: 状况一:通过上方搜寻框间接搜寻到小游戏的展示的信息包含小游戏的名字、图标和介绍。 状况二:通过微信游戏页面搜寻到小游戏展示的信息包含小游戏的封面图、名字、图标、介绍、3张宣传图、游戏圈: 状况三:如果有上传宣传视频,将会随机代替3张宣传图的地位: 状况四:排行榜在搜寻和小游戏核心的展示模式: 游戏内关键词展现除了在游戏元数据中优化关键词外,您还能够在游戏外部融入相干关键词。这能够通过游戏剧情、提醒、工作等形式实现。这样做不仅能够减少游戏的相关性,还能够进步搜索引擎对游戏内容的了解和评估,有助于更好地匹配用户的搜寻用意。 游戏内显著的大LOGO: 常驻题目: 闪屏图: 依据搜寻数据继续优化理解每个元素展示的地位之后,依据线上数据一直优化资源,调整至最优状态。 1.咱们关上We剖析后盾-平台数据-拜访剖析-搜寻渠道: 2.能够分明地看到昨天的引流人数详情和引流次数详情: 3.搜索词剖析中-Top5搜索词能够分明看到游戏被搜寻展现最多的前五个关键词,曝光次数、曝光人数、引流次数和引流人数。 4.笔者通过一直优化搜寻词条、游戏图标、游戏介绍等要害元素,把搜寻引流的用户达到了还不错的程度: 总结微信小游戏关键词搜寻优化是吸引更多流量的重要策略之一。通过深刻的关键词钻研、优化游戏元数据、融入游戏内关键词、社交媒体营销等伎俩,您能够晋升您的小游戏在微信平台上的可见性和吸引力。然而,要留神合规非法的准则,防止适度堆砌关键词或应用虚伪信息。最终,继续一直的致力和优化将为您博得更多的流量和用户关注。 本文的重点内容次要有以下几点,不晓得小伙伴们是否曾经了解: 关键词的钻研和抉择。游戏在搜寻渠道展示的元素批改的中央。搜寻元素在具体哪些场景展现。通过We剖析剖析数据继续优化要害词条。AD:笔者曾经上线的小游戏《填色之旅》《贪吃蛇掌机经典》《重力迷宫球》大家能够自行搜寻体验。 感兴趣的小伙伴记得关注我哦,一位有着8年游戏行业教训的主程。学习游戏开发不迷路。感谢您的关注,心愿能给到您帮忙, 也心愿通过您能帮忙到大家。 喜爱的能够点个赞、点个在看哦!请把文章分享给你感觉有须要的其余小伙伴。谢谢。 浏览原文

August 20, 2023 · 1 min · jiezi

关于微信小程序:微信开发者工具实现代码加固

一:下载安装node.jsnode.js下载地址:https://nodejs.cn/download/ 二:微信开发者工具装置代码加固拓展1:开发者工具抉择设置-》拓展设置 2:装置代码加固拓展 三:应用代码加固拓展实现外围明码加密1:装置devtool-code-obfuscation 扩大 2:生成代码加固配置文件在我的项目代码区域右击抉择生成加固配置文件 3:代码加固(1):单个文件代码加固抉择须要加固的文件,右击抉择进行代码加固 (2):批量代码加固间接批改 code_obfuscation_config.json 的 configs 字段,就能够实现批量代码加固 4:实现代码加固当开发者实现小程序我的项目开发,点击【预览】/【真机调试】/【上传】显示代码加固提醒,点击确定即可实现代码加固

May 9, 2023 · 1 min · jiezi

关于微信小程序:微信小程序中的值传递

在应用微信小程序的过程中,发现页面向组件中传值或是父子组件中传值并不值传递,本文通过代码试验旨在弄明确值在传递过程中产生的变动。 首先建设一个如下的数据测试类: export class TestModel { public _data = 1; get data() { console.log('call get data'); if (this._data === 1) { this._data = Math.random(); } return this._data; }}而后在C层中应用如下测试语句: const model = new TestModel(); const model1 = new TestModel(); console.log(model.data); console.log(model1._data); this.setData({ testModel: model }); console.log(model === this.data.testModel);最终的运行后果如下: 论断:在调用setData办法时,对象的clone仅限于属性(猜没是用了object 转json而后json又转成了object),办法是不会被clone的。我猜这也是为什么微信小程序在组件传值时,类型仅反对Object但不反对Interface的起因。 而至于为什么会这样,官网是这么解释的: 既然是两个过程,那么在传値时便只能进行序列化与反序列化了,这时是值传递也就难能可贵了。 如果真是这样的话,置信如下的状况会报stack异样: export class BarModel { public fooModel: FooModel;}export class FooModel { public barModel: BarModel;} onLoad() { const barModel = new BarModel(); const fooModel = new FooModel(); barModel.fooModel = fooModel; fooModel.barModel = barModel; this.setData({ fooModel: fooModel }); }, ...

April 26, 2023 · 1 min · jiezi

关于微信小程序:微信小程序除了蓝牙打印还有更好的方法

 最近接到一个需要,客户须要应用打印标签的服务。须要手机端操作,那样就不能应用厂家驱动来应用了,之前没有接触过打印指令,看了当初商用打印机指令罕用的esc/pos挺头疼的,cpcl还好一点不过也须要从新钻研。 一开始曾经有微信小程序的利用,所以打算应用蓝牙来打印,微信小程序目前只反对低功耗蓝牙(BLE),微信的文档 曾经很具体了,就不从新复述了。微信应用蓝牙最大的问题也是低功耗蓝牙,安卓设施能够调用 wx.setBLEMTU 进行 MTU 协商,然而苹果只能应用 20 字节为单位传输,算起来只有2kb/s,内容有图片的时候,打印速度切实太慢,而且微信小程序为啥肯定要地位权限呢(大雾)。 基于下面起因,蓝牙打印的办法就被放弃了。而后接触到jolimarX的云打印机,反对很多品种的接口,总体来说反对html、esc、json、云模版、图片、pdf等等。特地是云模版的接口,只须要在开发平台上注册账号,而后在云模版新建一个模版,依据本人须要设计模版。 设计好模版后点击右上角“打印预览” 在预览页底部能够看到,模版 ID、JSON 图片中 Json 便是调用“打印云模版”中 bill_content 对应的数据如:{"barCode":"20190117001","Kdate":"2019-01-17","billno":"820190117001","receivCom":"映美北京分公司","receiver":"张三","receivAd":"北京市朝阳区向阳公园南路 108 号","receivTel":"010-65953789","seder":"映美深圳分公司","sendAd":"深圳市南山区科技南路九洲电器大厦 708","chargeer":"陆正坤","serviceTel":"0755-8889998","QRcode":"http://open.jolimark.com","remarks":"这批货蕴含CTP535 打印机8000 台,CLP180 打印机 5000 台"} 整个调用参数:template_id:47950d9a18f8f3f2cus_orderid:2018011121paper_type:1order_id:201811231copies:1paper_width:210time_out:180access_token:t123456device_ids:18340058ALapp_id:a123456paper_height:140bill_content:{"barCode":"20190117001","Kdate":"2019-01-17","billno":"820190117001","receivCom":"映美北京分公司","receiver":"张三","receivAd":"北京市朝阳区向阳公园南路 108 号","receivTel":"010-65953789","seder":"映美深圳分公司","sendAd":"深圳市南山区科技南路九洲电器大厦 708","chargeer":"陆正坤","serviceTel":"0755-8889998","QRcode":"http://open.jolimark.com","remarks":"这批货蕴含CTP535 打印机 8000 台,CLP180 打印机 5000 台"} 其中bill_content 内容多,需以 form-data 形式传参。 打印成果 我不必再去计算打印像素值和坐标值了,只有把数据传过来就行,太敌对了。而且对接期间,发现不能应用调用动静图片,跟他们开发人员沟通后,他们示意这个性能很快就上线了。微信小程序抉择云打印办法,挺不便的,大家能够试试。

April 25, 2023 · 1 min · jiezi

关于微信小程序:微信小程序开发过程中需要首先了解一些基础知识

如果你是微信小程序开发的初学者,同时以前还应用过一些其它的前端框架,那么在进行微信小程序开发过程中,可能须要疾速阅览以下的常识: 测试号首先,须要一个用于开发的微信小程序测试账号。申请地址为:https://developers.weixin.qq.com/sandbox ,而后就在微信对立的治理后盾 https://mp.weixin.qq.com/ 上扫码登录时抉择本人的微信小程序测试账号了。 工具微信小程序开发原则上仅仅须要 微信开发者工具,并不需要其它的额定工具。 援用第三方包微信小程序反对援用npm治理的第三方包,但援用的形式与传统的node.js我的项目并不统一。具体还得随时开发随时学习垃圾的官网文档,之所以说须要随时学习,是因为这个文档变动的比拟快。 UI官网提供的WEUI尽管解决不了所有的场景,但在初步接触时必定够了。官网文档地址为:https://wechat-miniprogram.github.io/weui/docs/,坑的是这个DEMO上有些外链是不可用的,而后示例给的也不全,效果图也没有。这是腾讯的垃圾格调。想看具体的应用办法须要移步到:https://github.com/wechat-miniprogram/weui-miniprogram/tree/master/src/example,仅仅想看成果的话也能够简略看看 https://weui.io/ 框架此局部开始是技术相干 路由小程序的路由就是pages,某些路由是否可用,取决于其是否被增加到app.json中的pages属性中。 { "pages": [ "pages/index/index", "pages/login/login", "pages/web-view/web-view", "pages/questionnaire/questionnaire", "pages/template/template", "pages/final-score/final-score" ]}而pages中的第一项则为小程序的默认路由。 路由跳转的根本语法是:wx.navigateTo({url: 'pages的绝对地址'}).then(),当调整的url不存在或是未在pages中时,则会呈现page not found相干的谬误。对于跳转的具体参数,能够查看navigateTo的正文,这个正文还是写的不错的,并不像腾讯的格调。 生命周期小程序的生命周期有3个次要的局部够成,别离是:利用、page页面以及component组件. 利用利用是指整下微信小程序从启动到销毁的全过程,具体请参考官网文档,后期仅应用onShow即可。onShow会在小程序初始化时执行,或是在小程序初切回来的时候执行。 page页面页面与路由对应,所以每个路由即页面,生命周期可参考官网文档, 后期可应用onLoad办法。 component组件组件的生命周期全副在pageLifetimes属性中申明,参考官网文档。后期可应用created。 模板文本插值在组件初始化时,将默认复制data中的数据至V层: data: { foo: 'foo'}<view> {{foo}} </view>属性绑定以后组件(页面) data: {foo: 'foo'}<yz-foo foo="{{foo}}"></yz-foo>yz-foo组件: properties: { foo: { value: '', type: String } }以下是官网给的仅的两个例子: 在组件(页面)初始化时,会将properties上的值传递给data 事件绑定在微信小程序中,默认的点击事件是bindtap,留神齐全是小写。比方:<button bindtap="onTap">点击<button>。同时,并不反对被动传参,比方以下写法是谬误的<button bindtap="onTap(foo)">点击<button>. 而后在C层(页面和组件不一样,请参考: https://developers.weixin.qq.com/miniprogram/dev/reference/ap..., https://developers.weixin.qq.com/miniprogram/dev/reference/ap...)中对应创立onTap办法: onTap(e) { console.log(e);}如果在事件被触发的同时还想获取一些额定参数(比方遍历生成了N个按钮,当按钮被点击事件触发时,咱们心愿晓得是哪个按钮),则须要应用data-xxx来进行绑定: <button data-foo="{{foo}}" bindtap="onTap">点击<button>留神这样写是谬误的:data-foo="foo",而后在点击时能够通过以下办法获取到这个foo: onTap(e) { console.log(e.currentTarget.dataset.foo);}须要特地留神的是,微信小程序是值传递,而不是地址传递。如果此时获取到的foo是另一个对象,而不是你以前那个了。测试如下: data: { foo: { id: 1 } }, onButtonTap: function (e) { var foo = e.currentTarget.dataset.foo; console.log(foo === this.data.foo); },<button data-foo="{{foo}}" bindtap="onButtonTap">传值测试</button> ...

April 25, 2023 · 1 min · jiezi

关于微信小程序:微信小程序如何在事件中传参

在微信小程序中如果应用了wx:for进行渲染时,因为同时生成了很多一样的dom。这时候如果想晓得以后解决的是哪个对象,则须要在事件中进行传参,办法如下: <view data-xxx="{{xxx}}" bindonchange="bindOnChange"></view>此时,当触发bindOnChange事件时,便能够在 C 中接管到应用data-xxx传入的参数了. bindOnChange(e) { console.log(e.currentTarget.dataset.xxx); console.log(e.target.dataset.xxx);}然而不晓得微信出于什么目标,当应用data-xxx来绑定数据时,居然应用的不是地址传递,取而代之是进行值复制。比方: data: { xxx: {value: 123} }, bindOnChange(e) { const xxx = e.currentTarget.dataset.xxx; xxx.value = 234; console.log(this.data.xxx.value); // 后果依然是123 }我想没有应用简略的地址传递而是取而代之了更简单的值传递可能是为了关照老手或是升高小程序框架的难度吧。 另外还有个小坑是,它的语法是:data-xxx="{{foo}}",此时它会复制C层(实际上应该是 C 层中的数据复制(非值传递)到了 V 层)中的data.foo复制过来。如果语法不小心写成data-xxx="foo", 那么此时的foo将做为字符串解决。

April 22, 2023 · 1 min · jiezi

关于微信小程序:小程序因为textarea标签提示语会浮在弹窗上所以用的coverview但是coverview真机显示不了文字

问题:微信小程序:因为textarea标签提醒语会浮在弹窗上,所以用的cover-view,然而cover-view真机显示不了文字 解答方法:在字体的盒子上加上宽高,肯定要width和height都要写上具体的值,自适应的话在某些老旧机型上就是没方法显示或显示全

April 19, 2023 · 1 min · jiezi

关于微信小程序:微信小程序在组件中使用canvas

在微信小程序中的组件中调用canvas,获取节点的时候报错或者找不到canvas,解决方案须要这么写: wx.createSelectorQuery().in(this).select("#canvas").fields({ node: true, size: true}).exec((res) => { // console.log(res) resolve(res[0].node)});

April 10, 2023 · 1 min · jiezi

关于微信小程序:微信小程序关于拍照预览图片上传等

示例图:1:在小程序可见页面减少一个图片展现区域,并给定一个点击事件能够唤起拍照2:容许小程序应用相机权限后进入拍照页面(页面减少了一个头像搁置区域,返回按钮,拍摄按钮,摄像头转换按钮)3:点击拍照按钮拍照4:拍照后进入照片预览页面(页面提供返回重拍和裁剪后预览确认性能,如图红框区域为截图区域,可依照需要自行区域裁剪)5:裁剪后进入图片预览,并将图片转换成base64格局,与后端接口进行对接 文件代码centre:示例图1carame:示例图2,3,4preview:示例图5we-cropper:提供示例图4的缩放和剪裁性能(动态资源文件,下载后间接放到pages文件夹下,在carema.js中引入即可,官网下载可点击) 代码摘要示例图1:按钮触发后,进入carema页面示例图2: <view class="caream-wrap"> <camera device-position="{{cameraPos}}" class="carema-area" wx:if="{{showCamera}}"> <camera-view class="carema-anchor"> <image mode="widthFix" class="carema-anchor-img" src="/images/anchor.png"></image> </camera-view> </camera> <view class="CameraOptions" wx:if="{{showCamera}}"> <view class="takePicBtn"> <!-- 摄像头的返回按钮 --> <view class="takephotoicon"> <image mode="widthFix" class="confirm" src="/images/caremaback.png" bindtap="goBack"></image> </view> <!-- 照相的按钮 --> <view bindtap="getPhoto" class="takephotoicon"> <view class="outter-shoot"> <view class="inner-shoot"></view> </view> </view> <!-- 摄像头的前后转换按钮 --> <view class="takephotoicon"> <image mode="widthFix" class="switch" src="/images/switch.png" bindtap='changePos'></image> </view> </view> </view><!--剪裁区域--> <import src="../we-cropper/we-cropper.wxml" /> <view class="cropper-wrapper" wx:if="{{!showCamera}}"> <template is="we-cropper" data="{{...cropperOpt}}" /> </view> <view class="cropper-buttons" wx:if="{{!showCamera}}"> <view class="cancel" bindtap="handleCloseCropper">重拍</view> <view class="getCropperImage" bindtap="getCropperImage">确定并预览</view> </view></view>js import WeCropper from '../we-cropper/we-cropper.js'const device = wx.getSystemInfoSync(); // 获取设施信息const width = device.windowWidth; // 获取设施宽,不便设置画布和裁剪框宽度const height = device.windowHeight; // 获取设施高,不便设置画布和裁剪框高度Page({ data: { cropperOpt: { id: 'cropper', // 用于手势操作的canvas组件标识符 targetId: 'targetCropper', // 用于用于生成截图的canvas组件标识符 pixelRatio: device.pixelRatio, // 传入设施像素比 width, // 画布宽度 height: 413, // 画布高度 scale: 2.5, // 最大缩放倍数 zoom: 8, // 缩放系数 src: "", cut: { x: (width - 295) / 2, // 裁剪框x轴终点 y: 0, // 裁剪框y轴期终点 width: 295, // 裁剪框宽度 height: 413 // 裁剪框高度 } }, imageUrl: "", cameraPos: 'front', showCamera: true, wecropper: '' }, // 照相 getPhoto() { // c创立相机上下文对象,获取惟一的相机对象 var context = wx.createCameraContext() // 照相性能 context.takePhoto({ quality: "low", success: res => { // 照相胜利的回调 console.log(res); // 图片的信息 this.setData({ // 暗藏相机 showCamera: false, imageUrl: res.tempImagePath, src: res.tempImagePath, }) // 实例化WeCropper this.createCropper(); }, fail: () => { wx.showToast({ title: '呈现谬误', }) } }) }, createCropper() { const that = this let { cropperOpt } = that.data cropperOpt.src = that.data.imageUrl; let wecropper = new WeCropper(cropperOpt).on('ready', (ctx) => {}).on('beforeImageLoad', (ctx) => { }).on('imageLoad', (ctx) => {}) this.setData({ wecropper, }) }, // 相机前后镜头转换 changePos() { this.setData({ cameraPos: this.data.cameraPos == "back" ? "front" : "back" }) }, // 敞开相机,回退到个集体核心 goBack() { wx.switchTab({ url: '../centre/centre', }) }, //点击勾销裁剪 handleCloseCropper() { console.log(11111) this.setData({ showCamera: true }); }, touchStart(e) { this.wecropper.touchStart(e) }, touchMove(e) { this.wecropper.touchMove(e) }, touchEnd(e) { this.wecropper.touchEnd(e) }, getCropperImage() { wx.setStorageSync('caremapreview', null); this.data.wecropper.getCropperImage((tempFilePath) => { console.log(tempFilePath) // tempFilePath 为裁剪后的图片长期门路 if (tempFilePath) { this.setData({ // 暗藏相机 imageUrl: tempFilePath }) wx.getImageInfo({ src: tempFilePath, success(imageInfo) { let imgType = imageInfo.type wx.getFileSystemManager().readFile({ filePath: tempFilePath, encoding: "base64", success: res => { //返回base64格局 let base64Str = 'data:image/' + imgType + ';base64,' + res.data wx.setStorageSync('caremapreview', { imgurl: base64Str, }); wx.navigateTo({ url: '../preview/preview', }) }, fail: err => { console.log(err) } }) } }) } else { wx.showModal({ title: '获取图片地址失败,请稍后重试', icon: 'success' }) } }) },})外围办法阐明getCropperImage()实现了剪裁图片长期地址的额获取,并且在取得地址后应用微信自带的wx.getFileSystemManager().readFile()办法实现了将temp地址转换成base64格局。base64暂存入StorageSync,便于preview页面获取base64地址并展现 ...

April 3, 2023 · 2 min · jiezi

关于微信小程序:微信小程序npm构建报错-NPM-packages-not-found

在project.config.json中删去 { "miniprogramRoot": "miniprogram/"}增加 { "packNpmManually": true, "packNpmRelationList": [ { "packageJsonPath": "./package.json", "miniprogramNpmDistDir": "./miniprogram/" } ]}

February 24, 2023 · 1 min · jiezi

关于微信小程序:微信小程序获取用户头像信息以及修改用户头像

这里次要用到button的open-type性能,官网已有阐明:给button设置open-type="chooseAvatar",来使bindchooseavatar办法失效,在bindchooseavatar指定的函数中获取用户的头像信息 <button open-type="chooseAvatar" bindchooseavatar="chooseavatar"></button> chooseavatar(e){ this.setData({ avatar: e.detail.avatarUrl })}, 该办法触发后会自动弹出提示框,让用户抉择头像,用户抉择的头像会在bindchooseavatar指定的函数内获取,e.detail.avatarUrl就是以后的头像信息。调用批改用户信息接口,传入该门路信息即可。

February 1, 2023 · 1 min · jiezi

关于微信小程序:微信小程序分类菜单激活状态跟随列表滚动自动切换

这里次要用到微信小程序提供的SelectorQuery获取页面节点信息实现,组件用的是微信小程序的scroll-view逻辑就是获取右侧盒子的节点信息,获取右侧子分类的节点信息,当子分类滑动到顶部的之后,则切换左侧分类状态,而且当右侧子分类的地位处于触顶以及蕴含顶部地位的状态下,同样激活左侧分类状态。 view构造左侧父级分类 <scroll-view class="left" scroll-y > <view class="{{item.id == active ? 'left_current left_box' : 'left_box'}}" wx:for="{{leftData}}" wx:key="index" bindtap="leftClick" data-id="{{item.id}}" >{{item.catName}}</view> </scroll-view>右侧子分类 <scroll-view class="right" scroll-y scroll-into-view="{{'chunk'+ activeClassifyId}}" scroll-with-animation bindscroll="scroll" > <view class="right_box" wx:for="{{rightData}}" wx:key="index" id="{{'chunk'+ item.id}}" > <view class="right_title">{{item.name}}</view> <view class="right_innerBox" wx:for-item="item2" wx:for="{{item.list}}" wx:key="index2" > <view>{{item2.name}}</view> </view> </view> </scroll-view>css的局部大家本人依照需要写即可。 js局部data:{ // ...数据... active:'', // 左侧分类激活 activeClassifyId :'' // 滚动定位的id} // 左侧分类点击 leftClick(e){ // 以后分类id let { id } = e.currentTarget.dataset this.setData({ active:id, // 左侧激活的id activeClassifyId : id // 分类定位的id }) // activeClassifyId分类定位的id不应该和左侧激活的id是同一个,否则左侧激活会在上面的滚动事件内继续触发,导致无奈滚动。 }, // 右侧滚动触发 scroll(){ let { rightData } = this.data rightData.map(item=>{ if(item.list.length>0){ // 返回一个 SelectorQuery 对象实例。获取页面的节点信息。 const query = wx.createSelectorQuery() query.select('#chunk'+item.id) // 获取id为chunkID的元素 .boundingClientRect(ref=>{ // 获取节点宽高信息和地位信息 // 如果以后的子分类滚动到了顶部以及以后子分类正处于顶部的地位 if(0>ref.top&&ref.top>(ref.height*-1)){ this.setData({active :item.id}) // 切换左侧父分类的高亮 } }).exec() } }) },属性解释:scroll-with-animation:在设置滚动条地位时应用动画过渡scroll-into-view:值应为某子元素id(id不能以数字结尾)。设置哪个方向可滚动,则在哪个方向滚动到该元素bindscroll:滚动时触发的事件event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY}createSelectorQuery:返回一个 SelectorQuery 对象实例。获取页面的节点信息。select:获取id的元素boundingClientRect:获取节点宽高信息和地位信息 ...

January 30, 2023 · 1 min · jiezi

关于微信小程序:微信小程序wxnavigateTo跳转参数大小超出限制问题

微信小程序的跳转形式 wx.navigateTo(Object):保留以后页面,跳转到利用内的某个页面,应用 wx.navigateBack 能够返回到原页(新页面入栈)wx.redirectTo(Object):敞开以后页面,跳转到利用内的某个页面(以后页面出栈,新页面入栈)wx.switchTab(Object):跳转到 tabBar 页面,同时敞开其余非 tabBar 页面(非Tab页面全副出栈,只留下新的 Tab 页面)wx.navigateBack(Object):返回上一页面(页面一直出栈)wx.reLaunch(Object):敞开所有页面,关上到利用内的某个页面(页面全副出栈,只留下新的页面) 跳转携带参数的办法:在跳转的链接后接?参数名=参数 wx.redirectTo({ url: `../heartOrder/index?Info=${JSON.stringify(obj)}`})跳转携带的参数必须转换为字符串,否则报错。 小程序跳转带参的字符长度是受限制的,如果字符过长,会被截取掉,解决办法如下:应用encodeURIComponent和decodeURIComponent对字符进行编码和解码encodeURIComponent(url):可把字符串作为 URI 组件进行编码,返回URIstring 的正本,其中的某些字符将被十六进制的转义序列进行替换。 该办法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。其余字符(比方 :;/?: @&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。decodeURIComponent(url) :可把字符串作为 URI 组件进行解码。返回URIstring 的正本,其中的某些字符将被十六进制的转义序列进行替换。 跳转页 wx.redirectTo({ url: `../heartOrder/index?Info=${encodeURIComponent(JSON.stringify(obj))}`})接管页 onLoad(options) { let { Info} = options Info = JSON.parse(decodeURIComponent(Info))}

January 30, 2023 · 1 min · jiezi

关于微信小程序:微信小程序防抖

微信小程序闭包-防抖这里次要用到闭包,将函数内的值保留下来,下次点击的时候进入判断,如果定时器启动了,则革除定时器,直到最初一次启动定时器,也就是说,在规定的工夫内只会触发最初一次定时器,从而达到防抖成果。 防抖的应用场景: 避免间断疾速点击避免滚动条触底时的频繁事件触发办法一: data: { name : null }, time : null, // 滚动条触底 scrollLower(){ console.log('触底',this.time); clearTimeout(this.time) this.time = setTimeout(()=>{ console.log('防抖',this.time); },1000) },办法二: // 滚动条触底 scrollLower(){ this.light() // 如果要携带参数在这 }, light : (function() { let i = null console.log('触底',i); return function() { // 接管携带的参数在这 if(i != null) clearTimeout(i) i = setTimeout(()=>{ console.log('防抖',i); },1000) } })(),微信小程序外层不反对const fn = function() 这种语法,所以这里只能以对象的模式定义函数:fn : function(){} js闭包 <button id="attick">点击</button> <script> let attick = document.getElementById('attick') attick.addEventListener('click',function(){ light() }) // 点击 const light = (function() { let i = null console.log('点击',i); return function() { if(i != null) clearTimeout(i) // 革除定时器 i = setTimeout(()=>{ console.log('点击000',i); // 1s内无操作才会触发且只触发最初一次 },1000) } })() </script>

January 30, 2023 · 1 min · jiezi

关于微信小程序:盲盒抽奖流程

盲盒模块的流程大抵如下:进入盲盒抽奖页面,须要初始化间接获取一些盲盒的信息,例如:盲盒流动id,开奖buff等。首先须要获取盲盒流动id,前面的所有申请都是基于盲盒流动id进行的。 初始化获取: 盲盒流动id`抽奖buff校验抽奖活动状态:判断以后流动是否开启抽奖次数:获取以后流动的抽奖次数,以后用户残余抽奖次数工作次数:获取以后流动的工作(分享)次数,也就是残余分享次数获取分享邀请码:获取以后流动的分享邀请码,此码用于分享好友助力,好友进入分享页面后依据抽奖流动id和分享邀请码来为用户助力。一个用户一个流动只取得一个邀请码,不同的用户获取的邀请码是不同的。以后流动信息:获取以后的流动信息,返回的字段有流动id、名称、备注、图片等,依据这些信息,在分享的时候能够设置对应的文案、图片、id等信息。如果奖池预览是动静的,那么初始化也要申请奖池预览的信息。 抽奖buff模块因为初始化间接申请接口了,那么这里就能够间接拿到buff的信息,点击开buff的时候,间接开启动画渲染buff信息即可。 流动规定和我的奖品为弹框和跳转。 开盲盒这里须要判断一下以后盲盒的状态,是否是可开启的,并且是否有残余抽奖次数,如果条件都合乎,那么就申请开盲盒的接口开奖,如果不合乎则弹框提醒“抽奖次数有余,分享可取得抽奖次数”的弹框。盲盒开奖后抽奖次数必定会缩小,所以这里开完将须要申请初始化的一些接口,比方获取抽奖次数的接口,刷新以后的开奖次数信息。 获取机会:这里应用微信的凋谢能力bottom的open-type="share"的分享性能 onShareAppMessage(e) { if(e.from == "button") { console.log('按钮分享'); return { title: `点击助力“${userInfo.name}”,开盒助力,100%中奖`, //分享进来的题目 imageUrl: "图片门路", //分享时显示的图片 path: `/pages/home/index?goodsid=${xxx}`//他人点击链接进来的页面及传递的参数 } } else { console.log('胶囊分享'); return { title: `盲盒大礼,参加即得!`, //分享进来的题目 imageUrl: "图片门路", //分享时显示的图片 path: `/pages/home/index`//他人点击链接进来的页面及传递的参数 } } }用户点击分享的时候,须要携带分享码以及流动id,好友通过这两个参数为用户助力。点击分享的时候还须要申请分享操作的接口,在分享的接口里,可能有不同类型的分享,这里须要做一步逻辑判断,以后为哪种分享,是邀请还是分享操作还是邀请操作,而后再申请接口创立分享。

January 30, 2023 · 1 min · jiezi

关于微信小程序:微信小程序分包

当咱们程序太大的时候,关上小程序就会比较慢,此处就须要用到分包加载,依照模块划分不同的包,让用户在须要的时候才加载对用的模块,也就是用户在进入某些页面的时候才下载该页面的资源,进步小程序的关上速度,以及首次加载资源的速度。通常状况下,咱们建的文件都在根文件夹下的pages外面根文件夹其实就是主包,主包的文件对应在app.json中pages内的门路,比方在pages内新建一个home文件夹,home文件夹内新建index.wxml文件。小程序在关上的时候会加载主包内的内容,如果所有文件都写在主包,那么关上小程序的时候会加载大量资源,导致小程序关上迟缓。 解决办法:分包加载比方在这里要新建一个积分专区,那么主包内只须要新建一个对应的文件夹,这个是tabbar文件,必备,进入积分专区后,在专区内跳转的页面指定到子包,对应的模块在子包内实现。 新建子包在根文件夹下新建一个文件夹,文件夹能够依据模块来命名,新建文件夹后在app.json中配置。subpackages就是子包,外部的{"root":'xxx'}就是子包的文件夹名 { "root" : 'xxxx'}pages就是文件夹下的文件门路,跟失常新建的文件流程一样。如果要新建多个分包则在subpackages内配置多个包即可。 "subpackages" : { { "root": "包1", "name": "包1", "pages": [ "门路" ] }, { "root" : '包2' ..... }}

January 30, 2023 · 1 min · jiezi

关于微信小程序:微信小程序项目中使用icon图标

成果:步骤:1、先让ui负责人把你的账号退出到我的项目中,退出到我的项目中后就能够在icon图标库中看到该我的项目2、在小程序中应用新建一个view,在下面加一个class,复制icon名字下来即可,留神格局,格局为iconfont icon名。 iconfont这个前缀不是固定的,依据icon名字来,icon的前缀为my-icon-xxxx,那么前缀就是 my-icon没有前缀或者设置了前缀,个别都是应用iconfont,依据我的项目视状况而定,这里以my-icon举例。my-icon my-icon-fontxxx // 前缀 icon名 // 应用icon <view class="fontxxx my-icon my-icon-fontxxx "></view>// 设置icon款式 .fontxxx { font-size:30rpx; color:blue; } 下面演示的是曾经引入了icon的状况,如果没有引入则须要在iconfont图标库下载图标至本地,而后将文件外部的iconfont.css更名为iconfont.wxss,放入到根文件夹的style中即可失常应用。

January 30, 2023 · 1 min · jiezi

关于微信小程序:微信小程序数字转中文wxs

场景: 传入数字,转换成天数,比方:index = 1 转换后则为 一,在页面中的利用就是<view>第{{index}}天</view>,转为第几天。 <view>第{{exchange.exChangeNum(index)}}天</view><wxs module="exchange"> /** * 将数字(整数)转为汉字 * @param num * @description 从零到一亿亿,须要小数的可自行截取小数点前面的数字间接替换对应arr1的读法就行了 */var exChangeNum = function (num) { var arr1 = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']; var arr2 = ['', '十', '百', '千', '万', '十', '百', '千', '亿', '十', '百', '千', '万', '十', '百', '千', '亿'];//可持续追加更高位转换值 if (!num || isNaN(num)) { return "零"; } var english = num.toString().split(""); var result = ""; for (var i = 0; i < english.length; i++) { var des_i = english.length - 1 - i; //倒序排列设值 result = arr2[i] + result; var arr1_index = english[des_i]; result = arr1[+arr1_index] + result; } //将【零千、零百】换成【零】 【十零】换成【十】 result = result.replace(getRegExp('零(千|百|十)', 'g'), '零').replace(getRegExp('十零', 'g'), '十'); //合并两头多个零为一个零 result = result.replace(getRegExp('零+', 'g'), '零'); //将【零亿】换成【亿】【零万】换成【万】 result = result.replace(getRegExp('零亿', 'g'), '亿').replace(getRegExp('零万', 'g'), '万'); //将【亿万】换成【亿】 result = result.replace(getRegExp('亿万', 'g'), '亿'); //移除开端的零 result = result.replace(getRegExp('零+$'), ''); //将【零一十】换成【零十】 //result = result.replace(/零一十/g, '零十');//貌似正规读法是零一十 //将【一十】换成【十】 result = result.replace(getRegExp('^一十', 'g'), '十'); return result;}module.exports.exChangeNum = exChangeNum;</wxs>对于wsx的应用请看:微信小程序wxs应用以及在页面中调用函数 ...

January 30, 2023 · 1 min · jiezi

关于微信小程序:微信小程序组件封装传值以及问题点规避

封装组件1、在components文件加下新建组件文件夹,在该文件夹下新建组件2、在app.json中注册该组件 "usingComponents": { "page": "components/auth/index", "componentB":"/components/componentB/componentB.js" },3、子组件1、组件的json中,设置该页面为组件 { "component": true}2、组件js // pages/integral/integralRules/index.js.jsComponent({ behaviors: [], // 父组件传入的值在这里,传入的值在这里承受 properties: { ruleShow : Boolean // 父组件的值 }, data: { ruleShow:false, }, // 公有数据,可用于模版渲染 // 生命周期函数,能够为函数,或一个在methods段中定义的办法名 attached: function () {}, moved: function () { }, detached: function () { }, methods: { // 此处编写办法 onClickHide() { this.setData({ ruleShow: false }); } }})4、父组件1、父组件的json中引入子组件 { "usingComponents": { "componentB":"/component/componentB/componentB.js" }}2、页面应用,父传子 <page pclass="page"> // 加上page 会占位 <view> // .... // json中引入的名字在这里应用,这里就是引入的组件 // ruleShow为自定义名称,{{xxx}}为父组件传入的值 <componentB ruleShow='{{ruleShow}}'></componentB> </view></page> data: { ruleShow: false, }, // 规定弹框 showFunction() { console.log('更改父组件的值'); this.setData({ ruleShow : true }) } // 这里更改的值会回传给子组件 ...

January 30, 2023 · 1 min · jiezi

关于微信小程序:微信小程序自定义导航栏机型适配

自定义微信小程序头部导航栏,有几种形式 形式一{ "navigationStyle": "custom" // 将navigationStyle从默认default改为custom}定义此办法后,头部的导航栏会去掉,导航栏下的元素会间接向上挪动到原导航栏的地位,能够再app.json配置成全局沉迷式导航栏,以及在单页面配置沉迷式导航栏。 形式二应用组件这里应用vant组件作为演示组件配置的NavBar,款式在官网文档上有阐明,依据文档阐明批改款式即可。官网文档:https://vant-contrib.gitee.io/vant-weapp/#/nav-bar 机型适配因为自定义navBar了,导航栏上面的元素会间接向上偏移,须要离顶部的间隔才能够复原到失常的地位,此时设置的间隔依据不同的机型,地位也会不同,所以这里就须要做到机型适配。形式一:依据微信小程序胶囊到顶部以及胶囊的高度,算出navBar下的内容到顶部的间隔 // jslet pillHeight = wx.getMenuButtonBoundingClientRect().top // 胶囊到顶部的高度let pill = wx.getMenuButtonBoundingClientRect().height // 胶囊的高度this.setData({topHeight : pillHeight +pill })// 页面 动静设置margin-top高度 <view class="content_bg" style="margin-top: {{capsuleHeight}}px;">内容</view>形式二:依据小程序头部的高度加导航高度的间隔动静计算内容到顶部的间隔 // js wx.getSystemInfo({ success: res => { let navWindowHeight = res.statusBarHeight + 46; // 小程序头部的高度 + 导航高度 this.setData({capsuleHeight : navWindowHeight }) // 赋值高度 }, fail(err) { console.log(err); }// 页面<view class="content_bg" style="margin-top: {{capsuleHeight }}px;">内容</view>因为机型的不同,动静计算的高度也不同,不同机型对胶囊到顶部的高度都有差别,而且获取到的胶囊到顶部或者小程序头部的高度的值单位是 px ,所以间接将获取到的值赋值给间隔顶部的间隔即可,否则在动静计算高度的时候,px不会动静适配屏幕的大小变动,目前来说用形式二适配率高一些,在开发的时候须要依据理论状况,做不同的调整。 动静计算TabBar的高度 // tabbar高度 getTabHei() { wx.getSystemInfo({ success: (res) => { console.log(res) this.setData({ tabBatHeight: res.screenHeight - res.safeArea.bottom + 50 }) } })将计算出来的tabBatHeight间接写在页面的行内款式中即可 ...

January 30, 2023 · 1 min · jiezi

关于微信小程序:微信小程序支付

微信小程序的领取只有用到官网的领取API : wx.requestPayment(Object object)官网文档地址:https://developers.weixin.qq.com/miniprogram/dev/api/payment/wx.requestPayment.html 调用微信小程序领取须要携带以下几个参数,领取胜利后在success胜利的回调内做对应操作 示例代码 wx.requestPayment({ timeStamp: 1414561699, // 工夫戳,从 1970 年 1 月 1 日 00:00:00 至今的秒数,即以后的工夫 nonceStr: 'xxxxxx', // 随机字符串,长度为32个字符以下 package: 'xxxxxxxxxxxx', // 对立下单接口返回的 prepay_id 参数值,提交格局如:prepay_id=*** signType: 'MD5', // 签名算法,应与后盾下单时的值统一 paySign: 'xxxxxxxxxx', // 签名,具体见微信领取文档 success (res) { // 胜利的回调 wx.showToast({title: '付款胜利'}) }, fail (res) { // 失败的回调 wx.showToast({title: '领取失败',icon: 'none'}) } })})个别状况下,领取流程是这样的:商品页抉择商品 ——> 提交商品订单(跳转到领取页) ——> 确认收货地址 ——> 确认提交 ——> 领取 ——> 领取胜利领取胜利后在success的回调内做对应操作,能够跳转到领取胜利页面,让用户在此页面点击查看订单或者在此页面点击浏览更多商品。 1、在操作商品数量计算价格这里,申请计算价格的接口,此处能够前端计算也能够申请接口计算,如果有接口,肯定要申请接口计算。2、在计算价格这块,优惠券抉择了也要从新计算价格,通常在点击购买的这一步就间接申请优惠券接口,返回以后最优的优惠券搭配以及计算价格并渲染到页面,用户自主更改优惠券搭配后须要从新计算价格。3、订单在领取的时候勾销,订单进到待付款页面。

January 30, 2023 · 1 min · jiezi

关于微信小程序:微信小程序转发好友以及中文标题乱码问题解决

微信小程序的转发性能,参考官网文档,应用的buttom的open-type性能,上面是转发性能的具体实现。 // 通过按钮的 open-type="share"实现转发,触发onShareAppMessage函数 <button open-type="share">转发</button> // 用户点击右上角分享 & 转发 onShareAppMessage() { return { title: decodeURIComponent('自定义题目'), //分享进来的题目 imageUrl: "图片门路", //分享时显示的图片 path: "/pages/goodsDetail/goodsDetail" + id//他人点击链接进来的页面及传递的参数 } }某些时候,转发分享的中文题目为乱码,例如: %5456%654/545/45%5456解决办法如下: onShareAppMessage() { return { title: decodeURIComponent('自定义题目'), //此处用decodeURIComponent()转码解决 imageUrl: "图片门路", path: "/pages/goodsDetail/goodsDetail" + id//他人点击链接进来的页面及传递的参数 } }

January 30, 2023 · 1 min · jiezi

关于微信小程序:微信小程序关于地址信息的接入以及自动选择当前位置

在做收货地址的时候,通常会让用户填写或者关上地图抉择播种地址,此时就须要用到微信提供的地址API,在应用地址API的时候须要注册对应的API,而且地址API会常常调整,须要关注官网布告,上面就是对于地址API的应用。第一局部先看下此设置有没有关上 进入微信开发者文档,在API下找到地位,此处就是地位信息API了在应用地位信息之前,须要在app.json中注册地位信息api此处我应用的是wx.chooseLocation,所以在app.json中注册这个api即可注册实现后,在页面应用 // 抉择地址 在事件内调用这个api即可 wx.chooseLocation({ latitude: 0, success(res){ console.log(res); // 抉择的地址信息 } }) },第二局部局部API会弹出须要在app.json中申明permission字段尽管在requiredPrivateInfos注册过然而还须要在permission中注册 此时再应用API即可 // 获取以后地址信息 wx.getLocation({ type: 'gcj02', //返回能够用于 wx.openLocation 的经纬度 success (res) { const latitude = res.latitude // 维度 const longitude = res.longitude // 经度 wx.openLocation({ latitude, longitude, scale: 18 }) } }) 关上地位信息,主动定位到以后地位 // 地址 addAddress(){ let that = this // 抉择地址 wx.getLocation({ // 获取以后地址信息,地理位置、速度 type: 'gcj02', //返回能够用于 wx.openLocation 的经纬度 success (res) { const latitude = res.latitude // 维度 const longitude = res.longitude // 经度 wx.chooseLocation({ // 通过经纬度主动定位到以后地位 latitude, // 维度 longitude, // 经度 success(res){ wx.setStorageSync('address', res.address+res.name) that.setData({ address : res.address+res.name // 将以后地位信息保留,回显 }) } }) } }) },

January 30, 2023 · 1 min · jiezi

关于微信小程序:原生微信小程序跳转传参-非TabBar跳转传参-和-TabBar跳转传参

个别罕用的微信小程序跳转分为两种1、非TabBar跳转2、TabBar跳转 1、非TabBar跳转非TabBar页面的跳转通常应用wx.navigateTo来跳转页面,在链接前面加 ? 传参,如下: // 跳转页面 ? 前面传参 goods_id = 参数 wx.navigateTo({ url: `../goodsDetail/goodsDetail?goods_id=${goodsid}`, })// 跳转页面接参 onLoad(options) { // 此处的options.goods_id 就是页面跳转传过来的参数 this.setData({ goods_id : options.goods_id }) },2、TabBar跳转跳转TabBar页面,个别应用wx.switchTab跳转,跳转TabBar惯例的带参形式是不行的,官网文档已有阐明所以这里无奈在链接上带参,此处能够应用全局变量 getApp() ,具体操作如下: // 跳转购物车 jumpCart() { // 给全局变量增加一个参数 id getApp().id = 1 wx.switchTab({ url: '/pages/cart/cart' }) },// 购物车页面let app = getApp() // 获取全局变量Page({ onLoad(options) { console.log(app.id); // 此处的app.id就是上个页面跳转带过去的参数 },)}

January 30, 2023 · 1 min · jiezi

关于微信小程序:微信小程序自定义tabbar图标切换点击两次才选中解决方法

微信小程序开发过程中应用了自定义tabBar,运行官网提供的demo是没有问题的,然而本人增加了新的tab-item后点击会呈现谬误,具体表现为:点击一次tab跳到指定的页面,然而tabBar的状态还停留在上一个,再次点击能力更新。问题剖析Component({ data: { selected: 0, color: "#7A7E83", selectedColor: "#3cc51f", list: [{ pagePath: "/index/index", iconPath: "/image/icon_component.png", selectedIconPath: "/image/icon_component_HL.png", text: "组件" }, { pagePath: "/index/index2", iconPath: "/image/icon_API.png", selectedIconPath: "/image/icon_API_HL.png", text: "接口" }] }, attached() { }, methods: { switchTab(e) { const data = e.currentTarget.dataset const url = data.path wx.switchTab({url}) this.setData({ selected: data.index }) } }})在methods的switchTab()办法中看似在切换tab后更新了以后选中的tab,然而这样是不够的,能够查看对应页面的show()中官网还增加了上面的代码: // 组件页面show() { if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setData({ selected: 0 }) }}// 接口页面show() { if (typeof this.getTabBar === 'function' && this.getTabBar()) { this.getTabBar().setData({ selected: 1 }) }}咱们本人新增加的页面正是应为短少了这段代码,才会呈现开始提到的问题。在新增的页面增加即可解决,留神你的selected值应该是tabBar数组中对应的index。 ...

January 13, 2023 · 1 min · jiezi

关于微信小程序:如何制作自动输入短信验证码

成果展现: 前置筹备:搭建实现,待进行数据配置的页面具体步骤:增加动静容数据容器组件、标签文本和输入框组件进行发送验证码触发器配置验证码输入框配置键盘上方验证码接收器配置配置数据中心增加事件核心步骤合成:增加动静容器组件、标签文本和输入框组件增加 标签文本 动态数据容器 组件到同一地位,动态数据容器 在置后, 标签文本 置前增加 输入框 动态数据容器 组件到同一地位,动态数据容器 在置后, 输入框 置前 进行发送验证码触发器配置选中发送验证码 标签文本增加发送验证码 触发器 ,并进行数据配置 验证码输入框配置选中 输入框 组件在 触发器 中 增加 收到验证码 触发器 并进行数据配置选中验证码输入框 动态数据容器 组件在 数据绑定及设置 绑定数据 键盘上方验证码接收器配置选中键盘上方接收器 动态数据容器 组件在 触发器 中,增加更新 触发器 并进行数据配置在 触发器 中,增加查问 触发器 并进行数据配置在 数据绑定及设置 中,绑定数据选中数字点击下来 标签文本 组件在 触发器 中,增加送 触发器 并进行数据配置在 数据绑定及设置 中,批改 自定义数据 配置数据中心在面板上方 数据中心 创立验证码数据表格 增加事件核心在面板上方 事件核心 增加 数据事件 验证码查问,进行数据配置增加 数据事件 Update,进行数据配置 ...

January 13, 2023 · 1 min · jiezi

关于微信小程序:如何制作价格筛选并刷新商品列表

通过应用事件中对数字的范畴查问,实现筛选性能成果展现 前置筹备循环列表具体步骤创立数据表创立查问事件制作一个按钮制作价格筛选滑块制作价格输入框创立商品展现触发器创立价格随滑块实时展现触发器步骤合成创立数据表点击 数据中心创立数据表 创立查问事件点击 事件核心配置事件 制作一个按钮拖拽 按钮 到 根容器选中 按钮点击 查看面板 中的 款式配置款式 制作价格筛选滑块拖拽 滑块 到 根容器选中 滑块点击 查看面板 中的 数据绑定与设置配置数据 制作价格输入框拖拽 输入框 到 根容器点击 查看面板 中的 数据绑定与设置配置数据 创立商品展现触发器选中 循环容器点击 查看面板 中的 触发器创立 触发器 选中 循环条目点击 查看面板 中的 数据绑定与设置绑定数据 选中 按钮点击 查看面板 中的 触发器创立 触发器 创立价格随滑块实时展现触发器选中 滑块点击 查看面板 中的 触发器创立 触发器 这样就能够实现价格筛选并刷新商品列表了。官网链接:https://www.towify.com

January 12, 2023 · 1 min · jiezi

关于微信小程序:如何实现消息条目选中变色

成果展现 前置筹备1.音讯列表 具体步骤1.配置点击款式 2.创立触发器 步骤合成1.配置点击款式1.1. 选中 循环条目 1.2. 点击 查看面板 中的 款式 1.3. 创立款式 1.4. 款式切换为 选中 2.创立触发器2.1. 选中循环条目 2.2. 点击 查看面板 中的 触发器 2.3. 创立触发器 这样就能够实现音讯条目选中变色了。官网链接:https://www.towify.com

January 12, 2023 · 1 min · jiezi

关于微信小程序:如何制作知识问答页面

成果展现: 前置筹备:搭建实现带配置触发器的页面具体步骤:配置谬误答案触发器配置正确答案触发器步骤合成:配置谬误答案触发器选中谬误答案 容器在右侧上方面板 触发器 中增加谬误答案触发器,并进行数据配置 配置正确答案触发器选中正确答案 容器在右侧上方面板 触发器 中增加正确答案触发器,并进行数据配置

January 11, 2023 · 1 min · jiezi

关于微信小程序:如何在小程序里实现一个随机关注列表

应用随机查问能够实现一个随机的换一换性能。 成果展现 前置筹备1.已制作的换一换关注列表 具体步骤1.创立数据表 2.创立随机查问事件 3.创立关注列表展现触发器 4.绑定数据 步骤合成1.创立数据表1.1. 点击 数据中心 1.2. 创立数据表 2.创立随机查问事件2.1. 点击 事件核心 2.2. 创立 数据事件 3.创立关注列表展现触发器3.1. 选中 循环容器 3.2. 点击 查看面板 中的 触发器 3.3. 创立 触发器 3.4. 选中 按钮 3.5. 点击 查看面板 中的 触发器 3.6. 创立 触发器 4.绑定数据4.1. 选中 循环条目 4.2. 点击 查看面板 中的 数据绑定与设置 4.3. 配置 数据 这样就能够在小程序里实现一个随机关注列表了。

January 11, 2023 · 1 min · jiezi

关于微信小程序:如何制作QR扫描效果动画

成果展现: 前置筹备:待增加配置扫描线动画的页面具体步骤:制作QA扫描线为QA扫描线增加动画成果步骤合成:制作QA扫描线增加 容器 组件在右侧面板 款式 中 尺寸设置 设置 宽度 高度 数据在 显示设置 中增加 线性突变 为QA扫描线制作款式 为QA扫描线增加动画成果选中扫描线 容器 组件 在右侧面板 动画 中增加 自定义动画 并配置数据 官网链接:https://www.towify.com/#/

January 10, 2023 · 1 min · jiezi

关于微信小程序:如何动态实现搜索框下方展示历史搜索记录

通过应用数据中心的创立事件和API Hub中定义胜利的搜寻图片接口实现一个历史搜寻展现成果展现 前置筹备在 API Hub 中创立胜利的图片搜寻接口具体步骤创立数据表制作搜寻界面创立事件创立触发器绑定数据步骤合成创立数据表点击 数据中心创立 数据表 制作搜寻界面拖拽 组件切换器 到 根容器拖拽 容器 到 编辑区选中 组件切换器点击 查看面板 中的 数据绑定与款式设置关联内容 选中 组件素材拖拽 搜寻框 到 容器 拖拽 流式布局 到 容器 拖拽 循环容器 到 容器 拖拽 图片 到 流式布局 的 条目 拖拽 标签文本 到 循环容器 的 条目 创立事件点击 事件核心配置事件 创立触发器选中 组件切换器点击 查看面板 中的 触发器创立 触发器 选中 循环容器 点击 查看面板 中的 触发器 创立 触发器 选中 输入框点击 查看面板 中的 触发器创立 触发器 ...

January 10, 2023 · 1 min · jiezi

关于微信小程序:如何实现一个动态添加待办及完成功能

成果展现 前置筹备应用循环容器制作的待办列表应用输入框实现的输出待办工作应用按钮实现增加工作具体步骤创立数据表常见数据查问更新事件配置循环条目款式创立未实现待办的查问触发器创立点击单选框实现待办项触发器创立增加待办项触发器步骤合成1.创立数据表点击 数据中心创立数据表 常见数据查问更新事件点击 事件核心增加 数据事件 配置循环条目款式选中 循环条目点击 查看面板 中的 款式新增一个 款式款式状态 切换为 选中模式配置 款式 创立未实现待办的查问触发器选中 循环容器点击 查看面板 中的 触发器创立 触发器 选中 循环条目点击 查看面板 中的 数据绑定与设置绑定数据 创立点击单选框实现待办项触发器选中 循环条目点击 查看面板 中的 触发器创立 触发器 选中 单选框点击 查看面板 中的 触发器创立 触发器 创立增加待办项触发器选中 输入框点击 查看面板 中的 触发器创立 触发器 选中 按钮点击 查看面板 中的 触发器创立 触发器 官网链接:https://www.towify.com/#/

January 9, 2023 · 1 min · jiezi

关于微信小程序:如何使用搜索功能精确筛选数据

成果展现: 前置筹备:已搭建好,配少配置数据的搜寻详情页具体步骤:增加须要的组件增加须要查问的数据增加事件配置搜寻按钮和动静容器触发器步骤合成:增加须要的组件增加 标签文本增加 图标增加 动态数据容器增加 输入框 增加须要查问的数据点击上方面板 数据中心创立数据表,增加本人须要的数据内容 增加事件点击上方面板 事件核心增加 数据事件 并进行配置 配置搜寻按钮和动静容器触发器选中 动态数据容器 组件在右侧面板选中 触发器 增加接收数据触发器选中搜寻 图标 组件在右侧面板选中 触发器 增加搜寻触发器选中 循环条目 组件在右侧面板选中 数据绑定及设置 选中须要关联的数据 这样就能够应用搜寻性能准确筛选数据了。官网链接:https://www.towify.com/#/

January 9, 2023 · 1 min · jiezi

关于微信小程序:如何使用样式制作签到奖励页面

成果展现: 具体步骤:增加须要的组件配置默认选中款式配置触发器步骤合成:增加须要的组件增加 标签文本增加 容器增加 图片 配置默认选中款式在右侧面板上方 款式 中抉择 默认 款式 配置须要色彩在右侧面板上方 款式 中切换 选中 款式 配置须要色彩标签文本 配置办法雷同 配置触发器在右侧面板上方 触发器 中增加签到激活 触发器 并配置相干数据在右侧面板上方 触发器 中增加激活弹窗 触发器 并配置相干数据 这样就能够应用款式制作签到处分页面了。官网链接:https://www.towify.com/#/

January 4, 2023 · 1 min · jiezi

关于微信小程序:如何在页面中制作悬浮发布按钮弹窗

成果展现: 前置筹备:1.已搭建好,待增加悬浮层的页面 2.icon素材 具体步骤:(3)  1.增加悬浮层页面  2.配置悬浮层敞开触发器   3.配置首页公布icon触发器和动画 步骤合成:1.增加悬浮层页面 1.1点击左侧面板中的 界面 1.2增加 悬浮层 1.3增加 标签文本 组件 1.4增加 图标 组件 1.5在右上方面板 款式 中的 尺寸设置 填充色设置 配置须要的悬浮层款式 2.配置悬浮层敞开触发器 2.1选中敞开 图标 组件 2.2在右侧上方面板中的 触发器 增加敞开弹窗触发器 3.配置首页公布icon触发器和动画 3.1选中首页 界面 3.2选中公布 图标 组件 3.3在右侧上方面板中的 动画 增加 自定义动画 并进行相干数据配置 3.4在右侧上方面板中的 触发器 增加关上弹窗触发器,并进行相干数据配置 这样就能够在页面中制作悬浮公布按钮弹窗了。官网链接:https://www.towify.com/#/

January 4, 2023 · 1 min · jiezi

关于微信小程序:如何制作下拉刷新图片列表

成果展现 具体步骤创立数据表制作图片列表创立图片查问事件创立图片查问触发器步骤合成创立数据表点击 数据中心创立数据表 制作图片列表拖拽 流式布局列表 到 根容器拖拽 图片 到 条目中 创立图片查问事件点击 事件核心创立事件 创立图片查问触发器选中 流式布局列表点击 查看面板 中的 触发器创立触发器 选中 根容器点击 查看面板 中的 触发器创立触发器官网链接:https://www.towify.com

January 3, 2023 · 1 min · jiezi

关于微信小程序:如何实现动态投票计数功能

通过应用更新事件及激活性能,实现投票和勾销投票计数成果展现 前置筹备应用循环列表制作的投票选项具体步骤创立数据表制作投票前款式制作投票后款式创立投票数据展现相干触发器创立投票相干触发器步骤合成创立数据表点击 数据中心创立数据表 制作投票前款式选中 文本组件点击 查看面板 的 款式配置 款式 制作投票后款式选中 循环条目点击 查看面板 的 款式新增一个款式,款式状态 切换为 选中配置 款式 选中 文本组件点击 查看面板 的 款式新增一个款式,款式状态 切换为 选中配置 款式 选中 图片点击 查看面板 的 款式新增一个 款式,款式状态 切换为 选中配置 款式 创立投票数据展现相干触发器选中 循环容器点击 查看面板 中的 触发器创立触发器 创立投票相干触发器选中 图标点击 查看面板 的 款式新增一个款式,款式状态 切换为 选中配置 款式 官网链接:https://www.towify.com

January 3, 2023 · 1 min · jiezi

关于微信小程序:简单实现微信小程序支付php后端回调查询订单订单信息入库

本文解说如何开发微信小程序领取,蕴含小程序发动领取,后端对立下单,查问订单,订单回调,订单入库等操作。 流程微信小程序获取订单参数->向后端发动批准下单申请->获取订单参数->小程序调用Api进行发动领取->领取实现->发送回调->领取后果入库->查问订单领取状态。 后端代码getOpenid.php 须要配置的参数有 $appid、$secret、orderPrice,其中 $appid、$secret、orderPrice 是你小程序的两个参数,orderPrice 是订单金额,以元为单位。 <?php// 页面编码header("content-type:application/json");// 取得小程序传过来的CODE$code = trim($_GET['code']);// 小程序appid$appid = "这里填写你的";// 小程序appscret$secret = "这里填写你的";// 受权登录api接口$api = "https://api.weixin.qq.com/sns/jscode2session?appid=$appid&secret=$secret&js_code=$code&grant_type=authorization_code";// 发动申请$result = file_get_contents($api);// 获取openid$arr_result = json_decode($result, true);$openid = $arr_result["openid"];// 返回信息$result = array( 'code' => 200, 'msg' => '获取openid胜利', 'openid' => $openid, 'orderPrice' => 0.01 // 单位:元);// 输入JSONecho json_encode($result,JSON_UNESCAPED_UNICODE);?>creatOrder.php 须要配置的参数都在代码中有阐明。$appid、$mchid、$xlid、$data['notify_url']、$set_body、$price <?php// 页面编码header('Content-type:text/html; Charset=utf-8');ini_set('date.timezone','Asia/Shanghai');// 对立下单function wechartAddOrder($name,$ordernumber,$money,$openid,$timeStamp,$noncestr){ $url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi"; $urlarr = parse_url($url); // 须要配置以下参数 // 须要配置以下参数 // 须要配置以下参数 // 须要配置以下参数 // 须要配置以下参数 $appid = '填写你的小程序appid'; // appID $mchid = '填写你的微信领取商户号'; // 商户ID $xlid = '填写你的秘钥序列号'; // 秘钥序列号 可在这个网址中查问 https://myssl.com/cert_decode.html $data = array(); $time = $timeStamp; $data['appid'] = $appid; $data['mchid'] = $mchid; $data['description'] = $name; // 商品形容 $data['out_trade_no'] = $ordernumber; // 订单编号 // 异步订单回调线上地址 // 就是notify.php这个文件的线上URL // 例如你的notify.php所在服务器的地位是wwwroot/xcxpay/notify.php // 你的域名是https://www.qq.com // 那么应该依照这个格局填写URL:https://www.qq.com/xcxpay/notify.php $data['notify_url'] = "填写notify.php这个文件的线上URL"; $data['amount']['total'] = intval($money * 1); // 金额(单位:分) $data['payer']['openid'] = $openid; // 用户openID $data = json_encode($data); $key = getSign($data,$urlarr['path'],$noncestr,$time); // 签名 $token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"',$mchid,$xlid,$noncestr,$time,$key); // 头部信息 $header = array( 'Content-Type:'.'application/json; charset=UTF-8', 'Accept:application/json', 'User-Agent:*/*', 'Authorization: WECHATPAY2-SHA256-RSA2048 '.$token ); $ret = curl_post_https($url,$data,$header); $ret = ltrim($ret,'{"prepay_id":"'); $ret = rtrim($ret,'}"'); // 微信领取(小程序)签名 $str = getWechartSign($appid,$timeStamp,$noncestr,'prepay_id='.$ret); // 需返回的一些预领取参数 $arr = array( 'appid' => $appid, 'timestamp' => $timeStamp, 'package' => 'prepay_id='.$ret, 'paySign' => $str, 'noncestr' => $noncestr, 'orderNum' => $ordernumber, 'orderPrice' => intval($money * 1) // 可用number_format转换金额 ); exit(json_encode($arr));}// 微信领取签名function getSign($data=array(),$url,$randstr,$time){ $str = "POST"."\n".$url."\n".$time."\n".$randstr."\n".$data."\n"; $key = file_get_contents('apiclient_key.pem');// 在商户平台下载的秘钥 $str = getSha256WithRSA($str,$key); return $str;} // 调起领取的签名function getWechartSign($appid,$timeStamp,$noncestr,$prepay_id){ $str = $appid."\n".$timeStamp."\n".$noncestr."\n".$prepay_id."\n"; $key = file_get_contents('apiclient_key.pem'); $str = getSha256WithRSA($str,$key); return $str;} function getSha256WithRSA($content, $privateKey){ $binary_signature = ""; $algo = "SHA256"; openssl_sign($content, $binary_signature, $privateKey, $algo); $sign = base64_encode($binary_signature); return $sign;} /* PHP CURL HTTPS POST */function curl_post_https($url,$data,$header){ // 模仿提交数据函数 $curl = curl_init(); // 启动一个CURL会话 curl_setopt($curl, CURLOPT_URL, $url); // 要拜访的地址 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书起源的查看 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); // 从证书中查看SSL加密算法是否存在 curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模仿用户应用的浏览器 curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 应用主动跳转 curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 主动设置Referer curl_setopt($curl, CURLOPT_POST, 1); // 发送一个惯例的Post申请 curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包 curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限度避免死循环 curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的模式返回 curl_setopt($curl, CURLOPT_HTTPHEADER, $header); $tmpInfo = curl_exec($curl); // 执行操作 if (curl_errno($curl)) { echo 'Errno'.curl_error($curl);//捕抓异样 } curl_close($curl); // 敞开CURL会话 return $tmpInfo; // 返回数据,json格局}// 生成noncestrfunction creatnoncestr($length){ $str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890'; $randStr = str_shuffle($str); $rands= substr($randStr,0,$length); return $rands;}// 商品名称$set_body = '小程序领取';// 领取金额(单位:分)// 还须要去getOpenid.php外面批改这个价格才会在小程序显示精确的价格$price = 1;// 商户自定义订单号$out_trade_no = date('Ymd').time();// 工夫戳$timeStamp = time();// 领取用户$openid = trim($_GET['openid']);// 随机字符串$noncestr = creatnoncestr(8); // 创立订单wechartAddOrder($set_body,$out_trade_no,$price,$openid,$timeStamp,$noncestr);?>notify.php这个文件是领取回调。 ...

January 2, 2023 · 5 min · jiezi

关于微信小程序:如何实现点击图片进行预览

成果展现 具体步骤创立图片内容列表创立图片预览触发器步骤合成创立图片内容列表点击界面点击流式布局列表界面点击确认创立模版界面 创立图片预览触发器选中图片点击查看面板中的触发器创立点击预览触发器 这样就能实现点击图片进行预览了。官网链接:https://www.towify.com/#/

December 30, 2022 · 1 min · jiezi

关于微信小程序:如何在小程序内实现界面快速置顶功能

通过应用触发器中滚动到指定项实现界面疾速置顶。 成果展现 前置筹备应用 循环容器 制作好的内容列表置顶图标数据表具体步骤1.创立列表项滚动触发器 2.创立点击置顶触发器 步骤合成1.创立列表项滚动触发器1.1. 选中 循环容器 1.2. 点击 查看面板 中的 触发器 1.3. 创立 触发器 2.创立点击置顶触发器2.1. 选中 图标 2.2. 点击 查看面板 中的 触发器 2.3. 创立 触发器 这样就能够在小程序内实现界面疾速置顶性能了。官网链接:https://www.towify.com/#/

December 30, 2022 · 1 min · jiezi

关于微信小程序:如何使用存在查询实现邀请码兑换

成果展现 具体步骤创立数据表制作邀请码界面创立事件创立邀请码兑换相干触发器步骤合成创立数据表点击数据中心创立数据表格 制作邀请码界面拖拽一个标签文本到根容器选中标签文本点击查看面板中的款式配置款式 拖拽一个标签文本到根容器选中标签文本点击查看面板中的数据绑定与设置配置内容类型 拖拽一个按钮到根容器选中按钮点击查看面板中的款式配置款式 点击查看面板中的数据绑定与设置设置自定义内容 创立事件点击事件核心创立数据事件 创立邀请码兑换相干触发器选中按钮点击查看面板中的触发器创立触发器 这样就能够应用存在查问实现邀请码兑换了。官网链接:https://www.towify.com/#/

December 29, 2022 · 1 min · jiezi

关于微信小程序:如何在小程序中实现双击弹出提示并刷新图片列表的功能

通过应用触发器中的提醒触发行为及查问事件中的随机排序实现双击弹出提醒并刷新图片列表的性能 成果展现 前置筹备1.图片素材 2.已创立的图片数据表 具体步骤1.创立查问事件 2.创立图片内容展现触发器 3.绑定数据 4.创立点击刷新相干触发器 步骤合成1.创立查问事件1.1. 点击 事件核心 1.2. 增加 数据事件 2.创立图片内容展现触发器2.1. 选中 流式布局列表 2.2. 点击 查看面板 中的 触发器 2.3. 创立 触发器 3.绑定数据3.1. 选中 流式布局组件 的 循环条目 3.2. 点击 查看面板 中的 数据绑定与设置 3.3. 绑定数据 4.创立点击刷新相干触发器4.1. 选中 标签文本 4.2. 点击 查看面板 中的 触发器 4.3. 创立 触发器 这样就能够在小程序中实现双击弹出提醒并刷新图片列表的性能了。官网链接:https://www.towify.com/#/

December 29, 2022 · 1 min · jiezi

关于微信小程序:如何使用网格布局和流式列表实现自适应动态列表

成果展现 具体步骤创立数据表创立数据事件配置网格设置配置组件自适应网格创立图片预览触发器步骤合成创立数据表点击 数据中心创立数据表 创立数据事件点击 事件核心创立 数据事件 配置网格设置点击 流式布局列表 的 列表条目选中 列表条目点击 查看面板 中的 款式配置 网格设置将组件搁置于 网格 中 配置组件自适应网格选中 图片组件点击 查看面板 中的 款式配置款式 选中 标签文本组件点击 查看面板 中的 款式配置款式 创立图片预览触发器选中图片组件点击查看面板中的触发器创立触发器

December 27, 2022 · 1 min · jiezi

关于微信小程序:如何自定义小程序页面分享

步骤合成界面设置选中页面点击页面右侧图标点击界面设置 设置值 这样就能够实现自定义小程序页面分享了。官网链接:https://www.towify.com/

December 27, 2022 · 1 min · jiezi

关于微信小程序:如何通过Fit实现自适应内容

Fit 属性可能使容器的高度自适应容器内的内容成果展现 前置筹备1.应用流式布局及循环容器实现的内容列表具体步骤1.设置Fit高度步骤合成1.设置Fit高度官网链接:https://www.towify.com/#/

December 26, 2022 · 1 min · jiezi

关于微信小程序:如何在素材中心中下载字体并安装

前置筹备:文本组件具体步骤:进入 字体素材核心下载安装字体利用字体步骤合成:进入字体素材核心选中文本组件点击查看器面板的款式抉择字体设置点击字体素材核心 下载安装字体进入字体素材页面点击 Install 装置 利用字体选中文本组件进入我的字体利用字体官网链接:https://www.towify.com/#/

December 26, 2022 · 1 min · jiezi

关于微信小程序:如何使用-Towify-在小程序中实现输入文字并上传显示

成果展现: 前置筹备:须要增加文本的图片素材用于触发上传文字显示的 按钮组件(下文简称“ 触发组件 ”)具体步骤(4):增加 输入框组件增加 文本组件创立传递值 触发器创立执行其余 触发器步骤合成:增加输入框组件增加 输入框组件配置 输入框组件 增加文本组件增加 文本组件革除默认文本内容关上 承受动静数据项 创立传递值触发器选中 输入框组件创立设置值 触发器配置 触发器 创立执行其余触发器选中 触发组件创立执行其余 触发器配置 触发器 这样就能够在小程序中实现输出文字并上传显示了。官网链接:https://www.towify.com/#/

December 23, 2022 · 1 min · jiezi

关于微信小程序:如何创建一个数据选择器

成果展现: 前置筹备:须要承受数据的 文本组件具体步骤:创立 数据选择器创立关上数据选择器 触发器创立传递值 触发器步骤合成:创立数据选择器创立 数据选择器配置 数据选择器 款式选中 数据选择器 面板配置 数据选择器 面板 创立关上数据选择器触发器选中 数据选择器创立 触发器配置 触发器 创立传递值触发器选中 触发器创立 触发器配置 触发器官网链接:https://www.towify.com/#/

December 23, 2022 · 1 min · jiezi

关于微信小程序:如何使用企业账户进行协作

通过创立企业账户、增加成员并实现权限调配之后,不同的成员即可对同一个企业账户下的我的项目进行编辑,从而实现多端合作。具体步骤:创立企业账户切换至企业账户增加企业账户成员通过企业账户登录编辑器为企业账户成员调配我的项目权限步骤合成:创立企业账户登录官方网站进入企业服务页面填写企业信息并提交 切换至企业账户点击头像,通过菜单项进入账户切换页面抉择企业账户 增加企业账户成员 点击头像,通过菜单项进入账户信息页面通过左侧菜单切换至企业成员页面在搜寻框中输出成员用户名或用户 id ,点击搜寻后果增加用户为成员 通过企业账户登录编辑器登录编辑器后,点击抉择企业账户登录PS: 企业账户下,只有管理员具备创立我的项目权限 为企业账户成员调配我的项目权限点击头像,通过菜单项进入看板,点击须要调配权限的我的项目,进入我的项目详情页面过左侧菜单切换至权限设置页面抉择企业账户成员关上权限官网链接:https://www.towify.com/#/

December 21, 2022 · 1 min · jiezi

关于微信小程序:如何使用滑块实现切换图片功能

成果展现: 前置筹备:链接好四张图片的 组件切换器具体步骤:增加 滑块 组件创立 组件切换器 触发器创立执行其余 触发器创立值扭转 触发器步骤合成:增加滑块组件增加 滑块 组件配置滑块参数 创立组件切换器触发器选中组件切换器创立切换头像1 触发器配置 触发器同样的形式配置其余 触发器 选中 滑块 组件创立执行其余 触发器配置 触发器同样的形式配置其余 触发器 选中 滑块 组件创立值扭转 触发器配置 触发器官网链接:https://www.towify.com/#/

December 21, 2022 · 1 min · jiezi

关于微信小程序:如何利用浮动容器制作悬浮下拉菜单

成果展现: 前置筹备:一个用于点击下拉的菜单按钮四个菜单项图片素材四个菜单项文本素材创立点击执行其余 触发器具体步骤:制作悬浮下拉菜单创立关上 浮动容器 触发器创立敞开 浮动容器 触发器创立设置值 触发器步骤合成:制作悬浮下拉菜单增加 浮动容器增加 反复容器调整 反复容器 布局增加菜单项 容器调整菜单项布局增加图片素材至菜单项 容器增加文本素材至菜单项 容器 创立关上浮动容器触发器选中菜单按钮组件创立 触发器配置 触发器 创立敞开浮动容器触发器选中 浮动容器创立 触发器配置 触发器 创立设置值触发器开启按钮文本的 承受动态数据选中菜单项的 文本组件创立 触发器配置 触发器菜单项中的其余 文本组件 配置雷同的 触发器 创立点击执行其余触发器选中菜单项容器创立 触发器配置 触发器其余菜单项 容器 配置雷同的 触发器 官网链接:https://www.towify.com/#/

December 20, 2022 · 1 min · jiezi

关于微信小程序:如何使用-Towify-在小程序里实现一个广告轮播图

在很多商业场景下,某些 Banner 位须要用到轮播图来展现广告,进而使界面的内容更加丰盛,具备可互动性。上面就如何实现一个广告轮播图来进行具体操作。 成果展现: 前置筹备:三张商品图片商品介绍文本商品价格文本具体步骤(5):增加 轮播图组件创立数据表创立 事件创立轮播图 触发器绑定数据步骤合成:增加轮播图组件增加 轮播图组件配置 轮播图组件 款式增加 图片 和 文本组件 创立数据表关上 数据中心创立 数据表在 数据表 中增加图片和文本 创立事件关上 事件核心创立查问 事件 创立轮播图触发器选中 轮播图组件点击查看器 面板的 触发器 **图标创立 触发器配置 触发器 绑定数据选中 轮播图条目点击 查看器 面板的 数据绑定及设置 图标绑定数据 这样就能够在小程序里实现一个广告轮播图了。官网链接:https://www.towify.com/#/

December 20, 2022 · 1 min · jiezi

关于微信小程序:如何在小程序中完成支付进件

实现企业认证1.1. 创立试用小程序关上一个待发布的我的项目。点击顶部导航栏的 公布。手机扫码生成试用小程序。点击二维码底部的 公布利用。编辑切换为居中增加图片正文,不超过 140 字(可选)1.2. 应用企业主体转正小程序抉择转正类型为 企业认证。编辑切换为居中增加图片正文,不超过 140 字(可选)公司代码。公司名称。法人姓名。法人身份证。法人微信号。点击确认,期待管理员受权.企业法人在微信端实现人脸识别。我的项目管理员在微信端确认。编辑切换为居中增加图片正文,不超过 140 字(可选)编辑切换为居中增加图片正文,不超过 140 字(可选)受权胜利后,将显示如下页面编辑切换为居中增加图片正文,不超过 140 字(可选) 实现微信商户进件2.1 企业信息 再次进入发布页面后,将显示进件信息。上传 营业执照。上传 法人身份证照片正反面。输出 商户名缩写。编辑切换为居中增加图片正文,不超过 140 字(可选)2.2. 结算信息抉择 结算规定。结算账户名。结算银行。开户城市。输出 账户。编辑切换为居中增加图片正文,不超过 140 字(可选)2.3. 欠缺管理员信息 法人和代理人任选其一即可。 法人信息如下:编辑切换为居中增加图片正文,不超过 140 字(可选) 代理人信息如下:编辑切换为居中增加图片正文,不超过 140 字(可选)以上流程欠缺胜利后,期待微信官网审核。审核通过后,依照微信商家助手发送的入驻告诉,管理员实现商家入驻即可。编辑切换为居中增加图片正文,不超过 140 字(可选)在界面实现领取配置3.1. 创立数据表点击 数据中心。创立 自定义数据表,表名称为商品表。增加一个 字段类型 为 货币 的字段,towify 将主动创立订单表,如下图。编辑切换为居中增加图片正文,不超过 140 字(可选)编辑切换为居中增加图片正文,不超过 140 字(可选)3.2. 创立事件点击 事件核心。增加一个 算法事件:求和事件。编辑切换为居中增加图片正文,不超过 140 字(可选)增加一个 办法事件:创立订单。编辑切换为居中增加图片正文,不超过 140 字(可选)增加一个 自定义事件:查问商品。编辑切换为居中增加图片正文,不超过 140 字(可选)3.3. 配置触发器选中 循环容器 的 列表条目。点击 查看面板 中的 触发器。创立触发器:激活或非激活,用于切换以后列表条目标款式状态。编辑切换为居中增加图片正文,不超过 140 字(可选)选中 标签文本 组件。点击 查看面板 中的 触发器。创立触发器:求和,用户购物车中曾经选中的商品的总价计算。编辑切换为居中增加图片正文,不超过 140 字(可选)选中 单选框组件。点击 查看面板 中的 触发器。创立触发器:退出或者勾销购物车。编辑切换为居中增加图片正文,不超过 140 字(可选)选中 按钮 组件。点击 查看面板 中的 触发器。创立触发器:领取。编辑切换为居中增加图片正文,不超过 140 字(可选)手机端实现预览点击顶部导航栏的 公布。手机扫码预览小程序。编辑切换为居中增加图片正文,不超过 140 字(可选)在手机端点击领取,即可间接调用原生的微信领取性能。编辑切换为居中增加图片正文,不超过 140 字(可选)

December 19, 2022 · 1 min · jiezi

关于微信小程序:版本更新-Towify-V1240-有哪些实用新功能汇总来了

前言随着用户们应用Towify开发的我的项目越来越多,操作内容也是越来越简单,同时也就发现了更多的问题,所以这次降级,就是为了用户们更好的体验!Towify 1.24.0版本正式上线了!那新性能里是否有你所期待的呢?一起往下看看吧!重大更新二维码扫描二维码扫描性能,事件核心反对配置二维码扫描事件,可能唤起微信扫一扫性能,并传递值到界面。编辑器单值事件重构,对立了事件核心配置的单值事件,如 查问数量,扫码,求和等事件 与 数据库和 API 事件中一样的应用形式。 领取调优,反对用户将月套餐续费降级为年套餐。同时当用户已满足最高级别套餐时,该领取界面将显示扩大界面。 键盘自动弹出,输入框、文本框及公式输入框反对主动聚焦,键盘会自动弹出。播放控件,在视频组件新增了播放控件(播放/暂停按钮、播放进度条)的配置,用户可灵便抉择配置该控件。 图片切图配置,图片反对依照像素值和屏幕倍数切图。结语以上就是本次 Towify 1.24.0版本更新的所有内容啦!如果大家在应用过程中,有任何意见和反馈能够在软件内的 <技术支持> 板块寻找到咱们的客服人员,退出咱们的社区。

December 19, 2022 · 1 min · jiezi

关于微信小程序:如何发布组件模板

前置筹备:实现设计制作的 组件模板具体步骤:提交模板(编辑器内提交后能够在本账号下进行复用)补充模板信息提交审核进行上架步骤合成:编辑器公布点击 提交模板 按钮 抉择要公布的组件(当模板内有多个同级组件存在时) 设置模板根本信息 补充模板信息登录官方网站 进入 Creator Center抉择模板补充模板信息官网链接:https://www.towify.com/#/

December 19, 2022 · 1 min · jiezi

关于微信小程序:资源中心里的图片裁切如何使用

图片是构建利用时的罕用资源,过大的图片尺寸会耗费更多的流量,加载速度也会很慢,这带来了较差的用户体验。因而在 资源核心 中提供了图片尺寸裁切的性能。 具体步骤:关上 资源核心裁切图片点击图片裁切图片利用图片步骤合成:关上资源核心 裁切图片点击图片裁切图片 利用图片选中图片所在的界面选中 图片组件点击 查看器 面板的 数据绑定及设置 图标点击抉择图片切换至我的文件点击图片确认 官网链接:https://www.towify.com/#/

December 19, 2022 · 1 min · jiezi

关于微信小程序:创建好的小程序如何正式发布

前置筹备:一个待发布的小程序。具体步骤:Editor 中点击 Publish创立新的试用小程序已有试用小程序轮转绑定进入 User CMS 实现认证集体认证企业认证欠缺小程序信息提交审核公布上线Editor 中点击 Publish 创立新的试用小程序 已有试用小程序则轮转绑定 进入 User CMS 实现认证 集体认证 企业认证 欠缺小程序信息 提交审核(审核需1-2日) 公布上线 这样创立好的小程序就能够正式公布了。官网链接:https://www.towify.com/#/

December 16, 2022 · 1 min · jiezi

关于微信小程序:如何使用-Towify-在小程序中创建关联表

前置筹备:一张须要被关联的表格 具体步骤(5):增加关联字段抉择 被关联表双击关联字段格抉择被关联数据关联胜利步骤合成:增加关联字段 抉择被关联表 双击关联字段格 抉择被关联数据 关联胜利 这样就能够在小程序中创立关联表了。官网链接:https://www.towify.com/#/

December 16, 2022 · 1 min · jiezi

关于微信小程序:如何实现发送评论时总数自动加一

应用事件核心,数据操作中的数量查问获取总数,实现总数的实时显 成果展现 前置筹备应用循环容器制作的评论列表评论数据表,蕴含一个评论字段已实现发送评论,实时显示评论具体步骤创立获取总数事件制作数量显示框创立获取数量触发器步骤合成创立获取总数事件点击 事件核心点击加号,增加一个数据事件创立事件 制作数量显示框拖拽 标签文本 到 根容器选中 标签文本点击 查看面板 中的 款式配置款式 创立获取数量触发器选中 标签文本点击 查看面板 中的 触发器创立 触发器 选中 按钮抉择一个 指标触发器官网链接:https://www.towify.com/#/

December 15, 2022 · 1 min · jiezi

关于微信小程序:如何使用API-Hub-实现一个图片列表

具体步骤创立API配置 API 事件创立触发器步骤合成创立API分页,依据 API 返回的数据中的总数定义 Key如此案例返回的数据中,total代表返回的总数、per_page代表返回的数量、page Index代表第几页 配置 API 事件在事件核心,抉择该事件。 创立触发器选中流式布局点击 查看面板中的触发器创立触发器,关上分页开关 创立滚动时持续分页加载数据。 这样就能够用API Hub实现一个图片列表了。官网链接:https://www.towify.com/#/

December 15, 2022 · 1 min · jiezi

关于微信小程序:如何用弹出对话框实现登录页非空提示

应用触发器中的弹出对话框通过创立多个触发器,实现多个输入框的不同值的非空提醒。 成果展现 具体步骤1. 制作一个题目 2. 制作输入框 3. 制作“获取验证码”按钮 4. 制作“登陆”按钮 5. 创立按钮触发器 步骤合成1. 制作一个题目1.1. 拖拽 标签文本 到 动态数据容器 中 1.2. 点击 查看器 面板中的 款式 1.3. 配置 标签文本 款式 2. 制作输入框2.1. 拖拽 输入框 到 动态数据容器 中 2.2. 点击 查看面板 中的 款式 2.3. 选中 “请输出手机号” 输入框 2.4. 配置 “请输出手机号” 输入框 款式 2.5. 点击 查看面板 中的 数据绑定与设置 2.6. 填写 占位符 2.7. 选中 “验证码” 输入框 2.8. 配置 “验证码” 输入框 款式 2.9. 点击 查看面板 中的 数据绑定与设置 ...

December 14, 2022 · 1 min · jiezi

关于微信小程序:如何实现复制文本到剪贴板

成果展现: 前置筹备:增加触发复制的按钮 增加被复制的文本 步骤合成:创立胜利提醒触发器选中复制文本按钮点击查看器标签点击触发器标签创立触发器 配置胜利提醒触发器触发机会-无触发行为-弹出对话框抉择触发对话框动作-关上对话框题目内容-复制胜利! 创立复制文本触发器选中复制文本按钮点击查看器标签点击触发器标签创立触发器 配置复制文本触发器触发机会-点击触发行为-复制文本抉择组件-被复制文本题目指标触发器-胜利提醒 这样就能够实现复制文本到剪贴板了。官网链接:https://www.towify.com/#/

December 1, 2022 · 1 min · jiezi

关于微信小程序:如何实现带有预览效果的图片上传

成果展现: 前置筹备:增加用于展现预览图的图片组件(下文简称“预览图组件”) 增加文件上传组件 增加上传按钮 步骤合成:创立上传图片数据表:点击数据中心图标,进入数据中心点击创立数据表按钮增加类型为图片的字段(下文简称“图片字段”)创立上传图片 数据表(下文简称“图片表”) 创立上传图片事件:点击事件核心图标,进入事件核心点击创立事件按钮,创立自定义事件 配置上传图片事件:数据操作-创立抉择数据表-图片表抉择数据名称-图片字段-关联组件接口类型-胜利 创立上传胜利提醒触发器:选中上传按钮点击开展查看器面板点击开展 触发器面板点击点击 ➕ 号按钮创立触发器配置触发器 创立上传图片触发器:选中上传按钮点击开展 查看器面板点击开展触发器面板点击点击 ➕ 号按钮创立触发器配置触发器 预览图组件开启容许被设置动态数据:选中预览图组件点击开展查看器面板点击开展数据绑定及设置面板开启容许被设置动态数据开关 创立设置值触发器:选中文件上传组件点击开展查看器面板点击开展触发器面板点击点击 ➕ 号按钮创立触发器配置触发器 创立值扭转时监听触发器:选中文件上传组件点击开展查看器面板点击开展触发器面板点击点击 ➕ 号按钮创立触发器配置触发器 这样就能够实现带有预览成果的图片上传了。官网链接:https://www.towify.com/#/

December 1, 2022 · 1 min · jiezi

关于微信小程序:如何使用-Towify-在小程序里实现使用菜单控制器控制两个组件切换

在某些应用场景下,你须要在菜单选项栏进行组件切换,例如底部导航栏、老手疏导等场景。这时你能够应用 菜单控制器 和 组件切换器 配合来实现这一目标。 成果展现: 前置筹备:一个链接好两个组件的 组件切换器(下文简称“ 组件切换器 ”)具体步骤:增加 菜单控制器配置 组件切换器触发器配置 菜单控制器 选项一 触发器配置 菜单控制器 选项二 触发器步骤合成:增加菜单控制器选中 菜单控制器配置 菜单控制器配置 菜单控制器 款式 配置组件切换器触发器选中 组件切换器创立切换 触发器配置 触发器同样形式配置另一个 触发器 配置菜单控制器选项一触发器选中第一个 Tab item 组件创立 触发器配置 触发器 配置菜单控制器选项二触发器选中第二个 Tab item 组件创立 触发器配置 触发器 这样就就能够实现应用菜单控制器管制两个组件切换的性能了。官网链接:https://www.towify.com/#/

November 30, 2022 · 1 min · jiezi

关于微信小程序:如何使用-Towify-在小程序中配置获取手机验证码登陆功能

前置筹备:须要发送验证码的手机号具体步骤:创立 用户表增加 输入框组件增加触发 按钮创立 发送手机验证码事件创立 手机登陆事件配置获取验证码按钮 触发器配置登陆按钮 触发器步骤合成:创立用户表关上 数据中心创立 用户表 增加输入框组件增加“请输出手机号码” 输入框组件增加“输出验证码“ 输入框组件配置 输入框组件 自定义数据 增加触发按钮增加获取验证码 按钮组件增加登陆 按钮组件配置 按钮组件 创立发送手机验证码事件关上 事件核心点击 自定义事件创立 发送短信验证码事件 创立手机登录事件点击 手机登陆事件配置 手机登陆事件 配置获取验证码按钮触发器选中获取验证码 按钮创立发送验证码 触发器(发送提醒对话框需额定增加)配置 触发器 配置登陆按钮触发器选中登陆 按钮创立登陆 触发器(数据事件响应设置中须要额定各自配置一个胜利提醒和失败提醒的对话框)配置 触发器 这样就能够在小程序中配置“获取手机验证码登陆”的性能了。官网链接:https://www.towify.com/#/

November 29, 2022 · 1 min · jiezi

关于微信小程序:在使用-Towify-制作微信小程序时如何获取微信用户信息

在许多利用场景下,为了便于在小程序端更具个性化地服务用户,须要获取微信用户信息,这个时候须要先 配置微信用户登录 ,而后在此基础上再获取用户信息。 成果展现: 前置筹备:配置微信登陆一个点击触发获取用户信息的 组件(下文简称“ 触发组件 ”)具体步骤:创立 申请微信用户信息事件创立获取用户信息 触发器步骤合成:创立申请微信用户信息事件关上 事件核心点击 +点击 申请微信用户信息创立 申请微信用户信息事件(默认,不须要批改事件设置) 创立获取用户信息触发器选中 触发组件点击 查看器 面板的 触发器 图标创立获取用户信息 触发器配置获取用户信息 触发器 这样就能够配置获取用户信息了。官网链接:https://www.towify.com/#/

November 28, 2022 · 1 min · jiezi

关于微信小程序:在Towify使用时如何设置回退到上一个界面

设计交互时,须要跳转到下一个界面 ,也须要能从下一个界面回退到上一个界面 。这个时候就须要先实现 界面的跳转,再在跳转后的界面配置触发器,回退到上一个界面。 成果展现: 前置筹备:一个跳转前的 界面(下文简称“ 界面A”)一个跳转后的 界面(下文简称“ 界面B”)一个你所须要跳转界面的 组件(下文简称“ 组件A”)一个在跳转后界面你所须要实现回退界面的 组件(下文简称“ 组件B”)步骤合成:创立跳转触发器点击 界面A选中 组件A点击 查看器面板的 触发器图标增加 触发器 配置跳转触发器 创立回退触发器点击 界面B选中 组件B点击 查看器面板的 触发器图标增加 触发器 配置回退触发器选中图标组件点击查看面板中的触发器创立触发器官网链接:https://www.towify.com/#/

November 25, 2022 · 1 min · jiezi

关于微信小程序:在Towify中如何配置-3D-翻转动画

成果展现: 前置筹备:筹备须要执行翻转动画的卡片(下文简称“翻转卡片”)步骤合成:创立自定义动画选中翻转卡片点击 + 按钮增加 自定义动画 配置动画成果选中图片组件点击查看面板中的动画面板配置动画官网链接:https://www.towify.com/#/

November 24, 2022 · 1 min · jiezi

关于微信小程序:使用Towify时如何实现夜间模式和日间模式的自由切换

通过触发器中的执行其它触发器动态显示夜间模式和日光模式图标的显示和暗藏,同时应用组件切换器管制不同组件之间的切换 成果展现 具体步骤制作按钮切换模式制作切换图标创立开关切换触发器创立图标显示暗藏触发器创立日光模式和夜间模式的触发器制作夜间模式和日光模式页面设置组件切换器的链接内容步骤合成制作按钮切换模式拖拽 开关 到 根容器选中 开关点击 查看面板 中的 数据绑定与设置抉择 默认激活模式点击 查看面板 中的 款式配置款式配置款式实现后,敞开 默认激活模式 制作切换图标拖拽 图标 到 根容器 中点击 查看面板 中的 数据绑定与设置抉择太阳图标月亮图标的操作雷同 创立开关切换触发器选中 开关点击 查看面板 中的 触发器创立 触发器 创立图标显示暗藏触发器选中 图标点击 查看面板 中的 触发器创立 触发器月亮图标的相干触发器,操作逻辑雷同 将月亮图标 拖到 太阳图标上 创立日光模式和夜间模式的触发器拖拽 容器 到 根容器 中选中 容器点击 查看面板 中的 款式配置款式 新增一个 款式点击 选中配置 款式 拖拽 标签文本 到 款式选中 标签文本点击 查看面板 中的 款式配置字体 款式 新增一个 款式配置 款式 ...

November 23, 2022 · 1 min · jiezi

关于微信小程序:Towify-又双叒叕上新啦简直不要太实用

此次 Towify 更新并上线了五大新性能,让 Towify 的操作更加可视化,协同单干更加便捷化,用户体验也失去进步。 新性能一:独立创立及挂载 Data Driver / API Driver 独立创立及挂载此次更新的版本将 Data Driver / API Driver 从我的项目中独立进去,使其不用依附于我的项目而存在。用户能够独自创立一个 Data Driver / API Driver ,并能够将其利用到多个不同的我的项目中,且我的项目与 Data Driver / API Driver 二者互相独立,互不影响,使得用户的可操作空间与容错率都大大晋升。 Data Driver / API Driver Transfer用户在创立了独立的 Data Driver / API Driver 后,可将其转移分享给其余用户。但须要留神的是, Data Driver / API Driver 在转移过程中不会被复制,即被转移后的 Data Driver / API Driver 只存在于被分享用户,原用户将不再享有此 Data Driver / API Driver 的编辑应用权限。 Data Driver / API Driver Copy Project如果用户想要在与其余用户分享独立的 Data Driver / API Driver 的同时依然领有此 Data Driver / API Driver 的编辑应用权限,能够尝试应用 Data Driver / API Driver Copy Project,在传输过程中对 Data Driver / API Driver 进行复制,使得单方都领有此 Data Driver / API Driver 的编辑权限,更适宜团队办公。 ...

November 22, 2022 · 1 min · jiezi

关于微信小程序:在使用Towify制作微信小程序时如何配置打开对话框

许多业务场景下须要弹出 对话框 让用户对操作进行确认或勾销,通过 触发器 中 对话框 的配置就能够满足这种需要场景。 成果展现: 前置筹备:一个须要触发关上 对话框 的组件(下文简称“ 触发组件 ”)具体步骤:创立 触发器配置 触发器步骤合成:创立触发器选中跳转前的 界面选中 触发组件点击右侧 查看器 面板的 触发器 图标创立 触发器 配置触发器触发机会-点击触发行为-弹出 对话框触发对话框动作-关上 对话框配置 对话框 内容配置 Cancel 和 Confirm 按钮 这样就能够在小程序里配置对话框了。官网链接:https://www.towify.com/#/

November 21, 2022 · 1 min · jiezi

关于微信小程序:在使用Towify制作小程序时如何配置点击图标播放暂停视频

你须要在视频组件上创立 激活/非激活 两种状态 触发器 以对应播放/暂停两种状态,再通过播放/暂停图标上的点击触发器呼叫 激活/非激活 的状态,以实现视频播放暂停的性能。 成果展现: 前置筹备:用于播放的的视频文件(目前 Towify 反对视频的格局为ogv、mp4、m4v、webm、mov、3gp)增加视频组件选中 视频组件点击 上传视频 视频组件配置激活触发器选中 视频组件点击右侧 查看器 面板的 触发器 图标创立 激活触发器配置 激活触发器 视频组件配置勾销激活触发器创立 勾销激活触发器配置 勾销激活触发器 Play 图标配置执行激活触发器的触发器选中视频组件下的 Paly 图标组件点击右侧 查看器 面板的触发器图标增加执行 激活触发器 的 触发器配置 触发器 Pause 图标配置执行勾销激活触发器的触发器选中视频组件下的 Pause 图标组件点击右侧 查看器 面板的触发器图标创立执行 勾销激活触发器 的 触发器配置 触发器 这样就能够配置点击图标播放/暂停视频了。官网链接:https://www.towify.com/#/

November 17, 2022 · 1 min · jiezi

关于微信小程序:如何配置微信登录

如果你不心愿用户以游客的模式应用小程序,就须要在应用 Towify 设计小程序时配置微信登陆,通过“用户表 — 事件 — 触发器”来实现微信用户登陆。 成果展现: 具体步骤:创立用户表创立微信登陆事件表创立登录胜利提醒触发器创立微信登陆触发器 步骤合成:创立用户表1.1 关上数据中心1.2 创立用户表创立微信登陆事件2.1 关上事件核心2.2 点击 +2.3 点击微信登陆事件2.4 创立微信登陆事件(默认,不须要批改事件设置)创立登录胜利提醒触发器3.1 选中须要点击登陆的组件3.2 点击 查看器面板的触发器图标3.3 创立登录胜利提醒触发器3.4 配置登录胜利提醒触发器创立微信登陆触发器4.1 创立微信登陆触发器4.2 配置微信登陆触发器这样就能够在小程序里实现配置微信登陆了! Towify官网:https://www.towify.com/#/

November 9, 2022 · 1 min · jiezi

关于微信小程序:如何使用组件切换器配置点赞功能

如果须要实现某个组件切换类的交互体验,例如配置“点赞”性能时,能够应用 组件切换器 实现这一目标。成果展现: 前置筹备:“点赞” 图标组件 (下文简称“ 组件A ”)“勾销点赞” 图标组件 (下文简称“ 组件B ”)具体步骤(4):增加 组件切换器组件切换器 链接组件A和组件B组件切换器 配置“点赞” 触发器组件切换器 配置“勾销点赞” 触发器步骤合成:增加组件切换器增加 组件切换器选中 组件切换器配置 组件切换器 款式 组件切换器链接组件A和组件B选中 组件切换器点击 链接 ,生成链接线组件切换器 和 组件A 建设链接关系用同样形式和 组件B 建设链接关系在 查看器 的数据绑定及设置中,进行默认组件设置和内容组件设置 组件切换器配置“点赞”触发器选中 组件切换器点击 触发器 图标创立“点赞” 触发器配置“点赞” 触发器 组件切换器配置“勾销点赞”触发器创立“勾销点赞” 触发器配置“勾销点赞” 触发器 https://www.towify.com

November 8, 2022 · 1 min · jiezi

关于微信小程序:微信原生组件|基于小程序实现音视频通话

1 微信小程序原生推拉流组件性能简介本文将介绍如何应用微信小程序原生推拉流组件 \<live-pusher> 和 \<live-player> 进行推拉流,疾速实现一个简略的实时音视频通话。 因为微信小程序原生推拉流组件应用起来比较复杂,举荐开发者应用即构封装的音视频SDK \<zego-push> 和 \<zego-player> 组件实现视频通话,可参考 实现视频通话。 2 实现微信小程序音视频通话的前提条件在实现根本的实时音视频性能之前,请确保: 已在我的项目中集成 ZEGO Express SDK 即构音视频SDK,详情请参考 疾速开始 - 集成。已在 ZEGO 控制台 创立我的项目,申请无效的 AppID 和 ServerSecret,详情请参考 控制台 - 项目管理 中的“我的项目信息”。3 即构音视频SDK实现流程用户通过 ZEGO Express SDK 即构音视频SDK进行视频通话的根本流程为: 用户 A、B 退出房间,用户 B 预览并将音视频流推送到 ZEGO 云服务(推流),用户 A 收到用户 B 推送音视频流的告诉之后,在告诉中播放用户 B 的音视频流(拉流)。 3.1 配置微信小程序后盾在初始化 音视频SDK 前,须要在 微信公众平台 中进行如下配置: 服务器域名配置:在“小程序后盾 > 开发治理 > 开发设置 > 服务器域名”中,依照协定分类,将即构 Server 地址、LogUrl、以及用户业务须要用到的地址填到指定的“request非法域名”或“socket非法域名”中。 相干性能开启:在“小程序后盾 > 开发治理 > 接口设置 > 接口权限”中,关上 实时播放音视频流 和 实时录制音视频流 性能开关。3.2 即构音视频SDK初始化1. 创立音视频通话界面 ...

September 21, 2022 · 4 min · jiezi

关于微信小程序:微信小程序单指拖拽和双指缩放旋转

前言小程序单指拖拽和双指操作是一个比拟罕用的性能,成果如下图 实现这三个性能,次要用三个触摸事件touchstart、touchmove、touchend <view style="height: 100vh; width: 100vw"> <image src="..." style="transform: translate({{translateX}}px, {{translateY}}px) scale({{scale}}) rotate({{rotate}}deg);" catch:touchstart="touchStart" catch:touchmove="touchMove" catch:touchend="touchEnd" /></view>用了以下变量 Page({ data: { translateX: 0, // 位移x坐标 单位px translateY: 0, // 位移y坐标 单位px distance: 0, // 双指接触点间隔 scale: 1, // 缩放倍数 rotate: 0, // 旋转角度 oldRotate: 0, // 上一次旋转进行后的角度 startMove: { // 起始位移间隔 x: 0, y: 0, }, startTouches: [] // 起始点touch数组 },})单指拖拽实现单指拖拽比较简单,只须要记录挪动的点坐标,而后减去起始点坐标,就能够求出绝对页面的挪动间隔touchstart touchStart(e) { const touches = e.touches const { translateX, translateY } = this.data const { pageX, pageY } = touches[0] this.data.startMove = { x: pageX - translateX, y: pageY - translateY } this.data.startTouches = touches},touchmove ...

September 6, 2022 · 2 min · jiezi

关于微信小程序:微信小程序图片拖拽排序组件

前言图片拖拽排序是一个比拟罕用的组件,罕用于发帖或者评论等内容上传模块,我就借鉴了《一款优雅的小程序拖拽排序组件实现》这篇文章的实现思路,并封装成wx-drag-img公布到npm实现原理:每个图片初始化我都会封装成一个拖拽的数据结构,而后通过触发touch事件,扭转transform地位,从而达到拖拽成果性能包含图片上传拖拽删除,源码和npm地址我会贴在结尾,如果感觉好的话,欢送star我会在上面逐渐剖析这个组件的实现思路应用了以下变量 // 拖拽数据结构interface IDragImg { src: string; // 图片门路 key: number; // id: number; // for循环遍历应用, 不会扭转, 创立时自增id tranX: number; // x轴位移间隔 tranY: number; // y轴位移间隔}// props{ previewSize // 图片大小 defaultImgList // 初始化图片数组 maxCount // 图片上传数量限度 columns // 列数 gap // 图片距离 deleteStyle // 删除款式}data: { dragImgList: IDragImg[], containerRes: { top: 0, // 容器间隔页面顶部间隔 px left: 0, // 容器间隔页面右边间隔 px width: 0, // 容器宽度 px height: 0, // 容器高度 px }, // 拖拽容器属性 currentKey: -1, // 正在拖拽图片的key currentIndex: -1, // 正在拖拽图片的index tranX: 0, // 正在拖拽图片挪动的x间隔 tranY: 0, // 正在拖拽图片挪动的y间隔 uploadPosition: { // upload上传图标位移间隔 tranX: 0, tranY: 0, }},WXML<view style="width: {{containerRes.width}}px; height: {{containerRes.height}}px;" class="drag-container"> <view wx:for="{{dragImgList}}" wx:key="id" style="transform: translate({{index === currentIndex ? tranX : item.tranX}}px, {{index === currentIndex ? tranY : item.tranY}}px); z-index: {{index === currentIndex ? 10 : 1}}; width: {{previewSize}}px; height: {{previewSize}}px;" class="drag-item drag-item-transition" mark:index="{{index}}" mark:key="{{item.key}}" catch:longpress="longPress" catch:touchmove="touchMove" catch:touchend="touchEnd" > <image class="drag-item-img" src="{{item.src}}"/> <!-- 删除图标 --> <view catch:tap="deleteImg" mark:key="{{item.key}}" class="drag-item-delete"> <view class="drag-item-delete_default" style="{{deleteStyle}}">x</view> </view> </view> <!-- 上传图片 --> <view bindtap="uploadImage" class="drag-item drag-upload" hidden="{{dragImgList.length >= maxCount}}" style="transform: translate({{uploadPosition.tranX}}px, {{uploadPosition.tranY}}px); width: {{previewSize}}px; height: {{previewSize}}px;" > <view class="drag-upload_solt"> <slot name="upload"></slot> </view> <view class="drag-upload_default"> <text>+</text> </view> </view></view>图片上传图片上传很简略,就是初始化上传的图片,而后拼接到现有图片,最初批改上传图标地位即可点击上传区域回调函数uploadImage ...

September 4, 2022 · 4 min · jiezi

关于微信小程序:微信小程序瀑布流和虚拟列表

微信小程序瀑布流和虚构列表尽管本篇是写的微信小程序的案例,然而也可用于H5,思路是想通的,只是有些api的差别,最初会贴代码片段 虚构列表个别在做长列表优化时,特地是面试时,虚构列表就是个高频词。这个名词听起来很高级,其实原理很简略虚构列表就是将须要渲染的数组数据革新成二维数组,而后通过监听DOM节点在适合的中央切换为占位元素,达到长列表有限滚动时缩小DOM渲染的优化JS /** * 解决占位元素,就是在获取新的数据后 * 通过SelectQuery获取以后数据的理论高度,而后把这个高度设置到占位元素上 */getCurrentItemHeight() { const query = this.createSelectorQuery(); const { virtualId } = this.data query.select(`#${virtualId}`).boundingClientRect() query.exec((res) => { this.setData({ height: res[0].height }, this.observePage()) })}/** * 监听元素与页面的相交 * 能够抉择指定元素为参照区域,也能够抉择页面为参照元素,只是API不同 * @doc https://developers.weixin.qq.com/miniprogram/dev/api/wxml/IntersectionObserver.html */observePage() { const { virtualId, observeDistance, wrapId } = this.data let IntersectionObserver = wx.createIntersectionObserver(this); (wrapId ? IntersectionObserver.relativeTo(`#${wrapId}`) : IntersectionObserver.relativeToViewport({ top: observeDistance, bottom: observeDistance })) .observe(`#${virtualId}`, ({ intersectionRatio }) => { this.setData({ isShow: intersectionRatio > 0, }) })}WXML ...

August 21, 2022 · 2 min · jiezi

关于微信小程序:微信小程序四绝对不可错过切换自定义菜单栏的骚操作

前言在开发小程序的时候,个别的小程序用官网自带的菜单栏就够了,但一但略微简单的小程序可能因为产品经理的一句“页面太多了得加个菜单”,就可能要对菜单栏进行增、删、改的操作,这个时候自带的就满足不了需要了,能够应用官网提供的自定义菜单栏。但官网提供的自定义菜单栏有个特点,就是菜单栏的页面必须是 Component ,如果你是在我的项目做到一半的时候有要对菜单栏进行增、删、改的需要,用官网提供自定义菜单栏就须要把page页面改成 Component,那就须要很多工夫批改页面逻辑,会很麻烦。所以这个时候,咱们就能够采纳官网自带的菜单栏和本人封装的菜单栏组合应用,这样能节俭批改逻辑的工夫,还能享受自带菜单的良好交互。 思路咱们能够用小程序自带的菜单和咱们本人封装的自定义菜单组件应用,具体逻辑是这样的: 咱们先能够在全局 app.js 文件的全局变量 globalData 里定义一个辨别展现自定义菜单还是官网自带菜单的变量 tabbar_type通过 tabbar_type 在每个菜单页面辨别展现官网自带的菜单栏还是本人封装的自定义菜单栏当展现自定义菜单栏的时候调用官网提供的 api 暗藏官网自带的菜单栏。当展现官网菜单栏的时候,通过批改全局变量 tabbar_type 的值来暗藏自定义菜单栏成品成果 具体实现先在 app.json 页面配置好官网自带的菜单栏 "tabBar": { "custom": false, "color": "#999999", "selectedColor": "#00C3B3", "borderStyle": "black", "backgroundColor": "#f8f8f8", "list": [ { "selectedIconPath": "/assets/img/homeActive.png", "iconPath": "/assets/img/home.png", "pagePath": "pages/index/index", "text": "首页" }, { "selectedIconPath": "/assets/img/mallActive.png", "iconPath": "/assets/img/mall.png", "pagePath": "pages/index/index", "text": "商城" }, { "selectedIconPath": "/assets/img/myActive.png", "iconPath": "/assets/img/my.png", "pagePath": "pages/index/index", "text": "我的" } ] },而后封装一个自定义的菜单栏组件目录构造: + components + shoping-tabbar - index.js - index.json - index.wxml - index.wxssindex.js 文件代码 ...

July 21, 2022 · 2 min · jiezi

关于微信小程序:微信小程序三实现类似Vue中的-computedwatch-功能

前言微信小程序和 vue 的语法十分像,会写 vue 的敌人上手 vue 根本是大海捞针。然而微信小程序中短少了很多 vue 中没有的货色,比方计算属性 computed 、监听 watch。这些在平时开发中会常常用到。尽管微信小程序没有间接提供相干的 API 来应用这些,然而咱们能够用其余的一些办法来简略的间接的实现这些性能。这篇文章就是记录一下实现这些性能的过程和一些集体感触。 实现步骤computed 的实现过程computed 的实现过程非常简单,咱们能够通过微信小程序脚本语言 WXS(WeiXin Script) 来简略实现相似vue中的 计算属性性能(computed)。 先了解官网文档的示例 <!--wxml--><wxs module="m1">var msg = "hello world";module.exports.message = msg;</wxs><view> {{m1.message}} </view>页面输入:hello world咱们能够把 <wxs></wxs> 标签当做一对 <script></script> 标签一样,咱们能够在外面定义变量、函数。而后在 “Mustache” 语法双括号里应用咱们定义的函数和变量。 看完官网示例后咱们就来实现一个相似 vue 中的简略的 computed 。// page.jsPage({ data: { order: { time: '2022-06-27', status: 1, amount: 10 } }})<wxs module="comp"> module.exports = { handleMatchStatus: function (source) { switch (source) { case 1: return '已领取' case 2: return '领取失败' case 3: return '退款中' } } }</wxs><view> {{comp.handleMatchStatu(order.status)}} </view>输入:已领取在后盾拿到的一些数据,比方订单数据外面只有商品单价和数据,页面须要你显示总价,这个时候就能够这种形式来实现;或者是我的项目中有些数据是状态或者类型数据,比方订单状态、订单类型、商品渠道等,通过后端传过来的都是数字,有字典表的话还好办,没有字典表的话个别都是和后端磋商好,定死几个值,这个时候就能够通过这种形式显示数值对应的文字意思。 ...

July 21, 2022 · 2 min · jiezi

关于微信小程序:微信小程序一自定义导航栏和fixed失效及各机型兼容问题

前言置信小伙伴们应该或多或少都开发过微信小程序,微信小程序的写法尽管和vue有很多相似的中央,但又有很多vue属性,在小程序中没有相似的实现,比方计算属性,watch 监听等;因为小程序是附着在微信 app 上,所以常常要解决一些安卓端和苹果端的兼容,比方有些苹果机屏幕下方有平安区域,一些安卓机上点输入框输出结束后点实现按钮键盘不能主动发出,导致输入框不能失去焦点的问题,等等...为了当前本人和小伙伴们不再节约踩坑的工夫,我打算写一些文章记录一下我在开发微信小程序中遇到的一些坑和一些小性能的实现过程。 目录:微信小程序(一)自定义导航栏和fixed生效及各机型兼容问题微信小程序(二)用 movable-view 实现左滑删除性能微信小程序(三)实现相似Vue中的 computed,watch 性能微信小程序(四)相对不可错过切换自定义菜单栏的骚操作微信小程序(五)不同机型中的输入框兼容问题(待更新)...cover-view 组件应用 fixed 款式生效问题背景因我的项目需要,要开发一个自定义 tabBar,在微信官网文档找到一个demo,官网demo看到 tabBar 组件是用根底组件 cover-view 和 cover-image 构建的架子,用 position 的 fixed 固定定位在手机屏幕最下方,用真机调试是发现 tabBar 组件并不一定会固定在屏幕的最下方,而且如果页面滑动,用 fixed 固定的区域会上下挪动 官网demo 示例代码 起因: 在微信社区找相干问题发现是 cover-view 的起因,而后这个问题直到现在如同还没修复 解决方案改用 view 和 image 根底组件构建架子就能够了 自定义导航栏、状态栏在不同机型的适配背景起因因为不同机型的导航栏和胶囊距高低间距不同,导致自定义的导航栏的高度不能固定。需要是导航栏的文字要和胶囊对齐。 解绝计划废话不多说了,间接上代码,前面有解释阐明: /* 获取胶囊的地位和手机状态栏的信息 */ async getMenuInfo() { let { top, height } = wx.getMenuButtonBoundingClientRect(); let statusBarHeight = ""; wx.getSystemInfo({ success(res) { statusBarHeight = res.statusBarHeight } }) this.setData({ topParams: { top, height, statusBarHeight }, }) },通过 wx.getMenuButtonBoundingClientRect() 获取菜单按钮(右上角胶囊按钮)的布局地位信息。坐标信息以屏幕左上角为原点。获取的参数解释: ...

July 21, 2022 · 1 min · jiezi

关于微信小程序:getLocationfail-频繁调用会增加电量损耗可考虑使用-wxonLocationChange-监听地理位置变化

问题形容:在微信小程序里要做应用地址的关键字搜寻性能,比方搜“火车站”进去跟火车站相干的列表,可供选择。 于是引入:qqmap-wx-jssdk.js,并且在js中调用: map.search({ keyword: search, // 关键字,跟一个input绑定 page_size: 20, auto_extend: 1, success: function (res) {}, fail: function (res) {},});应用时发现问题:每当input的内容扭转时,触发search的调用,而后控制台就会报错message: "getLocation:fail 频繁调用会减少电量损耗,可思考应用 wx.onLocationChange 监听地理位置变动",而后在短时间内(约10秒)无奈再进行搜寻,用户体验很差。 奇了怪了,我只是调了map.search,没调wx.getLocation啊,怎么老是报这个错呢? 解决方案太长不看版本,间接给解决方案:search外面加个属性location,字符串,是以后所在经纬度用逗号隔开的。如: map.search({ keyword: search, // 关键字,跟一个input绑定 page_size: 20, auto_extend: 1, location: `${latitude},${longitude}`, // 加上这个属性 success: function (res) {}, fail: function (res) {},});而后问题就解决了 定位问题过程说说我是怎么定位问题的。首先咱们只调用了qqmap-wx-jssdk.js提供的api,却进去意料之外的谬误,八成是qqmap-wx-jssdk.js的问题。关上此js,搜寻wx.getLocation,很侥幸,代码里只有一个中央用到了,如下图: 于是持续搜寻wx.getLocation所在的getWXLocation函数,看看是在哪里,都是什么状况调用的,如下图: 于是持续搜寻这行代码所在的函数locationProcess,看看param是在哪里传入的,后果发现是在咱们所应用的map.search函数里调用的,如下图: 传入location之后,逻辑就不走下面走上面了,发现代码调用了一个checkLocation,于是去看checkLocation的逻辑,如下图: 找到getLocationParam函数之后,明确了location的数据类型及构造,如下图: 那么就能够梳理出map.search大体的流程:调用map.search时,如果options里没有location,就会调getWXLocation;如果有,就不凋。location属性能够是字符串,逗号分隔,也能够是一个对象,间接蕴含latitude和longitude。 结束

July 8, 2022 · 1 min · jiezi

关于微信小程序:此小程序已过期请重新扫描二维码错误码104

关上体验版报错:此小程序已过期,请从新扫描二维码(错误码:104)解决方案:勾销体验 - 从新设置体验

July 6, 2022 · 1 min · jiezi

关于微信小程序:微信小程序中使用canvas-卡顿问题

需要: 微信小程序中生成二维码,不可对二维码进行截图(截图的时候页面提醒), 问题1. onLoad 中监听手机的截屏动作,同时管制页面显示//在onLoad 中监听手机的截屏动作,同时管制页面显示onLoad(){ //二维码上面显示实时工夫 this.time = utils.showTime(new Date()); setInterval(() => { this.time = utils.showTime(new Date()); }, 1000) //在onLoad 中监听手机的截屏动作 //noScreenshot 管制页面切换的数据 let that = this; wx.onUserCaptureScreen(function (res) { that.noScreenshot = false; setTimeout(() => { that.noScreenshot = true; }, 3000); }) }, // 问题:// 不能够应用v-if 进行页面状态的切换,v-if为false时dom元素间接销毁,当切换为true的时候,canvas是没有重建的,会显示为空白,这里躲避能够应用v-show 来解决canvas的显示,这里还将提醒页面的定位层级加高了,遗记这里的解决是否是因为v-show为false的时候canvas没有暗藏的起因了,前面应用的时候能够验证一下问题2. 页面重绘的过程中canvas的地位变动响应很慢//问题总结:canvas 在绘制的过程中应用的全部都是CPU,没有应用GPU硬件加速,导致绘制很慢呈现卡顿的状况,//这里的需要是一个申请能够邀请多集体,用户二维码上面会显示以后曾经认证的伙伴人数和根本信息,能够折叠,在折叠的过程中,页面尺寸变动时,canvas的地位呈现卡顿,//wxml <view class="wrap-qrcode-info"> <canvas class="wrap-qrcode-canvas" canvasId='qrcode'></canvas> <image :src="loadImagePath"></image> </view> //js //生成canvas 实例 drawQrcode({ width: 140, height: 140, canvasId: 'qrcode', _this: this.$scope, text: applyUserInfo.visitor_code });//生成实例之后将其转化为img,将url复制给wxml中的image 标签 let that = this; setTimeout(function () { wx.canvasToTempFilePath({ width: 140, height: 140, canvasId: 'qrcode', success: function (res) { var tempFilePath = res.tempFilePath; that.loadImagePath = tempFilePath; }, fail: function (res) { console.log(res); } }); }, 500);//工夫须要调整,确保是canvas context 曾经生成 //这里须要留神的是wxml中其实是将canvas地位定位到页面看不到的地位,显示的二维码其实是依赖二维码生成的图片,

July 5, 2022 · 1 min · jiezi

关于微信小程序:快速创建微信小程序注册即认证无需300元认证费

疾速注册微信小程序,以前就搞过相干的零碎开发,通过接口间接注册,真的是很不便,能够用【快准好】来形容。而且是注册即认证的成果,也就是说,只有注册胜利,该小程序就是已认证的状态,无需再另外的认证费用。 相比从官网后盾去注册,须要筹备大量的信息材料,注册实现还要另外认证(300米),认证小额打款也须要肯定工夫,挺繁琐。而疾速注册则只需收集法人姓名、法人微信、企业名称、企业代码信息这四个信息,便能够向企业法人下发一条模板音讯来采集法人人脸信息,实现全副注册、认证流程,无需300米认证费用。 在接口调用胜利后,通过法人&企业主体校验,平台向法人微信下发模板音讯。法人需在24 小时内点击音讯,进行身份证信息与人脸识别信息收集。 撸了一个零碎,既能够从前端,也能够从后端进行疾速注册已认证的微信小程序,这个零碎次要是通过微信开放平台接口实现的。 前端是公众号h5的模式,包含三个模块,首页、记录、我的。 治理后端包含用户治理、注册治理、订单治理。 用户治理 用户信息,次要就是展现用户的一些信息。 注册治理 注册指南,次要就是对注册步骤的一些介绍。 疾速注册,次要就是注册认证小程序的提交信息和注意事项。 常见问题,次要就是注册过程遇到的一些常见问题以及解决办法。 设置账号,次要就是注册胜利后对小程序设置账号和明码的步骤。 订单治理 订单列表,次要就是对注册的一些信息记录,能够通过企业代码(也就是对立社会信用代码)来查问本人注册的一些记录信息。 以上就是微信小程序注册认证的流程。 回复【小程序注册】- 》获取账号密码 疾速创立微信小程序,注册即认证 山水有相逢,来日皆可期,谢谢浏览,咱们再会 我手中的金箍棒,上能通天,下能探海 上一篇:公众号开发-群发图文中插入小程序卡片报错 invalid content hint 的解决

June 29, 2022 · 1 min · jiezi

关于微信小程序:微信小程序-体验版上传流程

checkout到master分支批改/miniProgramInfo.js中的版本号点击菜单栏>>发行>>小程序-微信(仅实用于uni-app),默认都不勾选,间接点击发行发行后会主动在微信开发者工具中关上点击微信开发者工具>>右上角>>上传,批改版本号,填写我的项目备注,点击上传

May 30, 2022 · 1 min · jiezi

关于微信小程序:微信小程序接入扫呗支付

理论领取之前,须要先申请预充值信息,获取订单流水号,理论领取的时候须要带上这个参数,等到领取胜利,订单流水号会间接返给领取后果回调告诉地址。扫呗官网:http://help.lcsw.cn/xrmpic/ti... 总体流程图如下: 申请预充值信息getOrderNo() { return new Promise((resolve, reject) => { myAjax('getOrderNo','POST' { payAmount: 1 // 示意充值一分钱 }, (res) => { this.setData({ orderNo: res.orderNo // 示意返回的订单流水号 }, () => { resolve() }) }) }) }去充值,因为别的页面也须要购买或充值,这里封装成了公共办法publicPay,引入const { publicPay } = require('../../util/public.js') async goRecharge() { await this.getOrderNo() // 须要先等返回订单流水号 let param = { orderNo: this.data.orderNo, total_fee: this.data.amountSelected.toString() // 金额,单位分 } publicPay(param, (res, paySuccess) => { if (paySuccess) { // 示意领取胜利 } }) },publicPay办法须要先引入md5,代码如下:const md5 = require('../libs/md5/md5')export const publicPay = (param, cb) => { const sub_appid = 'wx543795375437543' // 微信小程序的appid const open_id = wx.getStorageSync('openid') // 应用微信领取时为必填项,请提前获取 const sb_http = 'https://pay.lcsw.cn/lcsw/pay/100/minipay' // 扫呗领取接口地址 const sb_key = '5034217reywrruewi23143e75b' // 扫呗提供给商户的密钥,一种token // 以下是必填参数 const pay_ver = '100' // 扫呗版本号,请到扫呗官网查看以后版本号 const pay_type = '010' // 领取形式,010 代表微信 const service_id = '015' // 接口类型,请到扫呗官网查看以后接口类型 const merchant_no = '85343242342341' // 扫呗提供的商户号 const terminal_id = '13065307' // 扫呗提供的终端号 const terminal_trace = param.orderNo // 订单流水号 const terminal_time = getDateTimeToString() // 交易工夫,这里是公共办法,上面有介绍 const total_fee = param.total_fee // 金额单位:分 // 必传参数拼接生成 key_sign let mustParamString = `pay_ver=${pay_ver}&pay_type=${pay_type}&service_id=${service_id}&merchant_no=${merchant_no}&terminal_id=${terminal_id}&terminal_trace=${terminal_trace}&terminal_time=${terminal_time}&total_fee=${total_fee}&access_token=${sb_key}` let key_sign = md5.hexMD5(mustParamString) // 须要md5加密 // 以下是非必填参数 let order_body = '本次领取的订单形容,选填' let notify_url = 'https://xxx.xxx.com/xxx' // 领取后果回调告诉地址,跟后端约好 let params = { pay_ver, pay_type, service_id, merchant_no, terminal_id, terminal_trace, terminal_time, total_fee, sub_appid, open_id, key_sign, order_body, notify_url } wx.request({ url: sb_http, method: 'POST', data: params, dataType: 'json', success: function (res) { // 把扫呗返回的后果,放进微信领取须要的参数 wx.requestPayment({ timeStamp: res.data.timeStamp, nonceStr: res.data.nonceStr, package: res.data.package_str, signType: 'MD5', paySign: res.data.paySign, success(resPay) { // 领取胜利的回调 cb(resPay, 'paySuccess') }, fail(resPayFail) { cb(resPayFail) } }) }, fail: function (err) { if (err) { cb(err) } } })}领取所须要的交易工夫格局,yyyyMMddHHmmss,办法如下:getDateTimeToString() { var date_ = new Date(); var year = date_.getFullYear(); var month = date_.getMonth() + 1; var day = date_.getDate(); if (month < 10) month = "0" + month; if (day < 10) day = "0" + day; var hours = date_.getHours(); var mins = date_.getMinutes(); var secs = date_.getSeconds(); var msecs = date_.getMilliseconds(); if (hours < 10) hours = "0" + hours; if (mins < 10) mins = "0" + mins; if (secs < 10) secs = "0" + secs; if (msecs < 10) secs = "0" + msecs; return year + month + day + hours + mins + secs;}md5.js 代码如下:/* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as defined in RFC 1321. * Version 1.1 Copyright (C) Paul Johnston 1999 - 2002. * Code also contributed by Greg Holt * See http://pajhome.org.uk/site/legal.html for details. *//* * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters. */function safe_add(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF) var msw = (x >> 16) + (y >> 16) + (lsw >> 16) return (msw << 16) | (lsw & 0xFFFF)}/* * Bitwise rotate a 32-bit number to the left. */function rol(num, cnt) { return (num << cnt) | (num >>> (32 - cnt))}/* * These functions implement the four basic operations the algorithm uses. */function cmn(q, a, b, x, s, t) { return safe_add(rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b)}function ff(a, b, c, d, x, s, t) { return cmn((b & c) | ((~b) & d), a, b, x, s, t)}function gg(a, b, c, d, x, s, t) { return cmn((b & d) | (c & (~d)), a, b, x, s, t)}function hh(a, b, c, d, x, s, t) { return cmn(b ^ c ^ d, a, b, x, s, t)}function ii(a, b, c, d, x, s, t) { return cmn(c ^ (b | (~d)), a, b, x, s, t)}/* * Calculate the MD5 of an array of little-endian words, producing an array * of little-endian words. */function coreMD5(x) { var a = 1732584193 var b = -271733879 var c = -1732584194 var d = 271733878 for (var i = 0; i < x.length; i += 16) { var olda = a var oldb = b var oldc = c var oldd = d a = ff(a, b, c, d, x[i + 0], 7, -680876936) d = ff(d, a, b, c, x[i + 1], 12, -389564586) c = ff(c, d, a, b, x[i + 2], 17, 606105819) b = ff(b, c, d, a, x[i + 3], 22, -1044525330) a = ff(a, b, c, d, x[i + 4], 7, -176418897) d = ff(d, a, b, c, x[i + 5], 12, 1200080426) c = ff(c, d, a, b, x[i + 6], 17, -1473231341) b = ff(b, c, d, a, x[i + 7], 22, -45705983) a = ff(a, b, c, d, x[i + 8], 7, 1770035416) d = ff(d, a, b, c, x[i + 9], 12, -1958414417) c = ff(c, d, a, b, x[i + 10], 17, -42063) b = ff(b, c, d, a, x[i + 11], 22, -1990404162) a = ff(a, b, c, d, x[i + 12], 7, 1804603682) d = ff(d, a, b, c, x[i + 13], 12, -40341101) c = ff(c, d, a, b, x[i + 14], 17, -1502002290) b = ff(b, c, d, a, x[i + 15], 22, 1236535329) a = gg(a, b, c, d, x[i + 1], 5, -165796510) d = gg(d, a, b, c, x[i + 6], 9, -1069501632) c = gg(c, d, a, b, x[i + 11], 14, 643717713) b = gg(b, c, d, a, x[i + 0], 20, -373897302) a = gg(a, b, c, d, x[i + 5], 5, -701558691) d = gg(d, a, b, c, x[i + 10], 9, 38016083) c = gg(c, d, a, b, x[i + 15], 14, -660478335) b = gg(b, c, d, a, x[i + 4], 20, -405537848) a = gg(a, b, c, d, x[i + 9], 5, 568446438) d = gg(d, a, b, c, x[i + 14], 9, -1019803690) c = gg(c, d, a, b, x[i + 3], 14, -187363961) b = gg(b, c, d, a, x[i + 8], 20, 1163531501) a = gg(a, b, c, d, x[i + 13], 5, -1444681467) d = gg(d, a, b, c, x[i + 2], 9, -51403784) c = gg(c, d, a, b, x[i + 7], 14, 1735328473) b = gg(b, c, d, a, x[i + 12], 20, -1926607734) a = hh(a, b, c, d, x[i + 5], 4, -378558) d = hh(d, a, b, c, x[i + 8], 11, -2022574463) c = hh(c, d, a, b, x[i + 11], 16, 1839030562) b = hh(b, c, d, a, x[i + 14], 23, -35309556) a = hh(a, b, c, d, x[i + 1], 4, -1530992060) d = hh(d, a, b, c, x[i + 4], 11, 1272893353) c = hh(c, d, a, b, x[i + 7], 16, -155497632) b = hh(b, c, d, a, x[i + 10], 23, -1094730640) a = hh(a, b, c, d, x[i + 13], 4, 681279174) d = hh(d, a, b, c, x[i + 0], 11, -358537222) c = hh(c, d, a, b, x[i + 3], 16, -722521979) b = hh(b, c, d, a, x[i + 6], 23, 76029189) a = hh(a, b, c, d, x[i + 9], 4, -640364487) d = hh(d, a, b, c, x[i + 12], 11, -421815835) c = hh(c, d, a, b, x[i + 15], 16, 530742520) b = hh(b, c, d, a, x[i + 2], 23, -995338651) a = ii(a, b, c, d, x[i + 0], 6, -198630844) d = ii(d, a, b, c, x[i + 7], 10, 1126891415) c = ii(c, d, a, b, x[i + 14], 15, -1416354905) b = ii(b, c, d, a, x[i + 5], 21, -57434055) a = ii(a, b, c, d, x[i + 12], 6, 1700485571) d = ii(d, a, b, c, x[i + 3], 10, -1894986606) c = ii(c, d, a, b, x[i + 10], 15, -1051523) b = ii(b, c, d, a, x[i + 1], 21, -2054922799) a = ii(a, b, c, d, x[i + 8], 6, 1873313359) d = ii(d, a, b, c, x[i + 15], 10, -30611744) c = ii(c, d, a, b, x[i + 6], 15, -1560198380) b = ii(b, c, d, a, x[i + 13], 21, 1309151649) a = ii(a, b, c, d, x[i + 4], 6, -145523070) d = ii(d, a, b, c, x[i + 11], 10, -1120210379) c = ii(c, d, a, b, x[i + 2], 15, 718787259) b = ii(b, c, d, a, x[i + 9], 21, -343485551) a = safe_add(a, olda) b = safe_add(b, oldb) c = safe_add(c, oldc) d = safe_add(d, oldd) } return [a, b, c, d]}/* * Convert an array of little-endian words to a hex string. */function binl2hex(binarray) { var hex_tab = "0123456789abcdef" var str = "" for (var i = 0; i < binarray.length * 4; i++) { str += hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 0xF) + hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8)) & 0xF) } return str}/* * Convert an array of little-endian words to a base64 encoded string. */function binl2b64(binarray) { var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" var str = "" for (var i = 0; i < binarray.length * 32; i += 6) { str += tab.charAt(((binarray[i >> 5] << (i % 32)) & 0x3F) | ((binarray[i >> 5 + 1] >> (32 - i % 32)) & 0x3F)) } return str}/* * Convert an 8-bit character string to a sequence of 16-word blocks, stored * as an array, and append appropriate padding for MD4/5 calculation. * If any of the characters are >255, the high byte is silently ignored. */function str2binl(str) { var nblk = ((str.length + 8) >> 6) + 1 // number of 16-word blocks var blks = new Array(nblk * 16) for (var i = 0; i < nblk * 16; i++) blks[i] = 0 for (var i = 0; i < str.length; i++) blks[i >> 2] |= (str.charCodeAt(i) & 0xFF) << ((i % 4) * 8) blks[i >> 2] |= 0x80 << ((i % 4) * 8) blks[nblk * 16 - 2] = str.length * 8 return blks}/* * Convert a wide-character string to a sequence of 16-word blocks, stored as * an array, and append appropriate padding for MD4/5 calculation. */function strw2binl(str) { var nblk = ((str.length + 4) >> 5) + 1 // number of 16-word blocks var blks = new Array(nblk * 16) for (var i = 0; i < nblk * 16; i++) blks[i] = 0 for (var i = 0; i < str.length; i++) blks[i >> 1] |= str.charCodeAt(i) << ((i % 2) * 16) blks[i >> 1] |= 0x80 << ((i % 2) * 16) blks[nblk * 16 - 2] = str.length * 16 return blks}/* * External interface */function hexMD5(str) { return binl2hex(coreMD5(str2binl(str))) }function hexMD5w(str) { return binl2hex(coreMD5(strw2binl(str))) }function b64MD5(str) { return binl2b64(coreMD5(str2binl(str))) }function b64MD5w(str) { return binl2b64(coreMD5(strw2binl(str))) }/* Backward compatibility */function calcMD5(str) { return binl2hex(coreMD5(str2binl(str))) }module.exports = { hexMD5: hexMD5}

April 25, 2022 · 9 min · jiezi

关于微信小程序:微信小程序封装公共组件table表格

因为小程序可能不止一个页面须要用表格展现数据,所以在components里封装公共组件,如下图: 首先,在myTable组件的index.wxml写好布局,这里次要是表格头部,表格内容则通过slot插槽插入进来<view class="my-table-wrap"> <view class="my-table"> <view class="my-table-thead"> <view class="my-tr"> <view class="my-th" style="width:{{item.width}}" wx:for-items="{{tableHeadData}}" wx:key="index" >{{item.title}}</view> </view> </view> <view class="my-table-tbody"> <slot></slot> </view> </view></view>表格的每一列是一个公共组件myTableCol,其index.wxml内容如下:<view style="height: 100%;"> <view wx:if="{{prop}}" class="my-table-tbody-col"> <block wx:for-items="{{list}}" wx:key="index"> <view class="my-td">{{item}}</view> </block> </view> <view wx:else class="my-table-tbody-col"> <view class="my-td-op" wx:for="{{tableData}}" wx:key="id" wx:for-index="row"> <block wx:for-items="{{operateList}}" wx:key="index"> <view class="blueviolet-edit" bindtap="operate" data-row="{{row}}" data-index="{{index}}">{{item}}</view> </block> </view> </view></view>分为两种状况,传了prop的一般列和操作列,myTableCol的index.js内容如下: Component({ properties: { prop: { type: String }, label: { type: String }, width: { type: String }, tableData: { type: Array, observer: function(newVal, oldVal) { // 当编辑表格时,会从新申请表格数据,这里就会渲染 let list = newVal.map(i=> i[this.properties.prop]) this.setData({list}) } }, operate: { type: String }, }, pageLifetimes: { show() { if(this.properties.prop){ // 筛选出每一一般列的数据 let list = this.properties.tableData.map(i=> i[this.properties.prop]) this.setData({list}) }else{ // 操作列 let operateList = this.properties.operate.split(',') this.setData({operateList}) } } }, data: { list:[], operateList:[], }, methods: { operate(e){ // 操作列的点击事件,须要传给父组件两个信息:点了表格的哪一行(row),点了按钮的哪一个(index) this.triggerEvent('getOperateIndex', { row: e.target.dataset.row, index: e.target.dataset.index, }) }, }})在页面援用,须要先在应用的页面的index.json文件中写上: "usingComponents": { "myTable":"../../components/myTable/index", "myTableCol":"../../components/myTableCol/index" }而后在index.wxml文件里应用组件,例如: ...

April 25, 2022 · 1 min · jiezi

关于微信小程序:微信小程序根据url生成二维码

首先,页面有个展现二维码的容器,canvas肯定要有宽高 <view class="qrcode"> <canvas style="width: 200px;height: 200px;" canvas-id="mycanvas"/> </view>在生命周期函数-页面加载中拿到要生成二维码的url,路由传url须要先用encodeURIComponent办法转码,而后再用decodeURIComponent办法解码(为的是避开&符号) onLoad: function (options) { this.createQrCode( decodeURIComponent(options.url), 'mycanvas', 200, 200 ) }创立二维码,这里须要先引入QR对象let QR = require('../../libs/qrcode/qrcode') createQrCode: function (content, canvasId, cavW, cavH) { //调用插件中的draw办法,绘制二维码图片 //this.canvasToTempImage 为绘制实现的回调函数,可依据本人的业务增加 QR.api.draw(content, canvasId, cavW, cavH, this, this.canvasToTempImage); },获取长期缓存图片门路,存入data中 canvasToTempImage: function (canvasId) { wx.canvasToTempFilePath({ canvasId, // 这里canvasId即之前创立的canvas-id success: (res) => { let tempFilePath = res.tempFilePath; // 这里能够获取到生成二维码的图片地址 }, fail: (res) => { console.log(res); } }); },qrcode.js源码如下:!(function () { // alignment pattern var adelta = [ 0, 11, 15, 19, 23, 27, 31, 16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24, 26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28 ]; // version block var vpat = [ 0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d, 0x928, 0xb78, 0x45d, 0xa17, 0x532, 0x9a6, 0x683, 0x8c9, 0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75, 0x250, 0x9d5, 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64, 0x541, 0xc69 ]; // final format bits with mask: level << 3 | mask var fmtword = [ 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, //L 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, //M 0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, //Q 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b //H ]; // 4 per version: number of blocks 1,2; data width; ecc width var eccblocks = [ 1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17, 1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28, 1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22, 1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16, 1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22, 2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28, 2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26, 2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26, 2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24, 2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28, 4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24, 2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28, 4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22, 3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24, 5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24, 5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30, 1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28, 5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28, 3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26, 3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28, 4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30, 2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24, 4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30, 6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30, 8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30, 10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30, 8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30, 3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30, 7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30, 5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30, 13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30, 17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30, 17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30, 13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30, 12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30, 6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30, 17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30, 4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30, 20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30, 19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30 ]; // Galois field log table var glog = [ 0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b, 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71, 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45, 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6, 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88, 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40, 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d, 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57, 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18, 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e, 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61, 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2, 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6, 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a, 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7, 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf ]; // Galios field exponent table var gexp = [ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1, 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce, 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54, 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41, 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09, 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16, 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00 ]; // Working buffers: // data input and ecc append, image working buffer, fixed part of image, run lengths for badness var strinbuf = [], eccbuf = [], qrframe = [], framask = [], rlens = []; // Control values - width is based on version, last 4 are from table. var version, width, neccblk1, neccblk2, datablkw, eccblkwid; var ecclevel = 2; // set bit to indicate cell in qrframe is immutable. symmetric around diagonal function setmask(x, y) { var bt; if (x > y) { bt = x; x = y; y = bt; } // y*y = 1+3+5... bt = y; bt *= y; bt += y; bt >>= 1; bt += x; framask[bt] = 1; } // enter alignment pattern - black to qrframe, white to mask (later black frame merged to mask) function putalign(x, y) { var j; qrframe[x + width * y] = 1; for (j = -2; j < 2; j++) { qrframe[(x + j) + width * (y - 2)] = 1; qrframe[(x - 2) + width * (y + j + 1)] = 1; qrframe[(x + 2) + width * (y + j)] = 1; qrframe[(x + j + 1) + width * (y + 2)] = 1; } for (j = 0; j < 2; j++) { setmask(x - 1, y + j); setmask(x + 1, y - j); setmask(x - j, y - 1); setmask(x + j, y + 1); } } //======================================================================== // Reed Solomon error correction // exponentiation mod N function modnn(x) { while (x >= 255) { x -= 255; x = (x >> 8) + (x & 255); } return x; } var genpoly = []; // Calculate and append ECC data to data block. Block is in strinbuf, indexes to buffers given. function appendrs(data, dlen, ecbuf, eclen) { var i, j, fb; for (i = 0; i < eclen; i++) strinbuf[ecbuf + i] = 0; for (i = 0; i < dlen; i++) { fb = glog[strinbuf[data + i] ^ strinbuf[ecbuf]]; if (fb != 255) /* fb term is non-zero */ for (j = 1; j < eclen; j++) strinbuf[ecbuf + j - 1] = strinbuf[ecbuf + j] ^ gexp[modnn(fb + genpoly[eclen - j])]; else for (j = ecbuf; j < ecbuf + eclen; j++) strinbuf[j] = strinbuf[j + 1]; strinbuf[ecbuf + eclen - 1] = fb == 255 ? 0 : gexp[modnn(fb + genpoly[0])]; } } //======================================================================== // Frame data insert following the path rules // check mask - since symmetrical use half. function ismasked(x, y) { var bt; if (x > y) { bt = x; x = y; y = bt; } bt = y; bt += y * y; bt >>= 1; bt += x; return framask[bt]; } //======================================================================== // Apply the selected mask out of the 8. function applymask(m) { var x, y, r3x, r3y; switch (m) { case 0: for (y = 0; y < width; y++) for (x = 0; x < width; x++) if (!((x + y) & 1) && !ismasked(x, y)) qrframe[x + y * width] ^= 1; break; case 1: for (y = 0; y < width; y++) for (x = 0; x < width; x++) if (!(y & 1) && !ismasked(x, y)) qrframe[x + y * width] ^= 1; break; case 2: for (y = 0; y < width; y++) for (r3x = 0, x = 0; x < width; x++, r3x++) { if (r3x == 3) r3x = 0; if (!r3x && !ismasked(x, y)) qrframe[x + y * width] ^= 1; } break; case 3: for (r3y = 0, y = 0; y < width; y++, r3y++) { if (r3y == 3) r3y = 0; for (r3x = r3y, x = 0; x < width; x++, r3x++) { if (r3x == 3) r3x = 0; if (!r3x && !ismasked(x, y)) qrframe[x + y * width] ^= 1; } } break; case 4: for (y = 0; y < width; y++) for (r3x = 0, r3y = ((y >> 1) & 1), x = 0; x < width; x++, r3x++) { if (r3x == 3) { r3x = 0; r3y = !r3y; } if (!r3y && !ismasked(x, y)) qrframe[x + y * width] ^= 1; } break; case 5: for (r3y = 0, y = 0; y < width; y++, r3y++) { if (r3y == 3) r3y = 0; for (r3x = 0, x = 0; x < width; x++, r3x++) { if (r3x == 3) r3x = 0; if (!((x & y & 1) + !(!r3x | !r3y)) && !ismasked(x, y)) qrframe[x + y * width] ^= 1; } } break; case 6: for (r3y = 0, y = 0; y < width; y++, r3y++) { if (r3y == 3) r3y = 0; for (r3x = 0, x = 0; x < width; x++, r3x++) { if (r3x == 3) r3x = 0; if (!(((x & y & 1) + (r3x && (r3x == r3y))) & 1) && !ismasked(x, y)) qrframe[x + y * width] ^= 1; } } break; case 7: for (r3y = 0, y = 0; y < width; y++, r3y++) { if (r3y == 3) r3y = 0; for (r3x = 0, x = 0; x < width; x++, r3x++) { if (r3x == 3) r3x = 0; if (!(((r3x && (r3x == r3y)) + ((x + y) & 1)) & 1) && !ismasked(x, y)) qrframe[x + y * width] ^= 1; } } break; } return; } // Badness coefficients. var N1 = 3, N2 = 3, N3 = 40, N4 = 10; // Using the table of the length of each run, calculate the amount of bad image // - long runs or those that look like finders; called twice, once each for X and Y function badruns(length) { var i; var runsbad = 0; for (i = 0; i <= length; i++) if (rlens[i] >= 5) runsbad += N1 + rlens[i] - 5; // BwBBBwB as in finder for (i = 3; i < length - 1; i += 2) if (rlens[i - 2] == rlens[i + 2] && rlens[i + 2] == rlens[i - 1] && rlens[i - 1] == rlens[i + 1] && rlens[i - 1] * 3 == rlens[i] // white around the black pattern? Not part of spec && (rlens[i - 3] == 0 // beginning || i + 3 > length // end || rlens[i - 3] * 3 >= rlens[i] * 4 || rlens[i + 3] * 3 >= rlens[i] * 4) ) runsbad += N3; return runsbad; } // Calculate how bad the masked image is - blocks, imbalance, runs, or finders. function badcheck() { var x, y, h, b, b1; var thisbad = 0; var bw = 0; // blocks of same color. for (y = 0; y < width - 1; y++) for (x = 0; x < width - 1; x++) if ((qrframe[x + width * y] && qrframe[(x + 1) + width * y] && qrframe[x + width * (y + 1)] && qrframe[(x + 1) + width * (y + 1)]) // all black || !(qrframe[x + width * y] || qrframe[(x + 1) + width * y] || qrframe[x + width * (y + 1)] || qrframe[(x + 1) + width * (y + 1)])) // all white thisbad += N2; // X runs for (y = 0; y < width; y++) { rlens[0] = 0; for (h = b = x = 0; x < width; x++) { if ((b1 = qrframe[x + width * y]) == b) rlens[h]++; else rlens[++h] = 1; b = b1; bw += b ? 1 : -1; } thisbad += badruns(h); } // black/white imbalance if (bw < 0) bw = -bw; var big = bw; var count = 0; big += big << 2; big <<= 1; while (big > width * width) big -= width * width, count++; thisbad += count * N4; // Y runs for (x = 0; x < width; x++) { rlens[0] = 0; for (h = b = y = 0; y < width; y++) { if ((b1 = qrframe[x + width * y]) == b) rlens[h]++; else rlens[++h] = 1; b = b1; } thisbad += badruns(h); } return thisbad; } function genframe(instring) { var x, y, k, t, v, i, j, m; // find the smallest version that fits the string t = instring.length; version = 0; do { version++; k = (ecclevel - 1) * 4 + (version - 1) * 16; neccblk1 = eccblocks[k++]; neccblk2 = eccblocks[k++]; datablkw = eccblocks[k++]; eccblkwid = eccblocks[k]; k = datablkw * (neccblk1 + neccblk2) + neccblk2 - 3 + (version <= 9); if (t <= k) break; } while (version < 40); // FIXME - insure that it fits insted of being truncated width = 17 + 4 * version; // allocate, clear and setup data structures v = datablkw + (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2; for (t = 0; t < v; t++) eccbuf[t] = 0; strinbuf = instring.slice(0); for (t = 0; t < width * width; t++) qrframe[t] = 0; for (t = 0; t < (width * (width + 1) + 1) / 2; t++) framask[t] = 0; // insert finders - black to frame, white to mask for (t = 0; t < 3; t++) { k = 0; y = 0; if (t == 1) k = (width - 7); if (t == 2) y = (width - 7); qrframe[(y + 3) + width * (k + 3)] = 1; for (x = 0; x < 6; x++) { qrframe[(y + x) + width * k] = 1; qrframe[y + width * (k + x + 1)] = 1; qrframe[(y + 6) + width * (k + x)] = 1; qrframe[(y + x + 1) + width * (k + 6)] = 1; } for (x = 1; x < 5; x++) { setmask(y + x, k + 1); setmask(y + 1, k + x + 1); setmask(y + 5, k + x); setmask(y + x + 1, k + 5); } for (x = 2; x < 4; x++) { qrframe[(y + x) + width * (k + 2)] = 1; qrframe[(y + 2) + width * (k + x + 1)] = 1; qrframe[(y + 4) + width * (k + x)] = 1; qrframe[(y + x + 1) + width * (k + 4)] = 1; } } // alignment blocks if (version > 1) { t = adelta[version]; y = width - 7; for (;;) { x = width - 7; while (x > t - 3) { putalign(x, y); if (x < t) break; x -= t; } if (y <= t + 9) break; y -= t; putalign(6, y); putalign(y, 6); } } // single black qrframe[8 + width * (width - 8)] = 1; // timing gap - mask only for (y = 0; y < 7; y++) { setmask(7, y); setmask(width - 8, y); setmask(7, y + width - 7); } for (x = 0; x < 8; x++) { setmask(x, 7); setmask(x + width - 8, 7); setmask(x, width - 8); } // reserve mask-format area for (x = 0; x < 9; x++) setmask(x, 8); for (x = 0; x < 8; x++) { setmask(x + width - 8, 8); setmask(8, x); } for (y = 0; y < 7; y++) setmask(8, y + width - 7); // timing row/col for (x = 0; x < width - 14; x++) if (x & 1) { setmask(8 + x, 6); setmask(6, 8 + x); } else { qrframe[(8 + x) + width * 6] = 1; qrframe[6 + width * (8 + x)] = 1; } // version block if (version > 6) { t = vpat[version - 7]; k = 17; for (x = 0; x < 6; x++) for (y = 0; y < 3; y++, k--) if (1 & (k > 11 ? version >> (k - 12) : t >> k)) { qrframe[(5 - x) + width * (2 - y + width - 11)] = 1; qrframe[(2 - y + width - 11) + width * (5 - x)] = 1; } else { setmask(5 - x, 2 - y + width - 11); setmask(2 - y + width - 11, 5 - x); } } // sync mask bits - only set above for white spaces, so add in black bits for (y = 0; y < width; y++) for (x = 0; x <= y; x++) if (qrframe[x + width * y]) setmask(x, y); // convert string to bitstream // 8 bit data to QR-coded 8 bit data (numeric or alphanum, or kanji not supported) v = strinbuf.length; // string to array for (i = 0; i < v; i++) eccbuf[i] = strinbuf.charCodeAt(i); strinbuf = eccbuf.slice(0); // calculate max string length x = datablkw * (neccblk1 + neccblk2) + neccblk2; if (v >= x - 2) { v = x - 2; if (version > 9) v--; } // shift and repack to insert length prefix i = v; if (version > 9) { strinbuf[i + 2] = 0; strinbuf[i + 3] = 0; while (i--) { t = strinbuf[i]; strinbuf[i + 3] |= 255 & (t << 4); strinbuf[i + 2] = t >> 4; } strinbuf[2] |= 255 & (v << 4); strinbuf[1] = v >> 4; strinbuf[0] = 0x40 | (v >> 12); } else { strinbuf[i + 1] = 0; strinbuf[i + 2] = 0; while (i--) { t = strinbuf[i]; strinbuf[i + 2] |= 255 & (t << 4); strinbuf[i + 1] = t >> 4; } strinbuf[1] |= 255 & (v << 4); strinbuf[0] = 0x40 | (v >> 4); } // fill to end with pad pattern i = v + 3 - (version < 10); while (i < x) { strinbuf[i++] = 0xec; // buffer has room if (i == x) break; strinbuf[i++] = 0x11; } // calculate and append ECC // calculate generator polynomial genpoly[0] = 1; for (i = 0; i < eccblkwid; i++) { genpoly[i + 1] = 1; for (j = i; j > 0; j--) genpoly[j] = genpoly[j] ? genpoly[j - 1] ^ gexp[modnn(glog[genpoly[j]] + i)] : genpoly[j - 1]; genpoly[0] = gexp[modnn(glog[genpoly[0]] + i)]; } for (i = 0; i <= eccblkwid; i++) genpoly[i] = glog[genpoly[i]]; // use logs for genpoly[] to save calc step // append ecc to data buffer k = x; y = 0; for (i = 0; i < neccblk1; i++) { appendrs(y, datablkw, k, eccblkwid); y += datablkw; k += eccblkwid; } for (i = 0; i < neccblk2; i++) { appendrs(y, datablkw + 1, k, eccblkwid); y += datablkw + 1; k += eccblkwid; } // interleave blocks y = 0; for (i = 0; i < datablkw; i++) { for (j = 0; j < neccblk1; j++) eccbuf[y++] = strinbuf[i + j * datablkw]; for (j = 0; j < neccblk2; j++) eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))]; } for (j = 0; j < neccblk2; j++) eccbuf[y++] = strinbuf[(neccblk1 * datablkw) + i + (j * (datablkw + 1))]; for (i = 0; i < eccblkwid; i++) for (j = 0; j < neccblk1 + neccblk2; j++) eccbuf[y++] = strinbuf[x + i + j * eccblkwid]; strinbuf = eccbuf; // pack bits into frame avoiding masked area. x = y = width - 1; k = v = 1; // up, minus /* inteleaved data and ecc codes */ m = (datablkw + eccblkwid) * (neccblk1 + neccblk2) + neccblk2; for (i = 0; i < m; i++) { t = strinbuf[i]; for (j = 0; j < 8; j++, t <<= 1) { if (0x80 & t) qrframe[x + width * y] = 1; do { // find next fill position if (v) x--; else { x++; if (k) { if (y != 0) y--; else { x -= 2; k = !k; if (x == 6) { x--; y = 9; } } } else { if (y != width - 1) y++; else { x -= 2; k = !k; if (x == 6) { x--; y -= 8; } } } } v = !v; } while (ismasked(x, y)); } } // save pre-mask copy of frame strinbuf = qrframe.slice(0); t = 0; // best y = 30000; // demerit // for instead of while since in original arduino code // if an early mask was "good enough" it wouldn't try for a better one // since they get more complex and take longer. for (k = 0; k < 8; k++) { applymask(k); // returns black-white imbalance x = badcheck(); if (x < y) { // current mask better than previous best? y = x; t = k; } if (t == 7) break; // don't increment i to a void redoing mask qrframe = strinbuf.slice(0); // reset for next pass } if (t != k) // redo best mask - none good enough, last wasn't t applymask(t); // add in final mask/ecclevel bytes y = fmtword[t + ((ecclevel - 1) << 3)]; // low byte for (k = 0; k < 8; k++, y >>= 1) if (y & 1) { qrframe[(width - 1 - k) + width * 8] = 1; if (k < 6) qrframe[8 + width * k] = 1; else qrframe[8 + width * (k + 1)] = 1; } // high byte for (k = 0; k < 7; k++, y >>= 1) if (y & 1) { qrframe[8 + width * (width - 7 + k)] = 1; if (k) qrframe[(6 - k) + width * 8] = 1; else qrframe[7 + width * 8] = 1; } return qrframe; } var _canvas = null; var api = { get ecclevel() { return ecclevel; }, set ecclevel(val) { ecclevel = val; }, get size() { return _size; }, set size(val) { _size = val }, get canvas() { return _canvas; }, set canvas(el) { _canvas = el; }, getFrame: function (string) { return genframe(string); }, //这里的utf16to8(str)是对Text中的字符串进行转码,让其反对中文 utf16to8: function (str) { var out, i, len, c; out = ""; len = str.length; for (i = 0; i < len; i++) { c = str.charCodeAt(i); if ((c >= 0x0001) && (c <= 0x007F)) { out += str.charAt(i); } else if (c > 0x07FF) { out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F)); out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F)); out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); } else { out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F)); out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); } } return out; }, /** * 新增$this参数,传入组件的this,兼容在组件中生成 */ draw: function (str, canvas, cavW, cavH, $this, cb = function () {}, ecc) { var that = this; ecclevel = ecc || ecclevel; canvas = canvas || _canvas; if (!canvas) { console.warn('No canvas provided to draw QR code in!') return; } var size = Math.min(cavW, cavH); str = that.utf16to8(str); //减少中文显示 var frame = that.getFrame(str), // 组件中生成qrcode须要绑定this ctx = wx.createCanvasContext(canvas, $this), px = Math.round(size / (width + 8)); var roundedSize = px * (width + 8), offset = Math.floor((size - roundedSize) / 2); size = roundedSize; //ctx.clearRect(0, 0, cavW, cavW); ctx.setFillStyle('#ffffff') ctx.fillRect(0, 0, cavW, cavW); ctx.setFillStyle('#000000'); for (var i = 0; i < width; i++) { for (var j = 0; j < width; j++) { if (frame[j * width + i]) { ctx.fillRect(px * (4 + i) + offset, px * (4 + j) + offset, px, px); } } } //--减少绘制实现回调 ctx.draw(false, function () { cb(); }) } } module.exports = { api }})();

April 25, 2022 · 22 min · jiezi

关于微信小程序:微信小程序上滑加载下一页

首先写了个公共办法publicNextPage,因为别的页面可能也须要上滑加载下一页,所以封装了一下,先引入const { publicNextPage } = require('../../util/public.js')而后页面里监听页面滚动到底部 onReachBottom() { publicNextPage( this.data.pageIndex, this.data.pageCount, (newPageIndex)=>{ if(newPageIndex){ this.getList(this.data.pageSize, newPageIndex) this.setData({ pageIndex:newPageIndex }) }else{ console.log('曾经是最初一页!'); } }) }更新参数后申请列表getList(pageSize,pageIndex) { let param = { pageSize, pageIndex } myAjax('getList', 'POST', param, (res) => { if (res.list) { let newList = this.data.list.concat(res.list) // 连贯数组 this.setData({ list:newList, pageCount:res.pageCount }) } })}publicNextPage办法如下:export const publicNextPage = (pageIndex, pageCount, cb) => { pageIndex++ if (pageIndex < pageCount) { cb(pageIndex) } else { cb() }}

April 25, 2022 · 1 min · jiezi

关于微信小程序:微信小程序用腾讯地图计算距离

首先引入地图var QQMapWX = require('../../libs/qqmap/qqmap-wx-jssdk1.2/qqmap-wx-jssdk');var qqmapsdk;qqmapsdk = new QQMapWX({ key: '填申请的key'});从接口取得列表list后,往目的地数组push值 let destinations = [];for (var i = 0; i < list.length; i++) { destinations.push({ location: { lat: list[i].lat, lng: list[i].lng } })}而后应用地图接口来计算间隔 let self = this;qqmapsdk.calculateDistance({ from: { latitude: userLocation.lat, longitude: userLocation.lng }, // 从以后用户的定位算 to: destinations, success: (res) => { let elements = res.result.elements; let box = []; for (let x = 0; x < elements.length; x++) { let distance; if (elements[x].distance >= 1000) { distance = (elements[x].distance / 1000) + 'km'; } else { distance = parseInt(elements[x].distance) + 'm'; } box.push({ id: list[x].id, ... // 其余属性(略) distance: distance }) }; self.setData({ list: box }) }, fail: function (failRes) {}, complete: function (completeRes) {} })

April 25, 2022 · 1 min · jiezi

关于微信小程序:微信小程序热启动监听

有的业务须要监听热启动,比方,当再次关上小程序时,从新获取用户的实时定位 首先须要在app.js里写个自定义监听器,就叫watch好了,watch对象须要监听该页面data的变动,当data变动,就调用watch办法,代码如下: watch: function (watchBack) { let obj = this.globalData; Object.defineProperty(obj, "appShow", { configurable: true, enumerable: true, set: function (value) { watchBack(value); }, get: function () { return this.appShow } }) },当然,要在app.js的对应办法里更新appShow onShow() { this.globalData.appShow = true }, onHide() { this.globalData.appShow = false }在须要更新定位的页面生命周期onLoad办法中调用该watch办法getApp().watch(this.watchBack)本页面的watchBack办法如下: watchBack(appShow) { if (appShow) { // 一旦热启动,就更新以后地位 getUserLocationFunc().then(res => { this.setData({ userLocation: res }) }) } }题外话:这里留神,小程序取得用户以后定位须要肯定的工夫,尽管很短暂,但同样是异步的,所以getUserLocationFunc办法返回promise对象,该办法是引入的公共办法 const { getUserLocationFunc } = require('../../util/public.js')代码如下: ...

April 25, 2022 · 1 min · jiezi

关于微信小程序:微信小程序用云函数获取绑定的手机号

首先,在页面里写个获取手机号的专用button,(这是小程序官网规定的) <button class="btn-sure" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">点击获取手机号</button>而后在该页面同目录的js文件写对应办法:getPhoneNumber(e) { let self = this; wx.cloud.callFunction({ name: 'getMobileNumber', data: { code: e.detail.code, // 根底库最低2.21.2,否则获取不到 } }).then(res => { self.setData({ userPhoneNumber: res.result.phoneInfo.phoneNumber }) }) },在cloudfunctions文件夹上右键新建云函数getMobileNumber,如下图其中,config.json的内容如下:{ "permissions": { "openapi": [ "templateMessage.send" ] }}index.js的内容如下: const cloud = require('wx-server-sdk')// cloud.init() cloud.init({ env: '云函数的环境id' // 传不传都行,app.js里曾经配置过了的})exports.main = async (event, context) => { const phoneResult = await cloud.openapi.phonenumber.getPhoneNumber({code:event.code}) return phoneResult}package.json的内容是生成的,大抵如下: { "name": "getMobileNumber", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "wx-server-sdk": "~2.6.1" }}app.js的配置如下: ...

April 25, 2022 · 1 min · jiezi

关于微信小程序:微信小程序wxrequest的简单封装

在理论开发中,前端须要跟后端约定HTTP申请头,这就须要对wx.request进行简略的封装 首先在util工具文件夹下新建ajax.js其中内容: export const myAjax = (url,method,param,cb) => { let baseUrl = 'https://dev.xxxx.com:8090/'; // 申请地址,8090是跟后端约定好的端口号 let header = { "sessionCode": wx.getStorageSync("sessionCode"), "content-type": "application/json" } if(url == 'login' || url == 'register'){ header = { "content-type": "application/json" } // 登录和注册的时候,不必在header里传sessionCode } wx.request({ url: baseUrl + url, method, data: param, header, dataType: 'json', success: function (res) { if( res.data.code == 200 ){ // 返回正确回调 cb(res.data); }else{ if(res.data.code == -1){ // 无论在哪个页面未登录,都应用公共登录办法 publicLogin(()=>{ // 公共登录回调 myAjaxPost(url,param,cb); }); }else{ // 提醒弹框 wx.showModal({ title: '提醒!', confirmText: '确定', showCancel: false, content: res.data.msg ?? '', success: (res) => { if (res.confirm) { } } }) } } }, fail: function (err) {}})}页面援用首先在须要应用的页面引入该js文件 ...

April 25, 2022 · 1 min · jiezi

关于微信小程序:家政小程序有什么优势

 随着人们生存程度和品质要求的一直进步,对服务的市场需求越来越大,很多服务行业也因而失去了疾速倒退。家政类正是其中的一个行业代表,以前咱们常常会在58、同城类站点上看到家政入驻的身影,到当初家政小程序也越来越多,那么家政服务做小程序有什么劣势吗? 家政小程序的劣势 1、开发成本低 除了小程序后期的开发费用,在上线后的经营中简直没有其他费用。用户间接进入小程序下单,产生的每笔交易都不须要向第三方平台领取佣金或手续费,利润率得以进步,对商家来说性价比更高。 2、提高效率 雇主与服务人员间接对接,流程简化,解决信息不对称的问题,无效、疾速实现单方需要。同时预约等性能让单方的工夫利用更高效,有利于进步收益。 3、用户体验好 家政小程序能够将服务进行分类,包含保洁、搬家、保姆、培修等,对于用户来说可能方便快捷的找到本人须要的服务,从需要到下单只有极短几步门路就能实现,用户体验更好。 4、促成待业 通过一个标准的平台让家政行业的市场雇佣关系公正化和透明化,为服务人员提供了更加宽泛的就业机会,有利于保护一个衰弱良好的市场秩序。 5、搭建私域 以往商家入驻其余平台,产生的流量都属于平台,一旦平台下架服务商品,商家就什么信息也没有了,更别谈留存和复购了。小程序的呈现能帮忙商家积攒“留量”市场,通过好的服务将用户留在本人的流量池了,而不是只是借助小程序社交属性去产生更多的增量留量。 小程序的飞速发展带给各行各业新的商机,帮忙商家盘活线上流量。如果还抱着传统守店待客的经营思路,始终无奈实现线上转型,只会散失更多的用户流量。小程序具备易触达、营销功能强大、开发周期短等特点,可能帮忙家政企业建立优质品牌形象,解决获客和营销的痛点!

April 15, 2022 · 1 min · jiezi

关于微信小程序:腾讯首发私域榜单展现小程序的私域力量

 4月11日,腾讯智慧批发团队首次公布《腾讯智慧批发T+品牌私域价值榜》(以下简称榜单),这是腾讯第一次公布也是业内首个综合掂量品牌私域经营情况的年度价值榜单。旨在帮忙品牌商家找到行业对标和增长空间,进一步助力批发实体经济倒退。 自2020年以来,受疫情重复影响,线下商家纷纷摒弃“守店待客+传统电商平台”的旧营销模式,转头借助数字化工具发动线上“自救”。私域经济体的影响力在一直壮大,重构线上线下一体化、全景化私域经营的改革浪潮已全面来袭。腾讯正是出于私域时代下企业的迫切转型需要,公布了《榜单》,本次榜单横跨十大行业,囊括了70+头部品牌,别离评比出“年度行业标杆”、 “年度飞跃标杆”、“年度四力标杆”三个子榜单,以下是榜单次要内容。 1、榜单解读 “年度行业标杆” “年度行业标杆”横跨10大重点垂直行业,以企业整体私域经营情况及四力(组织力、商品力、经营力、产品力)作为外围评审规范,对企业私域的综合竞争力进行评估。其中,企业私域经营情况和其私域范畴内销售规模及后劲相挂钩,为主观评判企业私域竞争力提供了无力根据。 “年度飞跃标杆” “年度飞跃标杆”是通过专家评审团进行综合判断,推选出2021年企业入门私域快速增长,且在私域经营获得显著冲破的十佳品牌。 “年度四力标杆” “年度四力标杆” 则专一于在私域经营“四力模型”单项能力评估,腾讯以2021四力平台商家评级后果为判断根据,依据入围品牌在私域经营“四力模型”单项能力 (组织力、商品力、经营力、产品力),每个单项有5个品牌怀才不遇。 2、小程序成私域必备基建 值得一提的是,除了榜单自身,腾讯智慧批发联手经济观察报还集结了来自产业一线、创投征询、学术研究、媒体察看等多领域专家,发动了主题为“新空间 新增长 新引擎”的智慧批发翻新研讨会,从宏观经济、消费市场以及品牌数字化倒退等角度,针对美妆日化、服装、3C、商超生鲜、餐饮等多个垂直行业进行了私域倒退研究,为行业提供前瞻性指引。 腾讯指出私域成为企业数字化的最轻量级入口,而企业想要实现私域,首先要赋能数字化加持,帮忙晋升企业对用户和消费者的连贯、触达效率以及由触达带来的销售转化效率。微信生态里的小程序、公众号、企业微信、视频号等等则成为承接并包容私域用户的无效工具和载体,其中,布局微信小程序成果十分显著,通过搭配企业微信+社群等生态产品联结经营,搭建小程序矩阵,从商城、本地门店、会员、试用等多维度进行精细化经营,让用户可能精准地找到对应的性能小程序。据腾讯披露,2021年,小程序的日活冲破4.5亿,商家自营的实物交易额同比翻倍,批发、餐饮和游览小程序交易额同比增长超100%。这些数据表明,扎根于微信的私域新业态已成为越来越多的品牌商家寻求转型、增长的重要阵地。 私域用户池、私域“门店”这些私域基础设施的建设,成为每个企业面对数字化转型的必做功课。腾讯智慧批发市场副总裁常越认为,这 2年是中国私域倒退的要害基建年,如果企业不做好私域基建,将来大概率会落后于竞争对手,建设私域曾经成为关乎企业生存倒退的“必答题”。当初这道题,你开始做了吗?

April 14, 2022 · 1 min · jiezi

关于微信小程序:微信小程序项目中使用iconfont步骤流程Font-class方式

本文记录一下在小程序我的项目中应用iconfont-阿里巴巴矢量图标库的步骤流程,忘了时候能够看看第一步,拜访网站并登录网站地址:https://www.iconfont.cn/登录(注册)略过... 第二步,搜寻所需图标,并退出购物车图一: 图二: 图三: 图四: 第三步,抉择Font class模式,并生成代码图一: 图二: 图三: 第四步,将生成的代码粘贴到文件目录中去 第五步,全局引入图标款式代码 第六步,应用即可图一应用: 图二效果图: 留神,图标的名字是在阿里iconfont那边,如下图:

April 11, 2022 · 1 min · jiezi