- 云开发基础NodeJS
云函数的运行环境是 Node.js,我们可以在云函数中使用 Nodejs 内置模块以及使用 npm 安装第三方依赖来帮助我们更快的开发。借助于一些优秀的开源项目,避免了我们重复造轮子,相比于小程序端,能够大大扩展云函数的使用 云函数与 Nodejs由于云函数与 Nodejs 息息相关,需要我们对云函数与 Node 的模块以及 Nodejs 的一些基本知识有一些基本的了解。下面只介绍一些基础的概念,如果你想详细深入了解,建议去翻阅一下 Nodejs 的官方技术文档: 技术文档:Nodejs API 中文技术文档 Nodejs 的内置模块在前面我们已经接触过 Nodejs 的 fs 模块、path 模块,这些我们称之为 Nodejs 的内置模块,内置模块不需要我们使用 npm install 下载,就可以直接使用 require 引入: const fs = require('fs') const path = require('path') Nodejs 的常用内置模块以及功能如下所示,这些模块都是可以在云函数里直接使用的: fs 模块:文件目录的创建、删除、查询以及文件的读取和写入,下面的 createReadStream 方法类似于读取文件,path 模块:提供了一些用于处理文件路径的 APIurl 模块:用于处理与解析 URLhttp 模块:用于创建一个能够处理和响应 http 响应的服务querystring 模块:解析查询字符串until 模块 :提供用于解析和格式化 URL 查询字符串的实用工具;net 模块:用于创建基于流的 TCP 或 IPC 的服务器crypto 模块:提供加密功能,包括对 OpenSSL 的哈希、HMAC、加密、解密、签名、以及验证功能的一整套封装在云函数中使用 HTTP 请求访问第三方服务可以不受域名限制,即不需要像小程序端一样,要将域名添加到 request 合法域名里;也不受 http 和 https 的限制,没有域名只有 IP 都是可以的,所以云函数可以应用的场景非常多,即能方便的调用第三方服务,也能够充当一个功能复杂的完整应用的后端。不过需要注意的是,云函数是部署在云端,有些局域网等终端通信的业务只能在小程序里进行。 常用变量module、exports、require require 用于引入模块、 JSON、或本地文件。 可以从 node_modules 引入模块,可以使用相对路径(例如 ./、)引入本地模块或 JSON 文件,路径会根据 __dirname 定义的目录名或当前工作目录进行处理。 node 模块化遵循的是 commonjs 规范,CommonJs 定义的模块分为: 模块标识(module)、模块导出(exports) 、模块引用(require)。 在 node 中,一个文件即一个模块,使用 exports 和 require 来进行处理。 exports 表示该模块运行时生成的导出对象。如果按确切的文件名没有找到模块,则 Node.js 会尝试带上 .js、 .json 或 .node 拓展名再加载。 .js 文件会被解析为 JavaScript 文本文件, .json 文件会被解析为 JSON 文本文件。 .node 文件会被解析为通过 process.dlopen() 加载的编译后的插件模块。以 '/' 为前缀的模块是文件的绝对路径。 例如, require('/home/marco/foo.js') 会加载 /home/marco/foo.js 文件。以 './' 为前缀的模块是相对于调用 require() 的文件的。 也就是说, circle.js 必须和 foo.js 在同一目录下以便于 require('./circle') 找到它。 module.exports 用于指定一个模块所导出的内容,即可以通过 require() 访问的内容。 // 引入本地模块: const myLocalModule = require('./path/myLocalModule'); // 引入 JSON 文件: const jsonData = require('./path/filename.json'); // 引入 node_modules 模块或 Node.js 内置模块: const crypto = require('crypto'); wx-server-sdk 的模块tcb-admin-node、protobuf、jstslib 第三方模块Nodejs 有 npm 官网地址 Nodejs 库推荐:awesome Nodejs 当没有以 '/'、 './' 或 '../' 开头来表示文件时,这个模块必须是一个核心模块或加载自 node_modules 目录,比如 wx-server-sdk 就加载自 node_modules 文件夹: const cloud = require('wx-server-sdk') Lodash 实用工具库Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库,通过降低 array、number、objects、string 等数据类型的使用难度从而让 JavaScript 变得更简单。Lodash 的模块化方法非常适用于:遍历 array、object 和 string;对值进行操作和检测;创建符合功能的函数。 技术文档:Lodash 官方文档、Lodash 中文文档 使用开发者工具新建一个云函数,比如 lodash,然后在 package.json 增加 lodash 最新版 latest 的依赖: "dependencies": { "lodash": "latest" } 在 index.js 里的代码修改为如下,这里使用到了 lodash 的 chunk 方法来分割数组: const cloud = require('wx-server-sdk') var _ = require('lodash'); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }) exports.main = async (event, context) => { //将数组拆分为长度为2的数组 const arr= _.chunk(['a', 'b', 'c', 'd'], 2); return arr } 右键 lodash 云函数目录,选择“在终端中打开”,npm install 安装模块之后右键部署并上传所有文件。我们就可以通过多种方式来调用它(前面已详细介绍)即可获得结果。Lodash 作为工具,非常好用且实用,它的源码也非常值得学习,更多相关内容则需要大家去 Github 和官方技术文档里深入了解。 在awesome Nodejs页面我们了解到还有 Ramba、immutable、Mout 等类似工具库,这些都非常推荐。借助于 Github 的 awesome 清单,我们就能一手掌握最酷炫好用的开源项目,避免了自己去收集收藏。 moment 时间处理开发小程序时经常需要格式化时间、处理相对时间、日历时间以及时间的多语言问题,这个时候就可以使用比较流行的 momentjs 了。 技术文档:moment 官方文档、moment 中文文档 使用开发者工具新建一个云函数,比如 moment,然后在 package.json 增加 moment 最新版 latest 的依赖: "dependencies": { "moment": "latest" } 在 index.js 里的代码修改为如下,我们将 moment 区域设置为中国,将时间格式化为 十二月 23 日 2019, 4:13:29 下午的样式以及相对时间多少分钟前: const cloud = require('wx-server-sdk') const moment = require("moment"); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }) exports.main = async (event, context) => { moment.locale('zh-cn'); time1 = moment().format('MMMM Do YYYY, h:mm:ss a'); time2 = moment().startOf('hour').fromNow(); return { time1,time2} } 不过云函数中的时区为 UTC+0,不是 UTC+8,格式化得到的时间和在国内的时间是有 8 个小时的时间差的,我们可以给小时数+8,也可以修改时区。云函数修改时区我们可以使用 timezone 依赖(和 moment 是同一个开源作者)。 技术文档:timezone 技术文档 在 package.json 增加 moment-timezone 最新版 latest 的依赖,然后修改上面相应的代码即可,使用起来非常方便: const moment = require('moment-timezone'); time1 = moment().tz('Asia/Shanghai').format('MMMM Do YYYY, h:mm:ss a'); 获取公网 IP有时我们希望能够获取到服务器的公网 IP,比如用于 IP 地址的白名单,或者想根据 IP 查询到服务器所在的地址,ipify 就是一个免费好用的依赖,通过它我们也可以获取到云函数所在服务器的公网 IP。 技术文档:ipify Github 地址 使用开发者工具新建一个 getip 的云函数,然后输入以下代码,并在 package.json 的”dependencies”里新增 "ipify":"latest" ,即最新版的 ipify 依赖: const cloud = require('wx-server-sdk') const ipify = require('ipify'); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }) exports.main = async (event, context) => { return await ipify({ useIPv6: false }) } 然后右键 getip 云函数根目录,选择在终端中打开,输入 npm install 安装依赖,之后上传并部署所有文件。我们可以在小程序端调用这个云函数,就可以得到云函数服务器的公网 IP,这个 IP 是随机而有限的几个,反复调用 getip,就能够穷举所有云函数所在服务器的 ip 了。 可能你会在使用云函数连接数据库或者用云函数来建微信公众号的后台时需要用到 IP 白名单,我们可以把这些 ip 都添加到白名单里面,这样云函数就可以做很多事情啦。 Buffer 文件流const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }) exports.main = async (event, context) => { const fileID = 'cloud://xly-xrlur.786c-xly-xrlur-1300446086/cloudbase/1576500614167-520.png' const res = await cloud.downloadFile({ fileID: fileID, }) const buffer = res.fileContent return buffer.toString('base64') } getServerImg(){ wx.cloud.callFunction({ name: 'downloadimg', success: res => { console.log("云函数返回的数据",res.result) this.setData({ img:res.result }) }, fail: err => { console.error('云函数调用失败:', err) } }) } "400px" height="200px" src="data:image/jpeg;base64,{{img}}">image> Buffer String Buffer JSON 图像处理 sharpsharp 是一个高速图像处理库,可以很方便的实现图片编辑操作,如裁剪、格式转换、旋转变换、滤镜添加、图片合成(如添加水印)、图片拼接等,支持 JPEG, PNG, WebP, TIFF, GIF 和 SVG 格式。在云函数端使用 sharp 来处理图片,而云存储则可以作为服务端和小程序端来传递图片的桥梁。 技术文档:sharp 官方技术文档 使用开发者工具新建一个 const cloud = require('wx-server-sdk') const fs = require('fs') const path = require('path') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }) const sharp = require('sharp'); exports.main = async (event, context) => { //这里换成自己的fileID,也可以在小程序端上传文件之后,把fileID传进来event.fileID const fileID = 'cloud://xly-xrlur.786c-xly-xrlur-1300446086/1572315793628-366.png' //要用云函数处理图片,需要先下载图片,返回的图片类型为Buffer const res = await cloud.downloadFile({ fileID: fileID, }) const buffer = res.fileContent //sharp对图片进行处理之后,保存为output.png,也可以直接保存为Buffer await sharp(buffer).rotate().resize(200).toFile('output.png') // 云函数读取模块目录下的图片,并上传到云存储 const fileStream = await fs.createReadStream(path.join(__dirname, 'output.png')) return await cloud.uploadFile({ cloudPath: 'sharpdemo.jpg', fileContent: fileStream, }) } 也可以让 sharp 不需要先 toFile 转成图片,而是直接转成 Buffer,这样就可以直接作为参数传给 fileContent 上传到云存储,如: const buffer2 = await sharp(buffer).rotate().resize(200).toBuffer(); return await cloud.uploadFile({ cloudPath: 'sharpdemo2.jpg', fileContent: buffer2, }) 连接数据库 MySQL公网连接数据库 MySQL技术文档:Sequelize const sequelize = new Sequelize('database', 'username', 'password', { host: 'localhost', //数据库地址,默认本机 port:'3306', dialect: 'mysql', pool: { //连接池设置 max: 5, //最大连接数 min: 0, //最小连接数 idle: 10000 }, }); 无论是MySQL,还是PostgreSQL、Redis、MongoDB等其他数据库,只要我们在 私有网络连接 MySQL默认情况下,云开发的函数部署在公共网络中,只可以访问公网。如果开发者需要访问腾讯云的 Redis、TencentDB、CVM、Kafka 等资源,需要建立私有网络来确保数据安全及连接安全。 连接数据库 Redisconst cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }) const Redis = require('ioredis') const redis = new Redis({ port: 6379, host: '10.168.0.15', family: 4, password: 'CloudBase2018', db: 0, }) exports.main = async (event, context) => { const wxContext = cloud.getWXContext() const cacheKey = wxContext.OPENID const cache = await redis.get(cacheKey) if (!cache) { const result = await new Promise((resolve, reject) => { setTimeout(() => resolve(Math.random()), 2000) }) redis.set(cacheKey, result, 'EX', 3600) return result } else { return cache } } 二维码 qrcode技术文档:node-qrcode Github 地址 邮件处理技术文档:Nodemailer Github 地址、Nodemailer 官方文档 使用开发者工具创建一个云函数,比如 nodemail,然后在 package.json 增加 nodemailer 最新版 latest 的依赖: "dependencies": { "nodemailer": "latest" } 发送邮件服务器:smtp.qq.com,使用 SSL,端口号 465 或 587 const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }) exports.main = async (event, context) => { const nodemailer = require("nodemailer"); let transporter = nodemailer.createTransport({ host: "smtp.qq.com", //SMTP服务器地址 port: 465, //端口号,通常为465,587,25,不同的邮件客户端端口号可能不一样 secure: true, //如果端口是465,就为true;如果是587、25,就填false auth: { user: "344169902@qq.com", //你的邮箱账号 pass: "你的QQ邮箱授权码" //邮箱密码,QQ的需要是独立授权码 } }); let message = { from: '来自李东bbsky <344169902@qq.com>', //你的发件邮箱 to: '你要发送给谁', //你要发给谁 // cc:'', 支持cc 抄送 // bcc: '', 支持bcc 密送 subject: '欢迎大家参与云开发技术训练营活动', //支持text纯文字,html代码 text: '欢迎大家', html: '你好:' + '欢迎欢迎', attachments: [ //支持多种附件形式,可以是String, Buffer或Stream { filename: 'image.png', content: Buffer.from( 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/' + '//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U' + 'g9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC', 'base64' ), }, ] }; let res = await transporter.sendMail(message); return res; } Excel 文档处理Excel 是存储数据比较常见的格式,那如何让云函数拥有读写 Excel 文件的能力呢?我们可以在 Github 上搜索关键词“Node Excel”,去筛选 Star 比较多,条件比较契合的。 Github 地址:node-xlsx 使用开发者工具新建一个云函数,在 package.json 里添加 latest 最新版的 node-xlsx: "dependencies": { "wx-server-sdk": "latest", "node-xlsx": "latest" } 读取云存储的 Excel 文件 const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }) const xlsx = require('node-xlsx'); const db = cloud.database() exports.main = async (event, context) => { const fileID = 'cloud://xly-xrlur.786c-xly-xrlur-1300446086/china.csv' const res = await cloud.downloadFile({ fileID: fileID, }) const buffer = res.fileContent const tasks = [] var sheets = xlsx.parse(buffer); sheets.forEach(function (sheet) { for (var rowId in sheet['data']) { console.log(rowId); var row = sheet['data'][rowId]; if (rowId > 0 && row) { const promise = db.collection('chinaexcel') .add({ data: { city: row[0], province: row[1], city_area: row[2], builtup_area: row[3], reg_pop: row[4], resident_pop: row[5], gdp: row[6] } }) tasks.push(promise) } } }); let result = await Promise.all(tasks).then(res => { return res }).catch(function (err) { return err }) return result } 将数据库里的数据保存为 CSV 技术文档:json2CSV HTTP 处理got、superagent、request、axios、request-promise 尽管云函数的 Nodejs 版本比较低(目前为 8.9),但绝大多数模块我们都可以使用 Nodejs 12 或 13 的环境来测试,不过有时候也要留意有些模块不支持 8.9,比如 got 10.0.1 以上的版本。node 中,http 模块也可作为客户端使用(发送请求),第三方模块 request 对其使用方法进行了封装,操作更方便!所以来介绍一下 request 模块 get 请求const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }) const rp = require('request-promise') exports.main = async (event, context) => { const options = { url: 'https://news-at.zhihu.com/api/4/news/latest', json: true, method: 'GET', }; return await rp(options) } post 请求结合文件流request('https://www.jmjc.tech/public/home/img/flower.png').pipe(fs.createWriteStream('./flower.png')) // 下载文件到本地 加解密 Cryptocrypto 模块是 nodejs 的核心模块之一,它提供了安全相关的功能,包含对 OpenSSL 的哈希、HMAC、加密、解密、签名、以及验证功能的一整套封装。由于 crypto 模块是内置模块,我们引入它是无需下载,就可以直接引入。 使用开发者工具新建一个云函数,比如 crypto,在 index.js 里输入以下代码,我们来了解一下 crypto 支持哪些加密算法,并以 MD5 加密为例: const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }) const crypto = require('crypto'); exports.main = async (event, context) => { const hashes = crypto.getHashes(); //获取crypto支持的加密算法种类列表 //md5 加密 CloudBase2020 返回十六进制 var md5 = crypto.createHash('md5'); var message = 'CloudBase2020'; var digest = md5.update(message, 'utf8').digest('hex'); return { "crypto支持的加密算法种类":hashes, "md5加密返回的十六进制":digest }; } 将云函数部署之后调用从返回的结果我们可以了解到,云函数 crypto 模块支持 46 种加密算法。 发短信“qcloudsms_js”: “^0.1.1” const cloud = require('wx-server-sdk') const QcloudSms = require("qcloudsms_js") const appid = 1400284950 // 替换成您申请的云短信 AppID 以及 AppKey const appkey = "a33b602345f5bb866f040303ac6f98ca" const templateId = 472078 // 替换成您所申请模板 ID const smsSign = "统计小助理" // 替换成您所申请的签名 cloud.init() // 云函数入口函数 exports.main = async (event, context) => new Promise((resolve, reject) => { /*单发短信示例为完整示例,更多功能请直接替换以下代码*/ var qcloudsms = QcloudSms(appid, appkey); var ssender = qcloudsms.SmsSingleSender(); var params = ["1234", "15"]; // 获取发送短信的手机号码 var mobile = event.mobile // 获取手机号国家/地区码 var nationcode = event.nationcode ssender.sendWithParam(nationcode, mobile, templateId, params, smsSign, "", "", (err, res, resData) => { /*设置请求回调处理, 这里只是演示,您需要自定义相应处理逻辑*/ if (err) { console.log("err: ", err); reject({ err }) } else { resolve({ res: res.req, resData }) } } ); }) 使用开发者工具 wx.cloud.callFunction({ name: 'sendphone', data: { // mobile: '13217922526', mobile: '18565678773', nationcode: '86' }, success: res => { console.log('[云函数] [sendsms] 调用成功') console.log(res) }, fail: err => { console.error('[云函数] [sendsms] 调用失败', err) } })
2021-09-10 - 关于安卓微信7.0.15蓝牙打印超时的解决方案
各位微信开发者: 6月2日以来我们持续收到开发者反馈的安卓微信7.0.15蓝牙打印超时的问题,为了让用户恢复正常使用,我们提供了修复版本,各位可自主下载以下版本进行替换: 64位版本: https://dldir1.qq.com/weixin/android/wechat_7.0.15_0x27000f3b_1680.apk 不便之处 敬希见谅。
2020-06-05 - 图片上传Uploader组件里 wx.chooseImage()方法怎么调用?
[代码]<view class="page__bd"> <mp-cells> <mp-cell> <mp-uploader bindfail="uploadError" bindsuccess="uploadSuccess" select="{{selectFile}}" upload="{{uplaodFile}}" files="{{files}}" max-count="5" title="图片上传" tips="图片上传提示"></mp-uploader> </mp-cell> </mp-cells> </view>[代码][代码]Page({ data: { files: [{ url: 'http://mmbiz.qpic.cn/mmbiz_png/VUIF3v9blLsicfV8ysC76e9fZzWgy8YJ2bQO58p43Lib8ncGXmuyibLY7O3hia8sWv25KCibQb7MbJW3Q7xibNzfRN7A/0', }, { loading: true }, { error: true }] }, onLoad() { this.setData({ selectFile: this.selectFile.bind(this), uplaodFile: this.uplaodFile.bind(this) }) }, chooseImage: function (e) { var that = this; wx.chooseImage({ sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 success: function (res) { // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片 that.setData({ files: that.data.files.concat(res.tempFilePaths) }); } }) }, previewImage: function(e){ wx.previewImage({ current: e.currentTarget.id, // 当前显示图片的http链接 urls: this.data.files // 需要预览的图片http链接列表 }) }, selectFile(files) { console.log('files', files) // 返回false可以阻止某次文件上传 }, uplaodFile(files) { console.log('upload files', files) // 文件上传的函数,返回一个promise return new Promise((resolve, reject) => { setTimeout(() => { reject('some error') }, 1000) }) }, uploadError(e) { console.log('upload error', e.detail) }, uploadSuccess(e) { console.log('upload success', e.detail) }});[代码]官方文档里,并没有调用chooseImage()方法的地方, 在mp-uoloader标签里 添加catchtap、bindtap方法调用,都会造成触发两次上传图片窗口的bug,同时,组件自带的点击图片放大wx.previewImage()方法,也没有明确调用的地方,问题还有点击图片放大时,也是触发上传窗口, 去掉catchtap、bindtap方法,就没有问题,但是去掉后 wx.chooseImage()方法就触发不了
2019-12-16 - margin-bottom无效
小程序给一个view设置margin-bottom 模拟器上是好的 但是真机上无效 由于这个view需要一个背景 所有如果把margin-bottom改为padding-bottom 背景会走样 有人遇到 该怎么解决么? 片段 https://developers.weixin.qq.com/s/s2UTjQmg7d4p
2018-12-22 - 地图需求轻松实现 腾讯地图插件助力小程序开发
出门在外,免不了查询地图的需求!为了帮助开发者们进一步“减负”,腾讯地图的插件添加了路线规划的能力,主要解决“向用户展示从A到B路线”的问题。使用插件的正确姿势究竟是什么呢?今天我们给大家介绍——腾讯地图插件的能力。 腾讯地图插件使用场景 >>> 场景1: -收到小程序的婚礼请柬,但是请柬上的地址找不到?怎么办? -用路线插件给用户指路~ 如果你开发的是请柬邀请类的小程序,就会遇到上述场景。在传统开发模式中,引入完整的地图选点、路线规划组件,开发成本非常高,更多开发者选择让用户直接输入文字地址进行展示,以此作为降低开发成本的妥协方案。这样的设计不可点击,更没有路线规划的能力,用户还需手动输入去查询地址和交通路线。 [图片] 传统请柬 不可交互 但如果开发者选择使用腾讯地图提供的路线插件,开发成本将大幅降低,用户体验也能直线上升。我们在这里以婚庆请柬小程序为例进行说明: 用户在编辑请柬小程序的过程中,提前设置好婚礼举办地点;当婚礼宾客收到请柬,点击地点,腾讯地图插件就能根据其宾客当前位置和目的地坐标,自动生成精准的导航路线,这样是不是比枯燥的文字多了几分智能呢? [图片] 一键导航 简洁明了 场景2:会议服务小帮手 提前了解参会路线 与会者应该如何从高铁站、机场、火车站前往会议地点,一直都是各类会议邀请的必备内容。但长期以来,此类信息都习惯以纯文字形式进行发布,体验上存在不便理解、记忆难的问题。 但如果小程序能够使用腾讯地图插件,这类场景的体验将发生质的改变: 会议组织方在小程序中提前设置多组起终点(如:机场-会议中心、高铁站-会议中心),与会者收到会议邀请后点击指定线路,就能在地图插件中查看到精确的参会路线, 腾讯地图插件使用指引 >>> 那使用腾讯地图插件会不会很麻烦呢?别担心,只需完成两步操作就能轻松接入: [图片] 1.在“小程序管理后台-设置-第三方服务-插件管理”中查找插件名称“腾讯地图”,并申请使用。 2.在小程序代码中使用插件( 详见《插件开发文档》) 腾讯地图插件应用>>> [图片] 腾讯地图+ 小程序 [图片] 扫码体验“腾讯地图+”
2018-09-21 - 这个免费视频插件,能帮商家节省推广费!
想要在自己的电商小程序中增加商品介绍视频,但自己搭建视频服务开发成本太大? 想要在餐饮服务中添加菜品视频,但苦于带宽成本过高? 想要在门票预订服务中用视频打动用户,但视频资质申请流程太长? 腾讯视频插件来帮你~ 今天,我们跟大家分享腾讯视频插件的故事。 腾讯视频插件提供了完整视频播放能力,方便开发者可以给用户提供更好的视频体验。 插件基于腾讯视频的CDN节点和成熟视频方案,可以做到为不同地点的用户提供更流畅的播放服务,更清晰的视频,更稳定的播放质量。只需要视频的vid,开发者即可直接在小程序内播放腾讯视频上的内容! 腾讯视频插件使用场景 场景一:电商类小程序 除了对商品的语言描述,实惠的价格,精美的图片,也需要生动直观、360度动态介绍商品,比单一的图片更能引起消费者的好感。 现在,在商品介绍里直接链入相关商品视频。比如,买衣服的电商小程序,可以把电视或电影中明星穿过的同款视频链入,在满足用户感官享受的同时,提升转化率。 场景二:文娱推荐类小程序 不局限于苍白的文字描述,推荐类小程序也可在小程序中添加电影视频、预告片,为用户带来完美的购票、观影体验。开发者无需独立开发视频功能,直接使用“腾讯视频”插件,即可实现视频播放功能。 [图片] 场景三:资讯类小程序 “腾讯视频”插件还可以是内容创作者的一大利器,以游戏攻略类小程序为例。小程序就可以直接用视频的形式展现,一方面清晰明了地展示攻略流程,同时也增加了用户在小程序内的停留时长,进一步引导用户做更多动作。 或者生活居家小技巧类的小程序,比如想教大家一种打结的方式,纯文字的形式即很难说清楚,又浪费内容运营者的时间,这时候直接使用插件链入视频,就能很快地教会大家,给予用户更好的内容体验。 轻松接入腾讯视频插件 “腾讯视频”提供了这么多的功能,使用起来也同样很方便: 1 在“小程序管理后台→设置→第三方服务→插件管理”中查找插件名称“腾讯视频”,并申请使用。 [图片] 2 参考详情页中的 [开发文档],在小程序代码中使用插件。
2018-09-21 - 梵高相机插件
利用人工智能AI 的方式,将图片转化为多种不同的风格,加强小程序的使用体验,提供趣味的玩法[图片] [图片] [图片]
2018-09-26 - 小程序中瀑布流布局太棘手?这款插件不仅貌美还「能屈能伸」
BrickLayout 晓瀑布流是知晓云为小程序开发者提供的第 3 款插件 BrickLayout 晓瀑布流为使用者提供开箱即用的瀑布流布局的一种可行性的方案,使用者仅需要按照对应所需的字段传入瀑布流组件,即可快速实现瀑布流布局。未来的瀑布流组件将会提供更多样式、适用更多场景的瀑布流模板,敬请期待!希望有更多场景推荐,希望有更多内容定制,欢迎留言或者告诉我们 g-emoji class="g-emoji" alias="clap" fallback-src="https://assets-cdn.github.com/images/icons/emoji/unicode/1f44f.png" style="box-sizing: border-box; font-family: "Apple Color Emoji", "Segoe UI", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 1.4em; line-height: 20px; vertical-align: middle;">👏/g-emoji> How BrickLayout g-emoji class="g-emoji" alias="sparkles" fallback-src="https://assets-cdn.github.com/images/icons/emoji/unicode/2728.png" style="box-sizing: border-box; font-family: "Apple Color Emoji", "Segoe UI", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 1.4em; font-weight: 400; line-height: 20px; vertical-align: middle;">✨/g-emoji>由于小程序的诸多限制,导致在 web 上很多常规实现瀑布流的方式大多受到不同程度的影响,小程序中,实现瀑布流组件大抵有两种思路:采用纯粹的 css 来实现,或者通过数据处理配合 css 来实现瀑布流。 采用纯粹的 css 采用纯粹的 css 可以用 multi-column 利用 css3 属性实现多列布局、flex 布局、grid 布局等等。但是结合每个布局的特性,我们率先排除了 grid 布局,因为 grid 布局是实现相对有规则的网格布局,瀑布流布局中,grid 布局不适用。其次,我们排除了 multi-column 这个 css3 属性。在呈现效果上看,multi-column 的确很好地满足了我们对于瀑布流布局的样式布局要求,但是,multi-column 本质上是将文档流分为多列,也就是我们在杂志、报刊常见的多列布局,最后呈现效果(如下图)实际上不满足我们对有序数据的展现要求,因此而排除。 最后我们的考虑范围只剩下 flex 布局,flex 布局在初始状态下的确很好地满足了我们对于数据的呈现效果,但是如果不加以数据干预,在默认非展开的情况下展开单个卡片,极端情况下会导致两列高度差过大,破坏了我们对于瀑布流的要求。 css 配合数据处理 综上所述,我们采用了 flex 布局加之对于使用者所传入的数据进行处理,达成了我们想要的效果。前端展现方面,我们还是通过 flex 布局,达成实际的瀑布流呈现效果,对于数据变化亦或是卡片展开时,我们再对数据进行进一步的处理,只有在初始化的时候,或者卡片状态发生改变的时候,对两列高度进行计算,保证两列保持较为稳定的高度差,进而实现瀑布流布局。 why BrickLayout g-emoji class="g-emoji" alias="sparkles" fallback-src="https://assets-cdn.github.com/images/icons/emoji/unicode/2728.png" style="box-sizing: border-box; font-family: "Apple Color Emoji", "Segoe UI", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 1.4em; font-weight: 400; line-height: 20px; vertical-align: middle;">✨/g-emoji>通过 BrickLayout 晓瀑布流使用者无须在关心实际的瀑布流布局实现,也无需关心前端的实际样式布局,更加专注于业务逻辑开发。未来的 BrickLayout 晓瀑布流将为使用者提供更加多样的模板,适用于不同场景之下的瀑布流布局。 [代码][代码] 插件使用案例 [图片]
2018-09-27 - 七牛传图,上传图片至七牛云
七牛传图插件说明文档 GitHub项目地址:https://github.com/oubingbing/qiniu-upload 1.目前七牛传图插件信息 AppId:wx00caa212d6710dcb 版本号:1.3.0 2.具体使用方法 2.1 配置app.json和使用页面的***.json [代码]//app.json[代码] [代码]{[代码] [代码] [代码][代码]"pages"[代码][代码]: [[代码] [代码] [代码][代码]"pages/index/index"[代码] [代码] [代码][代码]],[代码] [代码] [代码][代码]"plugins"[代码][代码]: { [代码][代码]//配置插件[代码] [代码] [代码][代码]"myPlugin"[代码][代码]: {[代码] [代码] [代码][代码]"version"[代码][代码]: [代码][代码]"1.0.0"[代码][代码],[代码] [代码] [代码][代码]"provider"[代码][代码]: [代码][代码]"wx00caa212d6710dcb"[代码] [代码]//appId[代码] [代码] [代码][代码]}[代码] [代码] [代码][代码]}[代码] [代码]}[代码] [代码]***.json[代码] [代码]{[代码] [代码] [代码][代码]"usingComponents"[代码][代码]: {[代码] [代码] [代码][代码]"upload"[代码][代码]: [代码][代码]"plugin://myPlugin/upload"[代码] [代码]//引入插件[代码] [代码] [代码][代码]}[代码] [代码]}[代码] 2.2 在页面的WXML文件中添加标签 [代码]<[代码][代码]upload[代码] [代码]icon-info[代码][代码]=[代码][代码]"{{icon}}"[代码] [代码]//上传图标信息,包括图标的宽高[代码] [代码] [代码][代码]qiniu-info[代码][代码]=[代码][代码]"{{qiniu}}"[代码] [代码]//七牛信息,包括七牛授权token、七牛存储区域、七牛域名以及可以一次性选择图片的最大数量[代码] [代码] [代码][代码]bind:success[代码][代码]=[代码][代码]"uploadSuccess"[代码] [代码]//上传成功回调 [代码] [代码] [代码][代码]bind:delete[代码][代码]=[代码][代码]"deleteSuccess"[代码] [代码]//删除成功回调[代码] [代码] [代码][代码]bind:error[代码][代码]=[代码][代码]"uploadError"[代码][代码]/> //上传错误回调[代码] 2.3 JS文件中处理传入插件数据 [代码]var[代码] [代码]plugin = requirePlugin([代码][代码]"myPlugin"[代码][代码])[代码] [代码]const token = [代码][代码]'dJVFK8ibSzHKWhcVOupqzn22EKJ9QXqjLIqqDsqn:FHJcjNuTs5HtSbsUQveZU3vLGcw=:eyJzY29wZSI6InNjaG9vbCIsImRlYWRsaW5lIjoxNTM3ODczODE0fQ=='[代码][代码];[代码] [代码]Page({[代码] [代码] [代码][代码]data:{[代码] [代码] [代码][代码]test:[代码][代码]"plugin"[代码][代码],[代码] [代码] [代码][代码]icon:{[代码] [代码] [代码][代码]width[代码][代码]:[代码][代码]"130rpx"[代码][代码],[代码][代码]//图片和图标的宽[代码] [代码] [代码][代码]height[代码][代码]: [代码][代码]"130rpx",[代码][代码]//图片和图标的高[代码] [代码] [代码] [代码][代码] path:"",//选择图片icon的URL地址,必须是网络地址,不能是本地地址,如果不填则选默认图标, showImage:true//是否显示上传后的图片 [代码] [代码][代码]},[代码] [代码] [代码][代码]qiniu:{[代码] [代码] [代码][代码]uploadNumber:4,[代码][代码]//一次性选择图片的最大限制[代码] [代码] [代码][代码]region: [代码][代码]"SCN"[代码][代码],[代码][代码]//ECN, SCN, NCN, NA,您的七牛存储区域[代码] [代码] [代码][代码]token: token,[代码][代码]//七牛上传token凭证,需您在服务器获取,然后自行维护这个token的有效期[代码] [代码] [代码][代码]domain: [代码][代码]"http://image.kucaroom.com",[代码][代码]//七牛域名[代码] returnAllImage:true,//是否返回上传图片的数组,false上传一个返回一个 [代码] [代码][代码]}[代码] [代码] [代码][代码]},[代码] [代码] [代码] [代码] [代码][代码]onLoad: [代码][代码]function[代码][代码]() {[代码] [代码] [代码][代码]},[代码] [代码] [代码] [代码] [代码][代码]/**[代码] [代码] [代码][代码]* 上传成功后的回调,返回已上传的图片数组[代码] [代码] [代码][代码]*/[代码] [代码] [代码][代码]uploadSuccess:[代码][代码]function[代码][代码](uploadImage){[代码] [代码] [代码][代码]console.log([代码][代码]"外部获取到上传照片:"[代码] [代码]+ JSON.stringify(uploadImage.detail));[代码] [代码] [代码][代码]},[代码] [代码] [代码][代码]/**[代码] [代码] [代码][代码]* 删除图片的回调,返回已上传的图片数组[代码] [代码] [代码][代码]*/[代码] [代码] [代码][代码]deleteSuccess: [代码][代码]function[代码] [代码](uploadImage) {[代码] [代码] [代码][代码]console.log([代码][代码]"外部获取到删除后的照片:"[代码] [代码]+ JSON.stringify(uploadImage.detail));[代码] [代码] [代码][代码]},[代码] [代码] [代码][代码]/**[代码] [代码] [代码][代码]* 上传图片出错的回调[代码] [代码] [代码][代码]*/[代码] [代码] [代码][代码]uploadError:[代码][代码]function[代码][代码](res){[代码] [代码] [代码][代码]console.log([代码][代码]"上传出错:"[代码][代码]+res);[代码] [代码] [代码][代码]}[代码] [代码]})[代码] 参数说明 上传成功返回参数 [代码][[代码] [代码] [代码][代码]{[代码] [代码] [代码][代码]"localPath"[代码][代码]: [代码][代码]"http://tmp/wx00caa212d6710dcb.o6zAJs3oh85Zb1lJE8oWix57vny0.VzUQ2ebaMb87c6609a10aab7698d8645216baafb307e.jpg"[代码][代码],[代码] [代码] [代码][代码]"uploadResult"[代码][代码]: {[代码] [代码] [代码][代码]"hash"[代码][代码]: [代码][代码]"Fia6Y7gP4gXuaEsTfk5D9rslFWEz"[代码][代码],[代码] [代码] [代码][代码]"key"[代码][代码]: [代码][代码]"tmp/wx00caa212d6710dcb.o6zAJs3oh85Zb1lJE8oWix57vny0.VzUQ2ebaMb87c6609a10aab7698d8645216baafb307e.jpg"[代码][代码],[代码] [代码] [代码][代码]"imageURL"[代码][代码]: [代码][代码]"http://image.kucaroom.com/tmp/wx00caa212d6710dcb.o6zAJs3oh85Zb1lJE8oWix57vny0.VzUQ2ebaMb87c6609a10aab7698d8645216baafb307e.jpg"[代码] [代码] [代码][代码]}[代码] [代码] [代码][代码]}, {[代码] [代码] [代码][代码]"localPath"[代码][代码]: [代码][代码]"http://tmp/wx00caa212d6710dcb.o6zAJs3oh85Zb1lJE8oWix57vny0.2sYa1Iz3HXvM983982ba2e07d25e79212b11b8c75742.jpg"[代码][代码],[代码] [代码] [代码][代码]"uploadResult"[代码][代码]: {[代码] [代码] [代码][代码]"hash"[代码][代码]: [代码][代码]"FmNPIb1IJ9xraRdl26zXAjjyTjfz"[代码][代码],[代码] [代码] [代码][代码]"key"[代码][代码]: [代码][代码]"tmp/wx00caa212d6710dcb.o6zAJs3oh85Zb1lJE8oWix57vny0.2sYa1Iz3HXvM983982ba2e07d25e79212b11b8c75742.jpg"[代码][代码],[代码] [代码] [代码][代码]"imageURL"[代码][代码]: [代码][代码]"http://image.kucaroom.com/tmp/wx00caa212d6710dcb.o6zAJs3oh85Zb1lJE8oWix57vny0.2sYa1Iz3HXvM983982ba2e07d25e79212b11b8c75742.jpg"[代码] [代码] [代码][代码]}[代码] [代码] [代码][代码]}[代码] [代码]][代码] localPath:上传图片的本地路径 uploadResult:上传七牛后成功返回的参数 上传失败后返回的参数 [代码]{error: [代码][代码]"bad token"[代码][代码], imageURL: [代码][代码]"http://image.kucaroom.com/undefined"[代码][代码]}[代码] 3.效果图 [图片]
2018-12-28