- 小程序资讯相关类目迭代更新
各位小程序开发者, 当前平台有较多资讯展示相关类目。为优化开发者选择类目体验,现拟定合并资讯相关类目为【资讯-信息资讯】,如小程序主要提供单一行业信息展示服务,请选择【资讯-信息资讯】类目,资质要求为《非经营性互联网信息服务备案核准》。 [图片] 以上调整仅针对国内非个人主体生效,本次类目迭代将于 2022 年 7 月 12 日生效。 微信团队 2022年7月4日
2023-09-26 - 个人主体未开放类目修改指引说明
代码审核环节,将会对小程序运营的内容与所选类目是否相符进行核实,当小程序涉及提供信息资讯服务,属于个人主体未开放服务类目,建议申请企业主体小程序,补充【资讯-信息资讯服务】类目合规提审,否则代码审核环节将面临因类目不符被驳回情形。 二、应用场景示例与整改指引: 信息资讯服务:属于个人主体未开放服务类目。 示例: [图片] 整改建议(2选1): 1、申请企业主体小程序,补充【资讯-信息资讯服务】类目后合规提审。 2、或自查代码,确保移除信息资讯服务等内容及相关分类标签。 本文档为信息资讯服务相关介绍说明,如存在上述问题应及时调整、修整,避免后续存在上诉问题审核失败;若仍有其他疑惑,可以通过以下咨询入口反馈: 1、微信开放社区-交流专区-小程序发帖咨询-提出问题-运营相关问题 2、代码审核驳回站内信通知-客服咨询入口(客服咨询入口目前正在测试开放阶段,若无客服入口,建议前往开放社区发帖咨询) 我们会根据新出现的问题、相关法律法规更新或产品运营的需要及时对其内容进行修改并更新,制定新的规则,保证微信用户的体验。建议开发者反复查看以便获得最新信息,定期了解更新情况。
2022-08-19 - 社区每周|Mac小程序公测、模板消息调整、云开发等能力升级与社区每周反馈(12.30-01.03)
各位微信开发者: 以下是Mac 版小程序开发者公测、模板消息能力调整说明、云开发相关功能更新、“小程序助手”性能分析功能升级、商品数据接入(内测)及上周小程序相关能力更新及我们在社区收到的问题反馈、需求的处理进度,希望同大家一同打造小程序生态。 微信 Mac 版小程序开发者公测微信 Mac 版新版本中,支持打开聊天中分享的小程序,开发者可下载安装微信 Mac 版公测版本进行体验和适配。 最新版微信开发者工具新增支持在微信 Mac 版中预览小程序和进行真机调试,详情请查看《Mac小程序开发说明》。 微信 Mac 版公测版:点击下载微信开发者工具:点击下载 关于小程序模板消息能力调整说明原计划2020年1月10日下线小程序模板消息能力,由于部分开发者反馈尚未完全将模板消息切换为订阅消息,为降低业务影响,现做如下调整: 下调模板消息接口日调用额度,2020年1月10日起(含1月10日),未开通支付能力的帐号调至5万/日,已开通支付能力的帐号调至50万/日2020年1月10日24:00以后,新发布的小程序,只能使用订阅消息,在该时间点之前发布的小程序仍然可以使用模板消息。(回退的版本,按当前发布时间算)2020年4月10日24:00以后,所有版本的小程序都不能使用模板消息,请还未切换使用订阅消息的开发者,在此时间点前完成切换 周期性更新/数据预拉取支持从云开发环境中获取数据周期性更新能够在用户未打开小程序的情况下,也能从服务器提前拉取数据,当用户打开小程序时可以更快地渲染页面,减少用户等待时间,增强在弱网条件下的可用性。目前,系统已支持从云开发环境中获取数据,并将数据下载到本地。开发者可登录小程序 MP 管理后台,进入设置->开发设置->数据周期性更新中进行配置。详情功能介绍请参考文档《周期性更新》。 [图片] 同时,小程序·云开发还支持数据预拉取功能,详细功能介绍请参考文档《数据预拉取》 商品数据接入(内测)商品数据目前应用于微信扫一扫识物、小程序商品搜索和扫条码三个功能。这些功能可以很好的满足微信用户对商品的信息获取诉求,同时也能为商家小程序带来曝光流量和建立用户品牌认知的机会。 商品数据接入方式请阅读《商品数据接入文档(内测)》。 服务平台新增AI、安全、地图等多项能力服务平台新增AI人脸检测、信息安全检查、地理位置、音乐资源等多项接口能力,帮助小程序开发者降低开发门槛、快速接入服务。可点击前往了解能力详情 [图片] “小程序助手”性能分析功能升级为了帮助小程序开发者分析性能数据并优化小程序体验,“小程序助手”升级了性能分析功能,新增启动性能、运行性能和网络性能等方面的数据,支持开发者监控小程序的基本性能指标。 [图片] 扫描下方小程序码即可立即体验: [图片] 上周问题反馈和处理进度(12.30-01.03) 已修复的问题微信更新到7.0.10之后, 安卓 wx.hideLoading 失效的问题 查看详情 小程序不能发布的问题 查看详情 微信开放平台 第三方平台代公众号授权突发异常授权失败,返回 system_error的问题 查看详情 发送模板消息超出限制的问题 查看详情 页面未找到 4.4 根据 OpenID 列表群发卡券消息的问题 查看详情 微信公众平台重复提示登录超时的问题 查看详情 编译提示cloud init error: Error: errCode: -1的问题 查看详情 2020年第一个BUG,排行版BUG,显示0月的问题 查看详情 安全接口报错 VM22379:1 cloud init error: Error: errCode 的问题 查看详情 文章模块MD样式错乱、插入图片展示很小的问题 查看详情 下个基础库修复开发者工具地图 marker anchorX 报错的问题 查看详情 picker 未点击确认前 columnChange 不触发的问题 查看详情 修复中的问题今天的开发者工具有种sublime的感觉的问题 查看详情 社区小程序不能回答,且“写回答”三个字位置固定的问题 查看详情 开发工具RC V1.02.1912261 wx.showModal 在开发工具上单行显示的问题 查看详情 发送订阅消息报错的问题 查看详情 wx.navigateBackMiniProgram() 安卓无效的问题 查看详情 创建SocketTask连接,session过期并断网,重连后,框架自动关闭的问题 查看详情 input 密码类型与 text 类型的 input 框的问题 查看详情 微信浏览器 原生 select 标签 点击不唤起下拉框的问题 查看详情 "jsserverRoot": "jsserver/"无法上传 checkInteractive 的问题 查看详情 SocketTask.onMessage 出现以下报错的问题 查看详情 为什么OPPO 华为某些机型登录微信小游戏出现黑屏现象的问题 查看详情 textarea 组件在2.10.0出现不支持的情况,无法显示多行输入的问题 查看详情 wx.getLocation在微信开发者工具里面调用成功,但预览、真机测试调用的时候安卓返回fail 的问题 查看详情 所有安卓 version7.0.10 版本保存图报错的问题 查看详情 小游戏2.10.0 copyFile 接口的问题 查看详情 使用最新调试基础库2.10.0,地图Map组件加载报错的问题 查看详情 微信7.0.10版本部分机型 select 点不了的问题 查看详情 banner广告内存问题问题 查看详情 荣耀play 微信版本更新到7.0.10 发现下拉框无法选择 查看详情 虚拟支付midas.getBalance接口报错 查看详情 开发者工具基础库2.10.0版本地图markers,报错的问题 查看详情 小游戏编译的时候出现错误的问题 查看详情 layaair 网络加载资源的问题的问题 查看详情 需求反馈需求评估中微信开发者工具中公众号收藏的链接有一个备注的需求 查看详情 建议小程序加个配置文件,用户共享配置的需求 查看详情 蓝牙发送数据API增加参数的需求 查看详情 小程序公众平台-开发-错误查询结果里显示时分秒的需求 查看详情 微信团队 2020.01.10
2020-01-10 - 社区每周 | PC小程序公测、云开发支持代开发、每周反馈(0729-0802)
各位微信开发者: 以下是新能力公测与更新公告、上周我们在社区收到的问题反馈与需求的处理进度,希望同大家一同打造小程序生态。 微信 PC 版小程序开发者公测 微信 PC 版新版本中,支持打开聊天中分享的小程序,开发者可下载安装微信 PC 版内测版本进行体验和适配。最新版微信开发者工具新增支持在微信 PC 版中预览小程序 查看详情 微信 PC 版内测版:点击下载 微信开发者工具:点击下载 开发者遇到问题,请在社区中发表标题包含「PC 小程序」的问答帖子反馈。 微信 Mac 版小程序也将在近期开启测试。 小程序·云开发支持第三方平台代开发 小程序·云开发目前已支持第三方平台代开发。第三方平台可在小程序权限集中勾选云开发管理权限,并通知小程序进行云开发权限集授权。授权完成后即可进行代开发,具体开发过程可参考第三方平台代开发 同时,为方便第三方平台进行代开发,云开发还提供了多种 API 接口,包括开通云开发、创建云环境以及创建云函数等。详见云开发接入指南 上周问题反馈和处理进度(07.29-08.02) 已修复的问题基础库2.8.0,iOS 下 video 组件同层渲染失效的问题 查看详情 修复中的问题自定义组件使用startBeaconDiscovery,uuids 五个以上,闪退的问题 查看详情 map 组件 bindregionchange 事件的问题 查看详情 工具目录树滑动时表现异常的问题 查看详情 需求反馈需求评估中 用 wx.request 发送带 PFX 证书和密码的请求 查看详情 浮窗关闭音频播放能监听的需求 查看详情 希望提供获取小程序内存使用情况的 API,以简化内存相关异常的排查流程 查看详情 小程序录音支持 PCM 格式的需求 查看详情 希望微信官方开放一个API:提供子组件获取父组件的实例对象 查看详情 camera 组件变焦的需求 查看详情 onCameraFrame 可以调整获取图片的频率吗的需求 查看详情 关于 swiper 组件动态添加 item 的需求 查看详情 强烈建议官方为小程序增加 table 组件 查看详情 官方版本的 jweixin SDK 的需求 查看详情 wx.previewImage 查看大图限制保存或获取用户点击保存事件回调的需求 查看详情 第三方平台,绑定小程序客服接口的需求 查看详情 地图缩放操作时 data 里面的 scale 可否同步更新的需求 查看详情 用 wx.request 发送带 PFX 证书和密码的请求 查看详情 浮窗关闭音频播放能监听的需求 查看详情 希望提供获取小程序内存使用情况的 API,以简化内存相关异常的排查流程 查看详情 小程序录音支持 PCM 格式的需求 查看详情 希望微信官方开放一个API:提供子组件获取父组件的实例对象 查看详情 camera 组件变焦的需求 查看详情 onCameraFrame 可以调整获取图片的频率吗的需求 查看详情 关于 swiper 组件动态添加 item 的需求 查看详情 强烈建议官方为小程序增加 table 组件 查看详情 官方版本的 jweixin SDK 的需求 查看详情 wx.previewImage 查看大图限制保存或获取用户点击保存事件回调的需求 查看详情 第三方平台,绑定小程序客服接口的需求 查看详情 地图缩放操作时 data 里面的 scale 可否同步更新的需求 查看详情 微信团队 2019.08.09
2019-08-09 - 订阅消息如果选择选择‘总是保持以上选择,"不再询问"后的设置问题
目前是选择‘总是保持以上选择,"不再询问"后,可以在设置中开启或拒绝接收,但不会再次拉起授权弹窗
2019-10-18 - 小程序代码包总包上限提升至12M、新增内置扩展库支持
小程序代码包总包上限提升至12M为了让开发者开发出功能更丰富的小程序,小程序或小游戏代码包总包上限由8M提升到12M。建议开发者优化小程序性能并将每个分包做得尽可能小,以便提升用户的打开速度,优化用户体验。 开发者可登录开发者工具,在详情-项目配置中点击刷新按钮,获取最新的配置信息。 [图片] 内置扩展库支持扩展库是将官方提供的一系列扩展能力打包而成的一些类库。为方便开发者使用,我们在最新的nightly版开发者工具支持了内置扩展库,开发者只需在app.json配置文件声明引用指定扩展库即可,无需自行引入相关 npm 包且不计入小程序代码包大小,目前支持了kbone和WeUI两种扩展库,更多详情请参考文档。 欢迎各位开发者接入,如有问题,可在本帖下方留言或在社区发帖反馈。 微信团队 2019.11.22
2019-11-22 - Wxml2Canvas -- 快速生成小程序分享图通用方案
Wxml2Canvas库,可以将指定的wxml节点直接转换成canvas元素,并且保存成分享图,极大地提升了绘制分享图的效率。目前被应用于微信游戏圈、王者荣耀、刺激战场助手等小程序中。 github地址:https://github.com/wg-front/wxml2canvas 一、背景 随着小程序应用的日渐成熟,多处场景需要能够生成分享图便于用户进行二次传播,从而提升小程序的传播率以及加强品牌效应。 对于简单的分享图,比如固定大小的背景图加几行简短文字构成的分享小图,我们可以利用官方提供的canvas接口将元素直接绘制, 虽然繁琐了些,但能满足基本要求。 对于复杂的分享图,比如用户在微信游戏圈发表完话题后,需要将图文混排的富文本内容生成分享图,对于这种长度不定,内容动态变化的图片生成需求,直接利用官方的canvas接口绘制是十分困难的,包括但不限于文字换行、表情文字图片混排、文字加粗、子标题等元素都需要一一绘制。又如王者荣耀助手小程序,需要将十人对局的详细战绩绘制成分享图,包含英雄数据、装备、技能、对局结果等信息,要绘制100多张图片和大量的文字信息,如果依旧使用官方的接口一步一步绘制,对开发者来说简直就是一场噩梦。我们急需一种通用、高效的方式完成上述的工作。 在这样的背景下,wxml2cavnas诞生了,作为一种分享图绘制的通用方案,它不仅能快速的绘制简单的固定小图,还能直接将wxml元素真实地转换成canvas元素,并且适配各种机型。无论是复杂的图文混排的富文本内容,还是展现形式多样的战绩结果页,都可以利用wxml2cavnas完美地快速绘制并生成所期望的分享图片。 二、Wxml2Canvas介绍及示例 1. 介绍 Wxml2Cavnas库,是一个生成小程序分享图的通用方案,提供了两种绘制方式: 封装基础图形的绘制接口,包括矩形、圆形、线条、图片、圆角图片、纯文本等,使用时只需要声明元素类型并提供关键数据即可,不需要再关注canvas的具体绘制过程; wxml直接转换成canvas元素,使用时传入待绘制的wxml节点的class类名,并且声明绘制此节点的类型(图片、文字等),会自动读取此节点的computedStyle,利用这些数据完成元素的绘制。 2. 生成图示例 下面是两张极端复杂的分享图。 2.1 游戏圈话题 [图片] 点击查看完整长图 2.2.2 王者荣耀战绩 [图片] 点击查看完整大图 三、小程序的特性及局限 小程序提供了如下特性,可供我们便捷使用: measureText接口能直接测量出文本的宽度; SelectorQuery可以查询到节点对应的computedStyle。 利用第一条,我们在绘制超长文本时便于文本的省略或者换行,从而避免文字溢出。 利用第二条,我们可以根据class类名,直接拿到节点的样式,然后将style转换成canvas可识别的内容。 但是和html的canvas相比,小程序的canvas局限性很多。主要体现在如下几点: 不支持base64图片; 图片必须下载到本地后才能绘制到画布上; 图片域名需要在管理平台加入downFile安全域名; canvas属于原生组件,在移动端会置于最顶层; 通过SelectorQuery只能拿到节点的style,而无法获取文本节点的内容以及图片节点的链接。 针对以上问题,我们需要将base64图片转换jpg或png格式的图片,实现图片的统一下载逻辑,并且离屏绘制内容。针对第五条,好在SelectorQuery可以获取到节点的dataset属性,所以我们需要在待绘制的节点上显示地声明其类型(imgae、text等),并且显示地传入文本内容或图片链接,后文会有示例。 四、Wxml2Canvas使用方式 1. 初始化 首先在wxml中创建canvas节点,指定宽高: [代码] <canvas canvas-id="share" style="height: {{ height * zoom }}px; width: {{ width * zoom }}px;"> </canvas> [代码] 引入代码库,创建DrawImage实例,并传入如下参数: [代码] let DrawImage = require('./wxml2canvas/index.js'); let zoom = this.device.windowWidth / 375; let width = 375; let height = width * 3; let drawImage = new DrawImage({ element: 'share', // canvas节点的id, obj: this, // 在组件中使用时,需要传入当前组件的this width: width, // 宽高 height: height, background: '#161C3A', // 默认背景色 gradientBackground: { // 默认的渐变背景色,与background互斥 color: ['#17326b', '#340821'], line: [0, 0, 0, height] }, progress (percent) { // 绘制进度 }, finish (url) { // 画完后返回url }, error (res) { console.log(res); // 画失败的原因 } }); [代码] 所有的数字参数均以iphone6为基准,其中参数width和height决定了canvas画布的大小,规定值是在iphone6机型下的固定数值; zoom参数的作用是控制画布的缩放比例,如果要求画布自适应,则应传入 windowWidth / 375,windowWidth为手机屏幕的宽度。 2. 传入数据,生成图片 执行绘制操作: [代码] drawImage.draw(data, this); [代码] 执行绘制时需要传入数据data,数据的格式分为两种,下面展开介绍。 2.1 基础图形 第一种为基础的图形、图文绘制,直接使用官方提供接口,下面代码是一个基本的格式: [代码] let data = { list: [{ type: 'image', url: 'https://xxx', class: 'background_image', // delay: true, x: 0, y: 0, style: { width: width, height: width } }, { type: 'text', text: '文字', class: 'title', x: 0, y: 0, style: { fontSize: 14, lineHeight: 20, color: '#353535', fontFamily: 'PingFangSC-Regular' } }] } [代码] 如上,type声明了要元素的类型,有image、text、rect、line、circle、redius_image(圆角图)等,能满足绝大多数情况。 class类名指定了使用的样式,需要在style中写出,符合css样式规范。 delay参数用来异步绘制元素,会把此元素放在第二个循环中绘制。 x,y用来指定元素的起始坐标。 将css样式与元素分离的目的是便于管理与复用。 此种方式每个元素都相互独立,互不影响,能够满足自由度要求高的情况,可控性高。 2.2 wxml转换 第二种方式为指定wxml元素,自动获取,下面是示例: [代码] let data = { list: [{ type: 'wxml', class: '.panel .draw_canvas', limit: '.panel' x: 0, y: 0 }] } [代码] 如上,type声明为wxml时,会查找所有类名为draw_canvas的节点,并且加入到绘制队列中。 class传入的第一个类名限定了查询的范围,可以不传,第二个用来指定查找的节点,可以定义为任意不影响样式展现的通用类名。 limit属性用来限定相对位置,例如,一个文本的位置(left, top) = (50, 80), class为panel的节点的位置为(left, top) = (20, 40),则文本canvas上实际绘制的位置(x, y) = (50 - 20, 80 -40) = (30, 40)。如果不传入limit,则以实际的位置(x, y) = (50, 80)绘制。 由于小程序节点元素查询接口的局限,无法直接获取节点的文本内容和图片标签的src属性,也无法直接区分是文本还是图片,但是可以获取到dataset,所以我们需要在节点上显示地声明data-type来指明类型,再声明data-text传入文字或data-url传入图片链接。下面是个示例: [代码] <view class="panel"> <view class="panel__img draw_canvas" data-type="image" data-url="https://xxx"></view> <view class="panel__text draw_canvas" data-type="text" data-text="文字">文字</view> </view> [代码] 如上,会查询到两个节点符合条件,第一个为image图片,第二个为text文本,利用SelectorQuery查询它们的computedStyle,分别得到left、top、width、height等数据后,转换成canvas支持的格式,完成绘制。 除此之外,下面的示例功能更加丰富: [代码] <view class="panel"> <view class="panel__text draw_canvas" data-type="background-image" data-radius="1" data-shadow="" data-border="2px solid #000"></view> <view class="panel__text draw_canvas" data-type="text" data-background="#ffffff" data-padding="2 3 0 0" data-delay="1" data-left="10" data-top="10" data-maxlength="4" data-text="这是个文字">这是个文字</view> </view> [代码] 如上,第一个data-type为background-image,表示读取此节点的背景图片,因为可以通过computedStyle直接获取图片链接,所以不需要显示传入url。声明data-radius属性,表示要将此图绘成乘圆形图片。data-border属性表示要绘制图片的边框,虽然也可以通过computedStyle直接获取,但是为了避免非预期的结果,还是要声明传入,border格式应符合css标准。此外,图片的box-shadow等样式都会根据声明绘制出来。 第二个文本节点,声明了data-background,则会根据节点的位置属性给文字增加背景。 data-padding属性用来修正背景的位置和宽高。data-delay属性用来延迟绘制,可以根据值的大小,来控制元素的层级,data-left和data-top用来修正位置,支持负值。data-maxlength用来限制文本的最大长度,超长时会截取并追加’…’。 此外,data-type还有inline-text,inline-image等行内元素的绘制,其实现较为复杂,会在后文介绍。 五、Wxml2Canvas实现原理 1. 绘制流程 整个绘制流程如下: [图片] 因为小程序的限制,只能在画布上绘制本地图片,所以统一先对图片提前下载,然后再绘制,为了避免图片重复下载,内部维护一个图片列表,会对相同的图片链接去重,减少等待时间。 2. 基本图形的实现 基础图形的绘制比较简单,内部实现只是对基础能力的封装,使用者不用再关注canvas的绘制过程,只需要提供关键数据即可,下面是一个图片绘制的实现示例: [代码] function drawImage (item, style) { if(item.delay) { this.asyncList.push({item, style}); }else { if(item.y < 0) { item.y = this.height + item.y * zoom - style.height * zoom; }else { item.y = item.y * zoom; } if(item.x < 0) { item.x = this.width + item.x * zoom - style.width * zoom; }else { item.x = item.x * zoom; } ctx.drawImage(item.url, item.x, item.y, style.width * zoom, style.height * zoom); ctx.draw(true); } } [代码] 如上,x,y值坐标支持传入负值,表示从画布的底部和右侧计算位置。 3. Wxml转Canvas元素的实现 3.1 computedStyle的获取 首先需要获取wxml的样式,代码示例如下: [代码] query.selectAll(`${item.class}`).fields({ dataset: true, size: true, rect: true, computedStyle: ['width', 'height', ...] }, (res) => { self.drawWxml(res); }) [代码] 3.2 块级元素的绘制 对于声明为image、text的元素,默认为块级元素,它们的绘制都是独立进行的,不需要考虑其他的元素的影响,以wxml节点为圆形的image为例,下面是部分代码: [代码] if(sub.dataset.type === 'image') { let r = sub.width / 2; let x = sub.left + item.x * zoom; let y = sub.top + item.y * zoom; let leftFix = +sub.dataset.left || 0; let topFix = +sub.dataset.top || 0; let borderWidth = sub.borderWidth || 0; let borderColor = sub.borderColor; // 如果是圆形图片 if(sub.dataset.radius) { // 绘制圆形的border if(borderWidth) { ctx.beginPath() ctx.arc(x + r, y + r, r + borderWidth, 0, 2 * Math.PI) ctx.setStrokeStyle(borderColor) ctx.setLineWidth(borderWidth) ctx.stroke() ctx.closePath() } // 绘制圆形图片的阴影 if(sub.boxShadow !== 'none') { ctx.beginPath() ctx.arc(x + r, y + r, r + borderWidth, 0, 2 * Math.PI) ctx.setFillStyle(borderColor); setBoxShadow(sub.boxShadow); ctx.fill() ctx.closePath() } // 最后绘制圆形图片 ctx.save(); ctx.beginPath(); ctx.arc((x + r), (y + r) - limitTop, r, 0, 2 * Math.PI); ctx.clip(); ctx.drawImage(url, x + leftFix * zoom, y + topFix * zoom, sub.width, sub.height); ctx.closePath(); ctx.restore(); }else { // 常规图片 } } [代码] 如上,块级元素的绘制和基础图形的绘制差异不大,理解起来也很容易,不再多述。 3.3 令人头疼的行内元素的绘制 当wxml的data-type声明为inline-image或者inline-text时,我们认为是行内元素。行内元素的绘制是一个难点,因为元素之前存在关联,所以不得不考虑各种临界情况。下面展开细述。 3.3.1 纯文本换行 对于长度超过一行的行内元素,需要计算出合适的换行位置,下图所示的是两种临界情况: [图片] [图片] 如上图所示,第一种情况为最后一行只有一个文字,第二种情况最后一行的文字长度和宽度相同。虽然长度不同,但都可通过下面代码绘制: [代码] let lineNum = Math.ceil(measureWidth(text) / maxWidth); // 文字行数 let sinleLineLength = Math.floor(text.length / lineNume); // 向下取整,保证多于实际每行字数 let currentIndex = 0; // 记录文字的索引位置 for(let i = 0; i < lineNum; i++) { let offset = 0; // singleLineLength并不是精确的每行文字数,要校正 let endIndex = currentIndex + sinleLineLength + offset; let single = text.substring(currentIndex, endIndex); // 截取本行文字 let singleWidth = measureWidth(single); // 超长时,左移一位,直至正好 while(singleWidth > maxWidth) { offset--; endIndex = currentIndex + sinleLineLength + offset; single = text.substring(currentIndex, endIndex); singleWidth = measureWidth(single); } currentIndex = endIndex; ctx.fillText(single, item.x, item.y + i * style.lineHeight); } // 绘制剩余的 if(currentIndex < text.length) { let last = text.substring(currentIndex, text.length); ctx.fillText(last, item.x, item.y + lineNum * style.lineHeight); } [代码] 为了避免计算太多次,首先算出大致的行数,求出每行的文字数,然后移位索引下标,求出实际的每行的字数,再下移一行继续绘制,直到结束。 3.3.2 非换行的图文混排 [图片] 上图是一个包含表情图片和加粗文字的混排内容,当使用Wxml2Canvas查询元素时,会将第一行的内容分为五部分: 文本内容:这是段文字; 表情图片:发呆表情(非系统表情,image节点展现); 表情图片:发呆表情; 文本内容:这也; 加粗文本内容:是一段文字,这也是文字。 对于这种情况,执行查询computedStyle后,会返回相同的top值。我们把top值相同的元素聚合在一起,认为它们是同一行内容,事实也是如此。因为表情大小的差异以及其他影响,默认规定top值在±2的范围内都是同一行内容。然后将top值的聚合结果按照left的大小从左往右排列,再一一绘制,即可完美还原此种情况。 3.3.3 换行的图文混排 当混排内容出现了换行情况时,如下图所示: [图片] 此时的加粗内容占据了两行,当我们依旧根据top值归类时,却发现加粗文字的left值取的是第二行的left值。这就导致加粗文字和第一部分的文字的top值和left值相同,如果直接绘制,两部分会发生重叠。 为了避免这种尴尬的情况,我们可以利用加粗文字的height值与第一部分文字的height值比较,显然前者是后者的两倍,可以得知加粗部分出现了换行情况,直接将其放在同组top列表的最后位置。换行的部分根据lineHeight下移绘制,同时做记录。 最后一部分的文本内容也出现了换行情况,同样无法得到真正的起始left值,并且其top值与上一部分换行后的top值相同。此时应该将他的left值追加加粗换行部分的宽度,正好得到真正的left值,最后再绘制。 大多数的行内元素的展现形式都能以上述的逻辑完美还原。 六、总结 基于基础图形封装和wxml转换这两种绘制方式,可以满足绝大多数的场景,能够极大地减少工作量,而不需要再关注内部实现。在实际使用中,二者并非孤立存在,而更多的是一起使用。 [图片] 如上图所示,对于列表内容我们利用wxml读取绘制,对于下部的白色区域,不是wxml节点内容,我们可以使用基础图形绘制方式实现。二者的结合更加灵活高效。 目前Wxml2Canvas已经在公司内部开源,不久会放到github上,同时也在不断完善中,旨在实现更多的样式展现与提升稳定性和绘制速度。 如果有更好的建议与想法,请联系我。
2019-02-28 - 生成分享朋友圈微海报
[图片] 描码体验 文未有小程序源码地址 (另有偿提供后台数据接口服务) [图片] 模板代码参考 [代码] <view class='padding text-center'> <image src="{{shareImage}}" mode="widthFix"></image> <canvasdrawer :painting.sync="painting" @getImage.user="eventGetImage"></canvasdrawer> </view> <view class="padding"> <button wx:if="{{shareImage}}" class='cu-btn block bg-red margin-tb-sm lg' @tap="eventSave">保存分享图</button> </view> [代码] 部分js代码 [代码]event = { getImage (e) { wepy.showToast({ title: e, icon: "success", duration: 2000 }); } } async buildPoster(){ if(this.shareImage == ''){ wepy.showLoading({ title: "生成中", mask: true }); let poster = await commApi.GetArticlePoster(this.id) this.painting = poster } this.showposter = true; this.$apply(); } methods = { async eventSave() { // 保存图片至本地 const res = await wepy.saveImageToPhotosAlbum({ filePath: this.shareImage }); if (res.errMsg === "saveImageToPhotosAlbum:ok") { wepy.showToast({ title: "分享图已保存到相册", icon: "success", duration: 2000 }); } }, eventGetImage(event) { wepy.hideLoading(); const { tempFilePath, errMsg } = event; if (errMsg === "canvasdrawer:ok"){ this.shareImage = tempFilePath; }else{ wepy.showToast({ title: errMsg, icon: "success", duration: 2000 }); } }, } [代码] 后端php代码 [代码]public function defalutArticlePoster($app, $user, $article){ // $title_length = Str::length($article->title,'UTF-8'); // dd($title_length); $poster = [ 'width'=>460, 'height'=> 500, 'clear'=> true, 'views'=>[ [ 'type'=> 'rect', 'background'=> '#666', 'top'=> 0, 'width'=> 460, 'height'=> 500, 'left'=> 0 ], [ 'type'=> 'rect', 'background'=> '#ffffff', 'top'=> 2, 'width'=> 456, 'height'=> 496, 'left'=> 2 ], [ 'type'=> 'image', 'url'=> $article->cover? $article->cover:'https://wx1.wechatrank.com/base64img/20190402233111.jpeg', 'top'=> 70, 'left'=> 28, 'width'=> 400, 'height'=> 320 ], [ 'type'=> 'text', 'content'=> $article->title, 'fontSize'=> 18, 'lineHeight'=> 24, 'color'=> '#333', 'textAlign'=> 'left', 'top'=> $title_length>22?16:26, 'left'=> 28, 'width'=> 387, 'MaxLineNumber'=> 2, 'breakWord'=> true, 'bolder'=> true ], [ 'type'=> 'text', 'content'=> str_replace(array(" ", " ", "\t", "\n", "\r", "\r\n", PHP_EOL), '', $article->intro), 'fontSize'=> 18, 'lineHeight'=> 24, 'color'=> '#666', 'textAlign'=> 'left', 'top'=> 406, 'left'=> 28, 'width'=> 310, 'MaxLineNumber'=> 3, 'breakWord'=> true, 'bolder'=> true ], [ 'type'=> 'image', 'url'=> url('/qrcode/article/'.$article->qrcode), 'top'=> 406, 'left'=> 360, 'width'=> 68, 'height'=> 68 ] ], ]; return $poster; } [代码] 示例代码来源: https://github.com/yizenghui/wxcms/blob/master/src/pages/poster/index.wpy 项目地址: https://github.com/yizenghui/wxcms https://github.com/simmzl/wepy_canvas_drawer 觉得对您有帮助请点个赞,谢谢
2019-05-27 - 借助云开发实现小程序模版消息推送(不用搭建服务器就可以实现微信消息推送)
上一节给大家将了借助云开发实现小程序支付功能,那么我们就要想了,能不能借助云开发实现小程序消息推送功能呢? 还别说,云开发还真能实现推送的功能。 一直关注我的同学肯定知道老师之前也写过借助java后台实现小程序消息推送的文章。 我们借助java后台虽然也能轻松的实现消息推送。但是呢?用java开发后台推送,必须要搭建服务器,学习java代码,部署java代码当然你就是做java开发的,或者学习过java,这没什么。 但是作为小程序开发人员来说,用java显得太重了。 传送门: 《借助小程序云开发实现小程序支付功能(含源码)》 《5行代码实现微信小程序模版消息推送 (含推送后台和小程序源码)》 下面就来教大家如何借助云开发实现小程序模版消息的推送功能。 老规矩,先看效果图 [图片] 下面来讲实现步骤 一,定义推送的云函数 由于我们的云推送功能只能在云函数里调用,所以我们这里必须要在云函数里实现推送功能。 1,首先我们定义一个云函数push0524。 如果你还不知道如何使用云开发,如何定义云函数,去翻下老师之前的文章。有写的。 [图片] 把完整的代码贴给大家 [代码]// 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() // 云函数入口函数 exports.main = async(event, context) => { console.log(event) return sendTemplateMessage(event) } //小程序模版消息推送 async function sendTemplateMessage(event) { const { OPENID } = cloud.getWXContext() // 接下来将新增模板、发送模板消息、然后删除模板 // 注意:新增模板然后再删除并不是建议的做法,此处只是为了演示,模板 ID 应在添加后保存起来后续使用 const addResult = await cloud.openapi.templateMessage.addTemplate({ id: 'AT0002', keywordIdList: [3, 4, 5] }) const templateId = addResult.templateId //新增的模版id const sendResult = await cloud.openapi.templateMessage.send({ touser: OPENID, templateId, formId: event.formId, page: 'pages/index/index', data: { keyword1: { value: '云开发实现推送', }, keyword2: { value: '2019 年 5 月 24 日', }, keyword3: { value: '编程小石头', }, } }) //删除模版id await cloud.openapi.templateMessage.deleteTemplate({ templateId, }) return sendResult } [代码] 上面代码所实现的就是 1,创建模版,拿到模版id 2,使用模版ID,填充模版消息,发送模版 3,删除模版。 我们正常开发时,模版都是在小程序后台获取到的。这里是为例演示方便。所以正常开发时,只需要实现第二步就行了。 推送的关键代码就是这个方法: cloud.openapi.templateMessage.send 通常我们定义完push0524云函数以后,如果直接调用的话,会报错误的。 [图片] 来看下这个错误,看到红色框里的permission就知道,肯定是权限的问题。所以我们在定义完云函数以后,要在push0524云函数下面添加权限配置页面。如下图 [图片] 重要的就是这个: “templateMessage.send”, 推送权限。因为推送是云开发给我们提供的,我们这里调用时,必须配置相关权限,才能使用的。 到这里我们的推送功能就实现了。下面我们来验证下。 二,验证云开发推送 验证其实很简单,和我们之前的《5行代码实现微信小程序模版消息推送 (含推送后台和小程序源码)》 类似。只不过一个是在java后台推送,一个是在小城里推送。下面我们简单写个小程序里验证推送的demo。 功能很简单 1,获取formid,因为推送必须有formid的 2,点击调用push0524实现推送 [图片] 简单的贴下代码 [图片] [图片] 需要注意的一点:我们测试时,必须要真机测试。因为模拟器没法获取到formid的。 [图片] 我们在推送成功的success回调中打印下log。如果log中出现,send:ok字样,就代表我们推送成功了。来看下推送成功的效果。 微信聊天列表接收到了消息提醒 [图片] 消息内容 [图片] 到这里我们就用云开发实现完整的消息推送功能了。是不是很简单。 有任何关于编程的问题都可以加老师微信 2501902696(备注小程序)也可以找老师索要完整源码。 编程小石头码农一枚,非著名全栈开发人员。分享自己的一些经验,学习心得,希望后来人少走弯路,少填坑 视频讲解地址:https://edu.csdn.net/course/detail/24770
2019-06-11 - 小程序原生高颜值组件库--ColorUI
[图片] 简介 ColorUI是一个Css类的UI组件库!不是一个Js框架。相比于同类小程序组件库,ColorUI更注重于视觉交互! 浏览GitHub:https://github.com/weilanwl/ColorUI [图片] 如何使用? 先下载源码包 → Github 引入到我的小程序 将 /demo/ 下的 colorui.wxss 和 icon.wxss 复制到小程序的根目录下 在 app.wxss 引入两个文件 [代码]@import "icon.wxss"; @import "colorui.wxss"; [代码] 使用模板全新开发 复制 /template/ 文件夹并重命名为你的项目,微信开发者工具导入为小程序就可以使用ColorUI了 体验沉浸式导航 [图片] App.js 获取系统参数并写入全局参数。 [代码]//App.js App({ onLaunch: function() { wx.getSystemInfo({ success: e => { this.globalData.StatusBar = e.statusBarHeight; let custom = wx.getMenuButtonBoundingClientRect(); this.globalData.Custom = custom; this.globalData.CustomBar = custom.bottom + custom.top - e.statusBarHeight; } }) } }) [代码] Page.js 页面配置获取全局参数。 [代码]//Page.js const app = getApp() Page({ data: { StatusBar: app.globalData.StatusBar, CustomBar: app.globalData.CustomBar, Custom: app.globalData.Custom } }) [代码] Page.wxml 页面构造导航。更多导航样式请下载Demo查阅 操作条组件。 [代码]<view class="cu-custom" style="height:{{CustomBar}}px;"> <view class="cu-bar fixed bg-gradual-pink" style="height:{{CustomBar}}px;padding-top:{{StatusBar}}px;"> <navigator class='action border-custom' open-type="navigateBack" delta="1" hover-class="none" style='width:{{Custom.width}}px;height:{{Custom.height}}px;margin-left:calc(750rpx - {{Custom.right}}px)'> <text class='icon-back'></text> <text class='icon-homefill'></text> </navigator> <view class='content' style='top:{{StatusBar}}px;'>操作条</view> </view> </view> [代码] 自定义系统Tabbar [图片] 按照官方 自定义 tabBar 配置好Tabbar (开发工具和版本库请使用最新版)。 使用ColorUI配置Tabbar只需要更改 Wxml 页的内容即可。 更多Tabbar样式请下载Demo查阅 操作条组件。 /custom-tab-bar/index.wxml [代码] <view class="cu-bar tabbar bg-white shadow"> <view class="action" wx:for="{{list}}" wx:key="index" data-path="{{item.pagePath}}" data-index="{{index}}" bindtap="switchTab"> <view class='icon-cu-image'> <image src='{{selected === index ? item.selectedIconPath : item.iconPath}}' class='{{selected === index ? "animation" : "animation"}}'></image> </view> <view class='{{selected === index ? "text-green" : "text-gray"}}'>{{item.text}}</view> </view> </view> [代码] 作者叨叨 ColorUI是一个高度自定义的Css样式库,包含了开发常用的元素和组件,元素组件之间也能相互嵌套使用。我也会不定期更新一些扩展到源码。 其实大家都在催我写文档,但这个库源码就在这,所见即所得,粘贴复制就可以得到你想要的页面。当然,文档我还是要写的,也希望大家多多提意见。 现在前端的开发方向基本都是奔着Js方向的,布局和样式大家讨论的有点少。以后我会在开发者社区多聊一聊关于开发中的布局和样式。 [图片] 感谢阅读。
2019-02-26