- 小程序怎么支付到个人零钱?
体验码(已上线,非具体需求用户请勿支付,如误操作,请联系客服商家动态微信退款) [图片] 下面看下演示 [图片] 开通步骤: 1、首先你得有个营业执照 2、打开微信-我-支付-收付款-二维码收款-收款小账本(或者直接搜索小程序:收款小账本) [图片] 3、补充经营信息,开启商家服务,需要上传营业执照 4、审核通过后,继续收款小账本首页,下单助手、商家动态等去完善店铺信息 5、信息完善后点击【收款小账本】头部店铺名称,然后再点击商家小程序即可打开小商店助手,然后进入我的小程序,就能打开啦 6、剩下的就是店铺活动,各种信息完善了 Tips:此小程序名称格式必须是是【主营业务|地理区域】,然后店铺名称可被全网搜索到
2020-11-22 - 【高校开发者】简单分享下
简单分享下 写这篇文章主要是想跟刚迈入编程这条水泥路的小程序新手开发人员一起交流交流的,因为咱也只是个开发小程序的菜鸟人员,技术帖咱是写不来了,就只能跟大家唠唠嗑了。 1. 开篇 接触微信小程序也有一年多了,在这一年多的时间里也写过五、六个小程序,最初接触小程序是因为我们想通过小程序,来推广运营公众号和扩展公众号功能。 之后的开发就完全是因为好玩和兴趣了吧! 好玩??? 怎么玩? 大一大二咱大家刚接触算法编程,或许对算法编程是这样的: [图片] [图片] [图片] [图片] 而且经常会听到学这到底干什么用的呀! 好烦,这周数据结构又学了几个算法,二叉树?图?那行吧,咱就用这些个数据结构写个小程序吧! 又或者我们玩了一些好玩的小程序,那行吧,咱也试着用我们学过的算法知识在小程序上也写一个吧? 即使是些老掉牙的游戏,贪吃蛇、扫雷、连连看消消乐、成语接龙等等这些小游戏,实现后你还能在这些个游戏基础上发挥你的脑洞,进行创作改编。或许还能让你编个爆款小程序出来也说不定,是吧。 这些小游戏,小程序内部或多或少都用到了传说中的算法。 之所以选择用小程序来实现,还有一个最主要的原因就是小程序能够很轻易、很低调的就让我们秀一波。 小程序在真机上运行测试很容易,一个二维码就搞定,而且开发的小程序,不仅仅只是让我们本专业同学能够测测玩玩,还能够让更多非本专业的,好比你对象呀同学呀爸爸妈妈呀爷爷奶奶呀哥哥姐姐弟弟妹妹姑姑婶婶阿姨婆婆呀等等等等(只要他们有微信就行)都能够一起体验我们写的这些个小游戏呀。(o(∩_∩)o ) 所以在小程序开发过程中不仅学到了知识,还让我们见到了知识,玩到了知识,还能从中时不时的得到些个赞赏鼓励。你说这样子学习,你学不好才怪! 小程序还可以是一个表白神器,花点心思写一个专属 Ta 的独一无二的小程序,只给你的 Ta 开放个权限,再送给 Ta 比你花多少钱买个什么礼物都珍贵,你说我说的在理不!所以,你说小程序开发好不好,爱情学习双丰收呀。 2. 案例 好吧,上面废话有点多,下面先放几个自己做的小程序聊聊,素材什么的都是自己花心思画的(丑不丑无所谓,自己看着舒服就行),而且写一款完完全全凭自己感觉设计出来的小程序会让自己更有成就感。 2.1 反义词消消乐 反义词消消乐这个就是去年参加微信小程序应用开发赛做的一个小程序,为了增加游戏趣味性也增加了多人对战的功能。 反义词的逻辑匹配算法其实很简单,后台字词数据表,表中每条数据存储正、反两词,因此拥有共同的id值(int类型),前端获取到数据后只需将每条数据进行简单分割处理,可以让正意思词的标记值等于+id,反意思词的标记值等于-id,这样我们就能通过两标记值相加为0,来判断字词是否匹配成功。 游戏内的所有逻辑都交给小程序来判断运转,后端只是用来实现数据的存取,中转和传输。多人中前后端是使用 WebSocket 通道进行实时双向通信的,确保游戏内所有消息能够快速同步。逻辑如下: [图片] 简单解释下上图,当用户点击匹配后,发送信号与后台建立websocket连接,连接成功后传回连接的websocket的id值即sid,前端打包用户数据,sid,用户状态,用户转态就是此时是否已经退出游戏,发送给后端,后端保存信息,放入用户匹配池中,当准备就绪后,传回前端,前端发送匹配请求,后端再次开始为用户分配房间号,之后判断实时监听判断分配的房间是否满足两人,满足即可开始游戏逻辑。当游戏开始后,前端与后端的处理逻辑为如下所示: [图片] 上图是表示游戏匹配过程中的逻辑,其中打包小程序端发送的游戏信息其实就是用户点击反义词数据的状态信息,有助于后台判断分数加减等情况。服务器端的定向广播游戏信息,就是将处理好的分数等情况广播发送给定向房间内的用户。 反义词小程序整体流程大致是这么实现,而分配玩家的逻辑可以是按随机,按先到先服务,又或者按指定条件(如胜率分段等)将玩家分配到一起。 [图片] [图片] 2.2 困住小星星 困住小星星这个小程序,其玩法是模仿日本游戏设计师TaroIto2007年制作的“黑猫”(ChatNoir)游戏,而我在将其成功围住之后放了一些彩蛋,具体内容嘛就不说了 (✿◡‿◡),你们可以自己更改主题后随意发挥。 玩法就是游戏初始化墙的个数大概是9-13个之间。玩家需自己想办法点一个圈,目的就是要将其围住,不让她从边界跑掉即可。 小星星的寻路机制算法用到了最小路径和最大通路的算法,在每次寻路前先计算出各个非墙点的最小路径步数,以及最大通路步数,当最小路径步数相同时,就用最大通路步数来进行比较,最终找到最优路径,所以要想困住其实还是有点难的。 因为游戏中的地图是9*9,因此在最短路径算法中,其中点是(4,4),要计算到各边界的最短路径问题,可以从外往里开始计算。比如最外围,因为是边界,所以其路径长度为0,之后每往里一层,其路径长度就加1,直到到达主角位置。在不存在墙的情况下如下示: [图片] 最小路径: 其实要想计算出这个图的路径,我们不难发现,计算某个点的路径时(例如上图标红处),我们只需遍历找出每个点周围(即左、左上、右上、右、右下、左下)路径最小的值并加1,即是最终的最短路径长度。 如何实现?首先我们规定图中81个点初始path值可设为 -100,障碍物的path值可设为 100,边界path值可设为 0,主角位置可设为 999。之后再分别从四个大方向,即左上、右上、右下、左下这四个方向进行反复计算。 如何计算,以左上为例,左上计算即表示从左到右,从上到下,对各个点进行遍历。在遍历各点的同时,判断该点是否为障碍物,是则直接返回path的值为100,若该点为边界,则直接返回path的值为0。 如果都不是,则找出该点周围的6个点,并分别遍历周围的这6个点,判断这6个点的路径值,找出周围6个点路径的最小值min,min初值设为100。 如果筛选出来周围的点中存在没有计算过的点,即存在小于0的值,那需要等以后来计算他们的值,因此先不参与比较判断。而周围点的path值满足大于0的条件时,与min值比较,选出其中的最小值并赋给min,遍历完6个点后。当min值满足小于100的条件时,那么说明该点周围的最小值已经计算出来,直接将该点周围最小值路径值加1即为该点path值。 上面说的有点绕,直接上代码: [代码]calPath: function(location) { //计算路径 var row = location.row var col = location.col if (this.data.map_location[row][col] == 1) { //墙直接返回100 location.path = 100 return location.path } if (row == 0 || col == 0 || row == 8 || col == 8) { //边界直接返回0 location.path = 0 return location.path } var sixDir = this.calSixDir(location) //寻找周围的六个点 //遍历周围6个点,找出最小值 var min = 100 for (var i = 0; i < 6; i++) { if (sixDir[i].path >= 0) { // 存在点没有值,那需要等下次再来计算其值 var tmp = sixDir[i].path if (min > tmp) { min = tmp } } } if (min < 100) { location.path = min + 1 } else { location.path += 1 } return location.path }, [代码] 以此类推,从右上、右下、左下这三个方向进行计算,也都是相同的逻辑操作。 最大通路: 最大通路其实与最短路径的计算差不多,只是最大通路我们计算的是该点周围能走的个数,即寻找出该点周围6个点后,统计一下该点周围非墙的个数即可。因此计算时只需两个for循环遍历一遍图中所有点并分别计算一下即可。 [图片] [图片] 2.3 fly 拖鞋、摩斯密码 这个名字嘛fly 拖鞋,就是我随便取的。当时画素材的时候,就是随笔画了画涂了涂,看着有点像拖鞋就叫了 fly 拖鞋,这个游戏其实是用小游戏写的,游戏内容其实就跟fly bird一样。 开发这个游戏的过程中其实没用到什么算法,也没什么好说的。但用到了些物理知识,就是高中咱都学过的上抛与自由落体的公式,说这个就是想你知道写游戏的时候其实很经常用到物理知识。 这个摩斯密码,就是因为当时跟那谁谁谁聊起过摩斯密码,感觉那滴滴哒哒的也很神奇,而且又凑巧那天看到了个摩斯密码表,于是就照着那个表写了这个翻译器。所以用小程序写个小工具自己用还是很方便的。我觉得吧小程序是最适合自己写工具的,方便,而且干什么都行,就看你怎么用了。 [图片] [图片] 上面说那么多其实就想让学弟学妹们知道小程序可以这么玩。把我们所学的知识用可视化的形式体现出来,这可能比单纯的学习课本上的知识更有趣。 3.聊聊 小程序开发起来不会太难,在这个过程中其实也没有遇到太多大问题,遇到的bug无非就两种,要么语法错误,要么逻辑错误。 其实当遇到一个问题的时候,最好的解决办法就是官方文档了。这个真不是废话,很多时候遇到的bug其实就是我们对api的不熟悉,错用,用错而已,再不是,那就是咱自己代码逻辑错误了吧。 3.1 开发 开发个小程序的过程无非就这五个过程:问题—>分析—>设计—> 编码—>优化。 本人开发的心路历程首先就是自己要明白到底要开发个什么东西出来,之后便是去官方文档中简单查询下这些api,看看我们设计实现的这些个功能到底可不可行能不能实现。实现不了的,就换个思路看看有什么可替代的方案。 之后就是得想清楚,具体的实现步骤,实现逻辑,并分配好前后端的功能逻辑,之后再简单搭建小程序的整体框架,架构。我写的小程序其实大部分的实现逻辑都是在前端实现,后端我只是单纯的用来做些数据存取、中转等功能。 当然现在小程序的云开发,大大方便了我们,直接可以将数据放到云开发数据库上,用官方的原话讲就是一个既可在小程序前端操作,也能在云函数中读写的 JSON 数据库,而且这也大大简化了后台服务器的环境构建,运营维护等。可以减少很大的工作量。 最后再是动手编码实现我们的想法,将小程序的基础功能逻辑基本实现后,再慢慢的对其进行优化,完善。 其实我最喜欢就是完善和优化的这个过程,它能够让我很惬意的去设计、体验,将我们自己的小程序从粗糙的demo到精致的成品这个过程,是一件很有成就感的事。作出一个美美哒,精致的小程序,你就会连吃饭学习睡觉都感觉很舒畅。 3.2 收尾 最后总结就是,在开发过程中,可以先分析好功能逻辑,再开发个拥有主要功能的demo出来(先不管页面什么的设计有多难看),之后我们在这个demo的基础上一版版的优化修改,一步步迭代,最终成型。是的,小程序的开发就是这么容易,这么简单,这么好学,这么有趣。 还有就是要开发设计一个小程序其实不需要太多太复杂的功能,开发一个小程序的真谛就是简洁! 不仅仅是界面简洁,操作简洁,其实最主要的就是功能简洁,这或许也就是小程序设计的初衷吧。 最后还有就是遇到问题咱们首先确定一下是不是语法错误,再看看是不是逻辑错误,再不是,可以去文档上看看找找原因,文档还没有就去开发者社区里搜搜,开发者社区还没有的话可以先在这里面提个问题,最后咱们再去百度google,查查看,如果还没有解决方案的话。 那没办法了,只能开大招了—— 小黄鸭调试法! [图片] 在很久很久以前,有一个传说,传说中有一位程序大师,他随身携带了一只小黄鸭,每当在调试代码的时候会在桌上放上这只小黄鸭,然后详细地向鸭子解释每行代码…没了,这个传说就这么短,这就是传说中的小黄鸭调试发。 为什么呢?维基百科是这么解释的,小黄鸭调试法,又称橡皮鸭调试法,或者黄鸭除虫法,是在软件工程中使用的代码调试的一种方法,方法就是在程序调试,测试,除错过程中,操作人向小黄鸭耐心的解释每一行程序的作用,以此来激发灵感与发现矛盾 说白了就是回归带自己代码上,然后自言自语一翻。 你还别说,这个真管用,说出来更容易帮自己捋清楚思路,这个方法真的是屡试不爽,一直试一直爽! 要是你有幸能够把问题解决好了,最好可以记录一下踩过的坑那是最好的了,如果你再善良一点那就来开发者社区中分享一波吧。不管问题多简单,你要知道比你懂的少的人还是有很多的,他们那些新新手可能更需要的是咱们这些菜鸟新手的帮助吧。 最后再说一句话: [图片]
2019-05-27 - 微信同声传译小程序插件 —— 机器翻译、智能语音
开发文档:https://mp.weixin.qq.com/wxopen/plugindevdoc?appid=wx069ba97219f66d99&token=61191740&lang=zh_CN 插件功能 语音转文字 语音合成 文本翻译 具体使用案例可以查看面对面翻译小程序开源项目: https://github.com/Tencent/Face2FaceTranslator 简单DEMO实现: step 1:添加插件 在使用前,需要登录官网 设置 → 第三方服务 → 添加插件 搜索 【微信同声传译】并添加 [图片] 在需要使用插件的小程序 app.json 中指明需要使用的插件版本等信息 [代码]// app.json { ... "plugins": { ... "WechatSI": { "version": "0.0.6", "provider": "wx069ba97219f66d99" } }[代码] 接下来,在index.js引入插件,获取全局唯一的语音识别管理器recordRecoManager [代码]// index.js const plugin = requirePlugin("WechatSI") const manager = plugin.getRecordRecognitionManager() [代码] step 2:语音输入 希望做到的效果是按住某个按钮,开始识别语音,松开按钮就结束识别 [代码][代码][代码]<view catchtouchstart="streamRecord" catchtouchend="endStreamRecord">中文view> [代码] [代码]// index.js Page({ data: {}, streamRecord: function() { manager.start({ lang: 'zh_CN', }) }, streamRecordEnd: function() { manager.stop() } }) [代码] step 3:绑定录音回调事件 [代码][代码][代码] <view>语音识别内容:{{currentText}}view> [代码] [代码]// page.js Page({ data: { currentText: '', }, initRecord: function() { //有新的识别内容返回,则会调用此事件 manager.onRecognize = (res) => { let text = res.result this.setData({ currentText: text, }) } // 识别结束事件 manager.onStop = (res) => { let text = res.result if(text == '') { // 用户没有说话,可以做一下提示处理... return } this.setData({ currentText: text, }) // 得到完整识别内容就可以去翻译了 this.translateTextAction() } }, translateTextAction: function() {}, onLoad: function() { this.initRecord() } }) [代码] step 4:文本翻译 [代码][代码][代码]<view>翻译结果:{{translateText}}view> [代码] [代码]// page.js Page({ data: { currentText: '', translateText: '', }, translateTextAction: function() { let lfrom = 'zh_CN' let lto = 'en_US' plugin.translate({ lfrom: lfrom, lto: lto, content: this.data.currentText, tts: true, // 需要合成语音 success: (resTrans)=>{ // 翻译可以得到 翻译文本,翻译文本的合成语音,合成语音的过期时间 let text = resTrans.result this.setData({ translateText: text, }) // 得到合成语音让它自动播放出来 wx.playBackgroundAudio({ dataUrl: resTrans.filename, title: '', }) }, }) }, }) [代码] step 5:语音合成 plugin.translate得到的语音文件是有过期时间,可以download到本地使用。 如果像面对面翻译一样需要存比较多历史记录的话,也可以选择过期之后调用plugin.textToSpeech接口再去重新合成一次。 [代码] plugin.textToSpeech({ lang: 'zh_CN', content: '我想重新进行语音合成', success: resTrans => { // 可以重新得到语音合成文件和过期时间 }, }) [代码]
2018-08-13 - 又淘到一个图表库,阿里开源的,感觉比echarts更轻量,还好用,还多样
最近一直在寻找一个相对比较好的图表库做统计,之前用echarts,虽然满足了部分需求,但还是有些有点丑,后来多找找,终于找到了阿里开源的一款叫F2的图表库。 官方描述:F2 是一个专注于移动,开箱即用的可视化解决方案,完美支持 H5 环境同时兼容多种环境(node, 小程序,weex),完备的图形语法理论,满足你的各种可视化需求。专业的移动设计指引为你带来最佳的移动端图表体验。 演示:扫二维码 [图片]
2018-10-25 - O2小程序营销组件
wxapp-market 是一套好用、易扩展的小程序营销组件, 支持大转盘、刮刮乐、老虎机、水果机、九宫格翻纸牌、摇一摇、手势解锁等多种营销玩法。
2017-09-20 - 【U计划】弹幕biubiu小程序开发经验分享
弹幕biubiu小程序开发经验分享 Hello,大家好~我们是来自清华大学软件学院大三的弹幕弹幕团队,我是团队的Leader&Developer。我们团队开发的小程序叫作“弹幕biubiu”,主要应用场景是各类晚会现场。你可能已经发现了,我们的团队名和小程序名是不一样的,这是因为我们在确定了团队名称之后,发现这个名字已经被其他的小程序占用了,所以我们只能将小程序换成另一个名字。这也提醒了大家,在开发小程序的时候,一定要先确认自己起的名字没有被使用哦~ 我们的小程序是从去年10月开始开发的,直至今年3月基本完成。之后在今年4月的清华大学软件学院学生节上,我们的小程序作为观众弹幕互动平台被使用,并取得了广泛好评。这一方面说明我们小程序的实用性,另一方面也说明了弹幕互动及其衍生方向依然有很大的发展空间。 [图片] 我们团队的开发选用了敏捷开发的方式,并采用Scrum框架(下图源自清华大学软件学院刘强老师的软件工程课件)。本文将介绍我们团队在开发过程中所做的一些主要工作,希望能够给大家一些启发与帮助。[图片] 1.立项 万事开头难,开发过程中最困难的地方,往往就是在最开始的地方。一个团队中不缺技术人员,而缺少设计人员,也就是“有思想的人”。而且好的想法一定是来源于生活的,如果不仔细观察生活,只是天马行空地构想,是无法获得好的项目主题的。 我们团队在计划开发一个小程序之后,就开始讨论主题。首先我们确定了我们小程序的大致方向。我们发现在每次举办院系学生节时,都需要科协同学用一天的时间去部署弹幕墙,这样效率较低,而且也常常出现弹幕墙宕机的情况,所以我们决定开发一个学生节小程序。之后我们团队通过头脑风暴,将自己设想为学生节举办方与学生节观众,讨论我们可能需要哪些功能,不需要哪些功能等等,从而将项目目标进一步细化。 在这里我们并不能只单纯地讨论,我们需要一个记录者,将所有人的想法记录下来并进行归整,之后再由每个成员进行修改完善,得到我们开发的第一份文档——产品规划文档(弹幕biubiu的产品规划文档)。如果大家对产品规划文档形式不太清楚的话,可以参照上述我们的文档。在文档中我们对于产品的定位、产品的特性以及产品的路线都有了一个明确的描述。 当我们有了产品规划文档之后,立项的过程还没有结束。因为这个文档只是根据自己团队的想法写成的,但是真正的用户会有成千甚至上万人,并不一定每个人都和团队内的成员想法相同。除此之外,市场上可能已经有一些类似的产品。所以我们必须要进行一个调查,明确其他可能的用户的需求以及现有市场上的产品提供的功能。这样的调查有助于我们跳出团队内固有的思维模式,催生出一些新的点子,同时也能避免无用功。在调查结束之后,我们获得了更多的用户需求。我们需要对需求进一步整理细化,写出用户故事(弹幕biubiu的需求获取与用户故事文档),并画出用户故事地图。 [图片] 到此为止,我们基本完成了所有立项工作。这时整个团队应当对自己的项目开发目标有了明确清晰的认知。 2.设计 当明确需求之后,我们就要开始设计工作,也就是进入到敏捷开发的迭代周期中了。设计主要分为两部分: 系统设计 原型设计 系统设计中最重要的工具是UML,即统一建模语言。你可能会用到其中的类图、活动图、用例图等。 2.1 系统设计 系统设计目的是确立技术开发过程中的总纲,这也是开发过程中极为重要的一步,整个开发过程都是围绕系统设计文档展开的。 我们团队开发的小程序使用的是MVC模式,即模型(model)-视图(view)-控制器(controller)。这种模式满足了高内聚、低耦合的程序结构,便于团队开发与管理。 系统设计要求我们首先对于整体系统结构有一个清晰的构想。我们的弹幕小程序的系统架构图如下所示,可以看到这里我们将系统清晰地分为了数层。 [图片] 之后我们就需要对系统的结构进行细化,主要包括两部分内容: 数据存储结构。也就是数据库的设计。我们用一个数据库来管理数据,那么我们需要构造哪些表,每个表中需要保存那些数据等等,都是我们需要考虑的问题。我们团队采用了Mysql+Redis两种数据库相结合的存储模式,保证了数据的读写效率。 前后端接口设计。接口设计可以方便团队前后端开发的分离,提高开发效率。我们团队采用的是Restful的API接口规范,大家可以自行查阅了解该规范的内容。 因为不同的小程序会有不同的系统,所以我这里的设计思路也仅供大家参考,主要的还是要开发团队自己思索并设计,得到最适合自己的系统结构。当然合适的系统架构不意味着在项目的最初就要将所有细节想得十分透彻。一个好的系统架构主要有两方面的特征:稳定的框架与可扩展性。稳定的框架保证了开发过程中无需对代码进行很大程度的调整重构;可扩展性保证了开发人员可以很轻松地将后续的内容添加进系统,而不会影响系统整体的特性。 2.2 原型设计 原型设计,也就是UI设计。我们团队使用的工具是墨刀。墨刀有着丰富的素材库,并且可以设计控件行为,方便团队成员理解交互过程。 [图片] 原型设计往往会是团队中讨论最激烈的环节,因为每个人的审美是不同的,更何况团队中基本都是理工生(sigh…)。我们在原型设计时也进行了多次讨论与修改,才最终确定其样式。 3.开发 3.1 团队管理 自组织团队是敏捷开发的基础,团队被授权自己管理工作进程,并决定如何完成工作。团队成员在开发的过程中需要各司其职,扮演好自己的角色。但是根据著名的“20%定律”,每个团队中总会有20%的成员是free rider,所以这就需要团队的领导者对团队进行良好管理。 在开发的初期,一个团队需要制定自己团队的开发章程,包括每周的开会时间、开会地点、每个成员负责开发的模块、团建安排等,并在之后的开发过程中严格按照章程的规定管理团队。 其次,团队在每次例会时,需要每名成员汇报之前任务的开发进度,对开发过程中遇到的问题进行讨论思考,并确定下一阶段的开发任务。每次的例会都需要指定一名成员记录会议内容,方便团队日后查看。 团队管理中,最主要的就是任务安排的部分。任务安排主要包括两点:明确分工与时间规划。 明确分工是要让大家清楚自己具体是要做什么,其重点在于“细化”。举个例子,如果你和我说,“你去做一个主办方管理网站”,我肯定一头雾水无从下手;但是如果你和我说:“你去实现一个主办方登录的功能,主办方输入用户名和密码就可以跳转到活动列表页面”,那我就可以很快地完成这一个任务。所以明确分工是团队成员,尤其是组织者,需要重点注意的。 时间规划则是让大家有一个紧迫感。做时间规划最好的方法是,组织者先定一个大概的时间,然后所有团队成员进行协商,定出每个人都满意或至少不反对的时间安排。因为团队成员都会有惰性,就算最好的团队也不例外,所以一个明确的时间规划可以让每个人有计划有安排地完成任务。从这个意义上来讲,时间规划也是调动成员热情的不错的方案。 3.2 代码管理与持续集成 我们团队使用git进行代码版本的控制管理,在开发过程中维护了三个代码库,分别对应于系统后端、微信小程序以及弹幕主墙应用程序。我们也利用Github上的Issues、Projects、Wiki等功能辅助我们进行开发。由于我们团队尚未开源,所以这里也不方便向大家展示代码库的具体细节。 此外,我们团队使用Travis CI辅助我们进行代码的持续集成与自动部署,感兴趣的话大家可以自主学习一下它的使用方法。 3.3 文档管理 通过上文我们也发现了,在开发过程中我们会写很多的文档,所以合理的文档管理也是开发中的重点问题。我们团队使用的在线文档工具是石墨文档。石墨文档有三个优点: 有清晰简洁的界面与丰富的功能 支持多成员在线编辑 可以很方便地导出为word文档与pdf文档 我们团队还维护了一个产品文档目录,这样每次要修改或查阅文档时,都有一个很便捷的入口。 [图片] 4.测试 测试主要有三部分:单元测试、功能测试与性能测试。 单元测试。单元测试,就是对软件中最小可测试单元进行检查和验证。不同软件的单元测试是不同的,比如我们在开发后端时,使用的是Python中的Django框架,这一框架是自带单元测试模块的,所以我们只需在test.py中实现所有测试样例即可。单元测试保证了软件最基本的正确性,最佳的模式是开发者在开发的过程中就将单元测试样例写好。(现在微信小程序还没有单元测试的模块,希望之后小程序团队可以在这方面给出接口。) 功能测试。功能测试就是要测试软件系统的各个功能能否正常执行。功能测试的辅助软件有很多,但最简单也最方便的就是人工手动测试,也就是开发者模拟用户的使用场景测试一遍自己的软件系统。 性能测试。软件性能也是评判一个软件好坏的重要依据。就以我们的弹幕小程序为例,虽然现在的学生节晚会只有三百多人,但是如果要拓展到所有晚会时,就不得不考虑高并发的情况。所以我们团队使用Jmeter对于发送弹幕的功能进行了性能测试,并在测试之后通过图片压缩等方式提高了我们小程序的性能。 除此之外,测试环节还包括安全性测试、易用性测试、兼容性测试等。测试过程中大家需要尤其注意的地方是:一定要将测试场景与测试样例想全面。越是严密的测试,软件系统也就相应越理想。 5.分析与维护 在开发与测试结束之后,小程序也就被正式投入使用了。因为用户行为是多种多样的,所以这个时候不出意外会出现一些奇奇怪怪的bug。作为开发者一定要给出一个用户反馈的途径,并且根据用户反馈的问题,制定下一个迭代周期的任务。这样循环往复,直至软件达到预期。下图为我们小程序为用户提供的反馈接口: [图片] 6.总结 以上就是我在开发过程中的一些经验与体会,希望能够给大家一些帮助与启示。弹幕biubiu小程序的开发,对于我来说是一个特别宝贵的经历。在这个过程中我学到了很多新的知识,接触到了很多新的事物,也发现了其他同学很多的优点。同时也很感谢刘强与刘璘两位老师对我们团队的支持与指导,在这里也推荐一下两位老师在学堂在线上的软件工程课程,如果大家感兴趣的话可以去了解学习一下,相信会给你们很大的帮助。 附言 如果大家对我们的小程序感兴趣的话,也可以使用一下呀~ 使用说明 主办方管理网站 应用程序下载链接(也可在主办方管理网站中下载) 小程序二维码 [图片] 大家有什么问题或者建议的话,也欢迎随时与我交流~ 我的Github地址是:https://github.com/JL-Cheng 我的邮箱是:chengjl16@163.com
2019-05-23 - CSS3 Animation动画的十二原则
作为前端的设计师和工程师,我们用 CSS 去做样式、定位并创建出好看的网站。我们经常用 CSS 去添加页面的运动过渡效果甚至动画,但我们经常做的不过如此。 [代码] 动效是一个有助于访客和用户理解我们设计的强有力工具。这里有些原则能最大限度地应用在我们的工作中。 迪士尼经过基础工作练习的长时间累积,在 1981 年出版的 The Illusion of Life: Disney Animation 一书中发表了动画的十二个原则 ([] (https://en.wikipedia.org/wiki/12_basic_principles_of_animation)) 。这些原则描述了动画能怎样用于让观众相信自己沉浸在现实世界中。 [代码] 在本文中,我会逐个介绍这十二个原则,并讨论它们怎样运用在网页中。你能在 Codepen 找到它们[] (https://codepen.io/collection/AxKOdY/)。 挤压和拉伸 (Squash and stretch) [图片] 这是物体存在质量且运动时质量保持不变的概念。当一个球在弹跳时,碰击到地面会变扁,恢复的时间会越来越短。 [代码] 创建对象的时候最有用的方法是参照实物,比如人、时钟和弹性球。 当它和网页元件一起工作时可能会忽略这个原则。DOM 对象不一定和实物相关,它会按需要在屏幕上缩放。例如,一个按钮会变大并变成一个信息框,或者错误信息会出现和消失。 尽管如此,挤压和伸缩效果可以为一个对象增加实物的感觉。甚至一些形状上的小变化就可以创造出细微但抢眼的效果。 HTML [代码] [代码] <h1>Principle 1: Squash and stretch</h1> <h2><a href="https://cssanimation.rocks/principles/" target="_parent">Animation Principles for the Web</h2> <article class="principle one"> <div class="shape"></div> <div class="surface"></div> </article> [代码] CSS [代码].one .shape { animation: one 4s infinite ease-out; } .one .surface { background: #000; height: 10em; width: 1em; position: absolute; top: calc(50% - 4em); left: calc(50% + 10em); } @keyframes one { 0%, 15% { opacity: 0; } 15%, 25% { transform: none; animation-timing-function: cubic-bezier(1,-1.92,.95,.89); width: 4em; height: 4em; top: calc(50% - 2em); left: calc(50% - 2em); opacity: 1; } 35%, 45% { transform: translateX(8em); height: 6em; width: 2em; top: calc(50% - 3em); animation-timing-function: linear; opacity: 1; } 70%, 100% { transform: translateX(8em) translateY(5em); height: 6em; width: 2em; top: calc(50% - 3em); opacity: 0; } } body { margin: 0; background: #e9b59f; font-family: HelveticaNeue, Arial, Sans-serif; color: #fff; } h1 { position: absolute; top: 0; left: 0; right: 0; text-align: center; font-weight: 300; } h2 { font-size: 0.75em; position: absolute; bottom: 0; left: 0; right: 0; text-align: center; } a { text-decoration: none; color: #333; } .principle { width: 100%; height: 100vh; position: relative; } .shape { background: #2d97db; border: 1em solid #fff; width: 4em; height: 4em; position: absolute; top: calc(50% - 2em); left: calc(50% - 2em); } [代码] 预备动作 (Anticipation) [图片] 运动不倾向于突然发生。在现实生活中,无论是一个球在掉到桌子前就开始滚动,或是一个人屈膝准备起跳,运动通常有着某种事先的累积。 [代码] 我们能用它去让我们的过渡动画显得更逼真。预备动作可以是一个细微的反弹,帮人们理解什么对象将在屏幕中发生变化并留下痕迹。 例如,悬停在一个元件上时可以在它变大前稍微缩小,在初始列表中添加额外的条目来介绍其它条目的移除方法。 [代码] HTML [代码]<h1>Principle 2: Anticipation</h1> <h2><a href="https://cssanimation.rocks/principles/" target="_parent">Animation Principles for the Web</h2> <article class="principle two"> <div class="shape"></div> <div class="surface"></div> </article> [代码] CSS [代码].two .shape { animation: two 5s infinite ease-out; transform-origin: 50% 7em; } .two .surface { background: #000; width: 8em; height: 1em; position: absolute; top: calc(50% + 4em); left: calc(50% - 3em); } @keyframes two { 0%, 15% { opacity: 0; transform: none; } 15%, 25% { opacity: 1; transform: none; animation-timing-function: cubic-bezier(.5,.05,.91,.47); } 28%, 38% { transform: translateX(-2em); } 40%, 45% { transform: translateX(-4em); } 50%, 52% { transform: translateX(-4em) rotateZ(-20deg); } 70%, 75% { transform: translateX(-4em) rotateZ(-10deg); } 78% { transform: translateX(-4em) rotateZ(-24deg); opacity: 1; } 86%, 100% { transform: translateX(-6em) translateY(4em) rotateZ(-90deg); opacity: 0; } } /* General styling */ body { margin: 0; background: #e9b59f; font-family: HelveticaNeue, Arial, Sans-serif; color: #fff; } h1 { position: absolute; top: 0; left: 0; right: 0; text-align: center; font-weight: 300; } h2 { font-size: 0.75em; position: absolute; bottom: 0; left: 0; right: 0; text-align: center; } a { text-decoration: none; color: #333; } .principle { width: 100%; height: 100vh; position: relative; } .shape { background: #2d97db; border: 1em solid #fff; width: 4em; height: 4em; position: absolute; top: calc(50% - 2em); left: calc(50% - 2em); } [代码] 演出布局 (Staging) [图片] 演出布局是确保对象在场景中得以聚焦,让场景中的其它对象和视觉在主动画发生的地方让位。这意味着要么把主动画放到突出的位置,要么模糊其它元件来让用户专注于看他们需要看的东西。 [代码] 在网页方面,一种方法是用 model 覆盖在某些内容上。在现有页面添加一个遮罩并把那些主要关注的内容前置展示。 另一种方法是用动作。当很多对象在运动,你很难知道哪些值得关注。如果其它所有的动作停止,只留一个在运动,即使动得很微弱,这都可以让对象更容易被察觉。 [代码] 还有一种方法是做一个晃动和闪烁的按钮来简单地建议用户比如他们可能要保存文档。屏幕保持静态,所以再细微的动作也会突显出来。 HTML [代码]<h1>Principle 3: Staging</h1> <h2><a href="https://cssanimation.rocks/principles/" target="_parent">Animation Principles for the Web</h2> <article class="principle three"> <div class="shape a"></div> <div class="shape b"></div> <div class="shape c"></div> </article> [代码] CSS [代码].three .shape.a { transform: translateX(-12em); } .three .shape.c { transform: translateX(12em); } .three .shape.b { animation: three 5s infinite ease-out; transform-origin: 0 6em; } .three .shape.a, .three .shape.c { animation: threeb 5s infinite linear; } @keyframes three { 0%, 10% { transform: none; animation-timing-function: cubic-bezier(.57,-0.5,.43,1.53); } 26%, 30% { transform: rotateZ(-40deg); } 32.5% { transform: rotateZ(-38deg); } 35% { transform: rotateZ(-42deg); } 37.5% { transform: rotateZ(-38deg); } 40% { transform: rotateZ(-40deg); } 42.5% { transform: rotateZ(-38deg); } 45% { transform: rotateZ(-42deg); } 47.5% { transform: rotateZ(-38deg); animation-timing-function: cubic-bezier(.57,-0.5,.43,1.53); } 58%, 100% { transform: none; } } @keyframes threeb { 0%, 20% { filter: none; } 40%, 50% { filter: blur(5px); } 65%, 100% { filter: none; } } /* General styling */ body { margin: 0; background: #e9b59f; font-family: HelveticaNeue, Arial, Sans-serif; color: #fff; } h1 { position: absolute; top: 0; left: 0; right: 0; text-align: center; font-weight: 300; } h2 { font-size: 0.75em; position: absolute; bottom: 0; left: 0; right: 0; text-align: center; } a { text-decoration: none; color: #333; } .principle { width: 100%; height: 100vh; position: relative; } .shape { background: #2d97db; border: 1em solid #fff; width: 4em; height: 4em; position: absolute; top: calc(50% - 2em); left: calc(50% - 2em); } [代码] 连续运动和姿态对应 (Straight-Ahead Action and Pose-to-Pose) [图片] 连续运动是绘制动画的每一帧,姿态对应是通常由一个 assistant 在定义一系列关键帧后填充间隔。 [代码] 大多数网页动画用的是姿态对应:关键帧之间的过渡可以通过浏览器在每个关键帧之间的插入尽可能多的帧使动画流畅。 [代码] 有一个例外是定时功能step。通过这个功能,浏览器 “steps” 可以把尽可能多的无序帧串清晰。你可以用这种方式绘制一系列图片并让浏览器按顺序显示出来,这开创了一种逐帧动画的风格。 HTML [代码]<h1>Principle 4: Straight Ahead Action and Pose to Pose</h1> <h2><a href="https://cssanimation.rocks/principles/" target="_parent">Animation Principles for the Web</h2> <article class="principle four"> <div class="shape a"></div> <div class="shape b"></div> </article> [代码] CSS [代码].four .shape.a { left: calc(50% - 8em); animation: four 6s infinite cubic-bezier(.57,-0.5,.43,1.53); } .four .shape.b { left: calc(50% + 8em); animation: four 6s infinite steps(1); } @keyframes four { 0%, 10% { transform: none; } 26%, 30% { transform: rotateZ(-45deg) scale(1.25); } 40% { transform: rotateZ(-45deg) translate(2em, -2em) scale(1.8); } 50%, 75% { transform: rotateZ(-45deg) scale(1.1); } 90%, 100% { transform: none; } } /* General styling */ body { margin: 0; background: #e9b59f; font-family: HelveticaNeue, Arial, Sans-serif; color: #fff; } h1 { position: absolute; top: 0; left: 0; right: 0; text-align: center; font-weight: 300; } h2 { font-size: 0.75em; position: absolute; bottom: 0; left: 0; right: 0; text-align: center; } a { text-decoration: none; color: #333; } .principle { width: 100%; height: 100vh; position: relative; } .shape { background: #2d97db; border: 1em solid #fff; width: 4em; height: 4em; position: absolute; top: calc(50% - 2em); left: calc(50% - 2em); } [代码] 跟随和重叠动作 (Follow Through and Overlapping Action) [图片] 事情并不总在同一时间发生。当一辆车从急刹到停下,车子会向前倾、有烟从轮胎冒出来、车里的司机继续向前冲。 [代码] 这些细节是跟随和重叠动作的例子。它们在网页中能被用作帮助强调什么东西被停止,并不会被遗忘。例如一个条目可能在滑动时稍滑微远了些,但它自己会纠正到正确位置。 要创造一个重叠动作的感觉,我们可以让元件以稍微不同的速度移动到每处。这是一种在 iOS 系统的视窗 (View) 过渡中被运用得很好的方法。一些按钮和元件以不同速率运动,整体效果会比全部东西以相同速率运动要更逼真,并留出时间让访客去适当理解变化。 [代码] 在网页方面,这可能意味着让过渡或动画的效果以不同速度来运行。 HTML [代码]<h1>Principle 5: Follow Through and Overlapping Action</h1> <h2><a href="https://cssanimation.rocks/principles/" target="_parent">Animation Principles for the Web</h2> <article class="principle five"> <div class="shape-container"> <div class="shape"></div> </div> </article> [代码] CSS [代码].five .shape { animation: five 4s infinite cubic-bezier(.64,-0.36,.1,1); position: relative; left: auto; top: auto; } .five .shape-container { animation: five-container 4s infinite cubic-bezier(.64,-0.36,.1,2); position: absolute; left: calc(50% - 4em); top: calc(50% - 4em); } @keyframes five { 0%, 15% { opacity: 0; transform: translateX(-12em); } 15%, 25% { transform: translateX(-12em); opacity: 1; } 85%, 90% { transform: translateX(12em); opacity: 1; } 100% { transform: translateX(12em); opacity: 0; } } @keyframes five-container { 0%, 35% { transform: none; } 50%, 60% { transform: skewX(20deg); } 90%, 100% { transform: none; } } /* General styling */ body { margin: 0; background: #e9b59f; font-family: HelveticaNeue, Arial, Sans-serif; color: #fff; } h1 { position: absolute; top: 0; left: 0; right: 0; text-align: center; font-weight: 300; } h2 { font-size: 0.75em; position: absolute; bottom: 0; left: 0; right: 0; text-align: center; } a { text-decoration: none; color: #333; } .principle { width: 100%; height: 100vh; position: relative; } .shape { background: #2d97db; border: 1em solid #fff; width: 4em; height: 4em; position: absolute; top: calc(50% - 2em); left: calc(50% - 2em); } [代码] 缓入缓出 (Slow In and Slow Out) [图片] 对象很少从静止状态一下子加速到最大速度,它们往往是逐步加速并在停止前变慢。没有加速和减速,动画感觉就像机器人。 [代码] 在 CSS 方面,缓入缓出很容易被理解,在一个动画过程中计时功能是一种描述变化速率的方式。 [代码] 使用计时功能,动画可以由慢加速 (ease-in)、由快减速 (ease-out),或者用贝塞尔曲线做出更复杂的效果。 HTML [代码]<h1>Principle 6: Slow in and Slow out</h1> <h2><a href="https://cssanimation.rocks/principles/" target="_parent">Animation Principles for the Web</h2> <article class="principle six"> <div class="shape a"></div> </article> [代码] CSS [代码].six .shape { animation: six 3s infinite cubic-bezier(0.5,0,0.5,1); } @keyframes six { 0%, 5% { transform: translate(-12em); } 45%, 55% { transform: translate(12em); } 95%, 100% { transform: translate(-12em); } } /* General styling */ body { margin: 0; background: #e9b59f; font-family: HelveticaNeue, Arial, Sans-serif; color: #fff; } h1 { position: absolute; top: 0; left: 0; right: 0; text-align: center; font-weight: 300; } h2 { font-size: 0.75em; position: absolute; bottom: 0; left: 0; right: 0; text-align: center; } a { text-decoration: none; color: #333; } .principle { width: 100%; height: 100vh; position: relative; } .shape { background: #2d97db; border: 1em solid #fff; width: 4em; height: 4em; position: absolute; top: calc(50% - 2em); left: calc(50% - 2em); } [代码] 弧线运动 (Arc) [图片] 虽然对象是更逼真了,当它们遵循「缓入缓出」的时候它们很少沿直线运动——它们倾向于沿弧线运动。 我们有几种 CSS 的方式来实现弧线运动。一种是结合多个动画,比如在弹力球动画里,可以让球上下移动的同时让它右移,这时候球的显示效果就是沿弧线运动。 HTML [代码]<h1>Principle 7: Arc (1)</h1> <h2><a href="https://cssanimation.rocks/principles/" target="_parent">Animation Principles for the Web</h2> <article class="principle sevena"> <div class="shape-container"> <div class="shape a"></div> </div> </article> [代码] CSS [代码].sevena .shape-container { animation: move-right 6s infinite cubic-bezier(.37,.55,.49,.67); position: absolute; left: calc(50% - 4em); top: calc(50% - 4em); } .sevena .shape { animation: bounce 6s infinite linear; border-radius: 50%; position: relative; left: auto; top: auto; } @keyframes move-right { 0% { transform: translateX(-20em); opacity: 1; } 80% { opacity: 1; } 90%, 100% { transform: translateX(20em); opacity: 0; } } @keyframes bounce { 0% { transform: translateY(-8em); animation-timing-function: cubic-bezier(.51,.01,.79,.02); } 15% { transform: translateY(8em); animation-timing-function: cubic-bezier(.19,1,.7,1); } 25% { transform: translateY(-4em); animation-timing-function: cubic-bezier(.51,.01,.79,.02); } 32.5% { transform: translateY(8em); animation-timing-function: cubic-bezier(.19,1,.7,1); } 40% { transform: translateY(0em); animation-timing-function: cubic-bezier(.51,.01,.79,.02); } 45% { transform: translateY(8em); animation-timing-function: cubic-bezier(.19,1,.7,1); } 50% { transform: translateY(3em); animation-timing-function: cubic-bezier(.51,.01,.79,.02); } 56% { transform: translateY(8em); animation-timing-function: cubic-bezier(.19,1,.7,1); } 60% { transform: translateY(6em); animation-timing-function: cubic-bezier(.51,.01,.79,.02); } 64% { transform: translateY(8em); animation-timing-function: cubic-bezier(.19,1,.7,1); } 66% { transform: translateY(7.5em); animation-timing-function: cubic-bezier(.51,.01,.79,.02); } 70%, 100% { transform: translateY(8em); animation-timing-function: cubic-bezier(.19,1,.7,1); } } /* General styling */ body { margin: 0; background: #e9b59f; font-family: HelveticaNeue, Arial, Sans-serif; color: #fff; } h1 { position: absolute; top: 0; left: 0; right: 0; text-align: center; font-weight: 300; } h2 { font-size: 0.75em; position: absolute; bottom: 0; left: 0; right: 0; text-align: center; } a { text-decoration: none; color: #333; } .principle { width: 100%; height: 100vh; position: relative; } .shape { background: #2d97db; border: 1em solid #fff; width: 4em; height: 4em; position: absolute; top: calc(50% - 2em); left: calc(50% - 2em); } [代码] [图片] 另外一种是旋转元件,我们可以设置一个在对象之外的原点来作为它的旋转中心。当我们旋转这个对象,它看上去就是沿着弧线运动。 HTML [代码]<h1>Principle 7: Arc (2)</h1> <h2><a href="https://cssanimation.rocks/principles/" target="_parent">Animation Principles for the Web</h2> <article class="principle sevenb"> <div class="shape a"></div> <div class="shape b"></div> </article> [代码] CSS [代码].sevenb .shape.a { animation: sevenb 3s infinite linear; top: calc(50% - 2em); left: calc(50% - 9em); transform-origin: 10em 50%; } .sevenb .shape.b { animation: sevenb 6s infinite linear reverse; background-color: yellow; width: 2em; height: 2em; left: calc(50% - 1em); top: calc(50% - 1em); } @keyframes sevenb { 100% { transform: rotateZ(360deg); } } /* General styling */ body { margin: 0; background: #e9b59f; font-family: HelveticaNeue, Arial, Sans-serif; color: #fff; } h1 { position: absolute; top: 0; left: 0; right: 0; text-align: center; font-weight: 300; } h2 { font-size: 0.75em; position: absolute; bottom: 0; left: 0; right: 0; text-align: center; } a { text-decoration: none; color: #333; } .principle { width: 100%; height: 100vh; position: relative; } .shape { background: #2d97db; border: 1em solid #fff; width: 4em; height: 4em; position: absolute; top: calc(50% - 2em); left: calc(50% - 2em); } [代码] 次要动作 (Secondary Action) [图片] 虽然主动画正在发生,次要动作可以增强它的效果。这就好比某人在走路的时候摆动手臂和倾斜脑袋,或者弹性球弹起的时候扬起一些灰尘。 在网页方面,当主要焦点出现的时候就可以开始执行次要动作,比如拖拽一个条目到列表中间。 HTML [代码]<h1>Principle 8: Secondary Action</h1> <h2><a href="https://cssanimation.rocks/principles/" target="_parent">Animation Principles for the Web</h2> <article class="principle eight"> <div class="shape a"></div> <div class="shape b"></div> <div class="shape c"></div> </article> [代码] CSS [代码].eight .shape.a { transform: translateX(-6em); animation: eight-shape-a 4s cubic-bezier(.57,-0.5,.43,1.53) infinite; } .eight .shape.b { top: calc(50% + 6em); opacity: 0; animation: eight-shape-b 4s linear infinite; } .eight .shape.c { transform: translateX(6em); animation: eight-shape-c 4s cubic-bezier(.57,-0.5,.43,1.53) infinite; } @keyframes eight-shape-a { 0%, 50% { transform: translateX(-5.5em); } 70%, 100% { transform: translateX(-10em); } } @keyframes eight-shape-b { 0% { transform: none; } 20%, 30% { transform: translateY(-1.5em); opacity: 1; animation-timing-function: cubic-bezier(.57,-0.5,.43,1.53); } 32% { transform: translateY(-1.25em); opacity: 1; } 34% { transform: translateY(-1.75em); opacity: 1; } 36%, 38% { transform: translateY(-1.25em); opacity: 1; } 42%, 60% { transform: translateY(-1.5em); opacity: 1; } 75%, 100% { transform: translateY(-8em); opacity: 1; } } @keyframes eight-shape-c { 0%, 50% { transform: translateX(5.5em); } 70%, 100% { transform: translateX(10em); } } /* General styling */ body { margin: 0; background: #e9b59f; font-family: HelveticaNeue, Arial, Sans-serif; color: #fff; } h1 { position: absolute; top: 0; left: 0; right: 0; text-align: center; font-weight: 300; } h2 { font-size: 0.75em; position: absolute; bottom: 0; left: 0; right: 0; text-align: center; } a { text-decoration: none; color: #333; } .principle { width: 100%; height: 100vh; position: relative; } .shape { background: #2d97db; border: 1em solid #fff; width: 4em; height: 4em; position: absolute; top: calc(50% - 2em); left: calc(50% - 2em); } [代码] 时间节奏 (Timing) [图片] 动画的时间节奏是需要多久去完成,它可以被用来让看起来很重的对象做很重的动画,或者用在添加字符的动画中。 [代码] 这在网页上可能只要简单调整 animation-duration 或 transition-duration 值。 [代码] 这很容易让动画消耗更多时间,但调整时间节奏可以帮动画的内容和交互方式变得更出众。 HTML [代码]<h1>Principle 9: Timing</h1> <h2><a href="https://cssanimation.rocks/principles/" target="_parent">Animation Principles for the Web</h2> <article class="principle nine"> <div class="shape a"></div> <div class="shape b"></div> </article> [代码] CSS [代码].nine .shape.a { animation: nine 4s infinite cubic-bezier(.93,0,.67,1.21); left: calc(50% - 12em); transform-origin: 100% 6em; } .nine .shape.b { animation: nine 2s infinite cubic-bezier(1,-0.97,.23,1.84); left: calc(50% + 2em); transform-origin: 100% 100%; } @keyframes nine { 0%, 10% { transform: translateX(0); } 40%, 60% { transform: rotateZ(90deg); } 90%, 100% { transform: translateX(0); } } /* General styling */ body { margin: 0; background: #e9b59f; font-family: HelveticaNeue, Arial, Sans-serif; color: #fff; } h1 { position: absolute; top: 0; left: 0; right: 0; text-align: center; font-weight: 300; } h2 { font-size: 0.75em; position: absolute; bottom: 0; left: 0; right: 0; text-align: center; } a { text-decoration: none; color: #333; } .principle { width: 100%; height: 100vh; position: relative; } .shape { background: #2d97db; border: 1em solid #fff; width: 4em; height: 4em; position: absolute; top: calc(50% - 2em); left: calc(50% - 2em); } [代码] 夸张手法 (Exaggeration) [图片] 夸张手法在漫画中是最常用来为某些动作刻画吸引力和增加戏剧性的,比如一只狼试图把自己的喉咙张得更开地去咬东西可能会表现出更恐怖或者幽默的效果。 在网页中,对象可以通过上下滑动去强调和刻画吸引力,比如在填充表单的时候生动部分会比收缩和变淡的部分更突出。 HTML [代码]<h1>Principle 10: Exaggeration</h1> <h2><a href="https://cssanimation.rocks/principles/" target="_parent">Animation Principles for the Web</h2> <article class="principle ten"> <div class="shape"></div> </article> [代码] CSS [代码].ten .shape { animation: ten 4s infinite linear; transform-origin: 50% 8em; top: calc(50% - 6em); } @keyframes ten { 0%, 10% { transform: none; animation-timing-function: cubic-bezier(.87,-1.05,.66,1.31); } 40% { transform: rotateZ(-45deg) scale(2); animation-timing-function: cubic-bezier(.16,.54,0,1.38); } 70%, 100% { transform: rotateZ(360deg) scale(1); } } /* General styling */ body { margin: 0; background: #e9b59f; font-family: HelveticaNeue, Arial, Sans-serif; color: #fff; } h1 { position: absolute; top: 0; left: 0; right: 0; text-align: center; font-weight: 300; } h2 { font-size: 0.75em; position: absolute; bottom: 0; left: 0; right: 0; text-align: center; } a { text-decoration: none; color: #333; } .principle { width: 100%; height: 100vh; position: relative; } .shape { background: #2d97db; border: 1em solid #fff; width: 4em; height: 4em; position: absolute; top: calc(50% - 2em); left: calc(50% - 2em); } [代码] 扎实的描绘 (Solid drawing) [图片] 当动画对象在三维中应该加倍注意确保它们遵循透视原则。因为人们习惯了生活在三维世界里,如果对象表现得与实际不符,会让它看起来很糟糕。 如今浏览器对三维变换的支持已经不错,这意味着我们可以在场景里旋转和放置三维对象,浏览器能自动控制它们的转换。 HTML [代码]<h1>Principle 11: Solid drawing</h1> <h2><a href="https://cssanimation.rocks/principles/" target="_parent">Animation Principles for the Web</h2> <article class="principle eleven"> <div class="shape"> <div class="container"> <span class="front"></span> <span class="back"></span> <span class="left"></span> <span class="right"></span> <span class="top"></span> <span class="bottom"></span> </div> </div> </article> [代码] CSS [代码].eleven .shape { background: none; border: none; perspective: 400px; perspective-origin: center; } .eleven .shape .container { animation: eleven 4s infinite cubic-bezier(.6,-0.44,.37,1.44); transform-style: preserve-3d; } .eleven .shape span { display: block; position: absolute; opacity: 1; width: 4em; height: 4em; border: 1em solid #fff; background: #2d97db; } .eleven .shape span.front { transform: translateZ(3em); } .eleven .shape span.back { transform: translateZ(-3em); } .eleven .shape span.left { transform: rotateY(-90deg) translateZ(-3em); } .eleven .shape span.right { transform: rotateY(-90deg) translateZ(3em); } .eleven .shape span.top { transform: rotateX(-90deg) translateZ(-3em); } .eleven .shape span.bottom { transform: rotateX(-90deg) translateZ(3em); } @keyframes eleven { 0% { opacity: 0; } 10%, 40% { transform: none; opacity: 1; } 60%, 75% { transform: rotateX(-20deg) rotateY(-45deg) translateY(4em); animation-timing-function: cubic-bezier(1,-0.05,.43,-0.16); opacity: 1; } 100% { transform: translateZ(-180em) translateX(20em); opacity: 0; } } /* General styling */ body { margin: 0; background: #e9b59f; font-family: HelveticaNeue, Arial, Sans-serif; color: #fff; } h1 { position: absolute; top: 0; left: 0; right: 0; text-align: center; font-weight: 300; } h2 { font-size: 0.75em; position: absolute; bottom: 0; left: 0; right: 0; text-align: center; } a { text-decoration: none; color: #333; } .principle { width: 100%; height: 100vh; position: relative; } .shape { background: #2d97db; border: 1em solid #fff; width: 4em; height: 4em; position: absolute; top: calc(50% - 2em); left: calc(50% - 2em); } [代码] 吸引力 (Appeal) [图片] 吸引力是艺术作品的特质,让我们与艺术家的想法连接起来。就像一个演员身上的魅力,是注重细节和动作相结合而打造吸引性的结果。 [代码] 精心制作网页上的动画可以打造出吸引力,例如 Stripe 这样的公司用了大量的动画去增加它们结账流程的可靠性。 [代码] HTML [代码]<h1>Principle 12: Appeal</h1> <h2><a href="https://cssanimation.rocks/principles/" target="_parent">Animation Principles for the Web</h2> <article class="principle twelve"> <div class="shape"> <div class="container"> <span class="item one"></span> <span class="item two"></span> <span class="item three"></span> <span class="item four"></span> </div> </div> </article> [代码] CSS [代码].twelve .shape { background: none; border: none; perspective: 400px; perspective-origin: center; } .twelve .shape .container { animation: show-container 8s infinite cubic-bezier(.6,-0.44,.37,1.44); transform-style: preserve-3d; width: 4em; height: 4em; border: 1em solid #fff; background: #2d97db; position: relative; } .twelve .item { background-color: #1f7bb6; position: absolute; } .twelve .item.one { animation: show-text 8s 0.1s infinite ease-out; height: 6%; width: 30%; top: 15%; left: 25%; } .twelve .item.two { animation: show-text 8s 0.2s infinite ease-out; height: 6%; width: 20%; top: 30%; left: 25%; } .twelve .item.three { animation: show-text 8s 0.3s infinite ease-out; height: 6%; width: 50%; top: 45%; left: 25%; } .twelve .item.four { animation: show-button 8s infinite cubic-bezier(.64,-0.36,.1,1.43); height: 20%; width: 40%; top: 65%; left: 30%; } @keyframes show-container { 0% { opacity: 0; transform: rotateX(-90deg); } 10% { opacity: 1; transform: none; width: 4em; height: 4em; } 15%, 90% { width: 12em; height: 12em; transform: translate(-4em, -4em); opacity: 1; } 100% { opacity: 0; transform: rotateX(-90deg); width: 4em; height: 4em; } } @keyframes show-text { 0%, 15% { transform: translateY(1em); opacity: 0; } 20%, 85% { opacity: 1; transform: none; } 88%, 100% { opacity: 0; transform: translateY(-1em); animation-timing-function: cubic-bezier(.64,-0.36,.1,1.43); } } @keyframes show-button { 0%, 25% { transform: scale(0); opacity: 0; } 35%, 80% { transform: none; opacity: 1; } 90%, 100% { opacity: 0; transform: scale(0); } } /* General styling */ body { margin: 0; background: #e9b59f; font-family: HelveticaNeue, Arial, Sans-serif; color: #fff; } h1 { position: absolute; top: 0; left: 0; right: 0; text-align: center; font-weight: 300; } h2 { font-size: 0.75em; position: absolute; bottom: 0; left: 0; right: 0; text-align: center; } a { text-decoration: none; color: #333; } .principle { width: 100%; height: 100vh; position: relative; } .shape { background: #2d97db; border: 1em solid #fff; width: 4em; height: 4em; position: absolute; top: calc(50% - 2em); left: calc(50% - 2em); } [代码]
2019-03-21