- 【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 - 小打卡|如何组件化拆分一个200+页面的小程序
大家好,我是小打卡的前端唐驰。刚才金轩正同学分享了基于原生小程序底层架构,在此基础上我为大家分享下如何拆分一个200+页面的小程序,主要通过以下几点来聊一聊小打卡在组件化路上的一些实践 1.背景 2.组件与方案 3.组件间通讯 4.基于组件我们做了哪些事 [图片] [图片] 1. 其实一开始小打卡是没有引入组件化的,因为微信最开始是不支持组件化的。当时js代码已经4k+行了,各种功能代码,有用的没有用的,不知道干什么的代码就躺在那里,一动不动。举个例子,一个头像点击跳转的逻辑搜索了下,遍布在各个页面。修改起来可想而知的胆战心惊。另一个原因就是当时由于业务功能直线上升,很快我们就遇到了代码包超包了。在微信还没有实现分包之前,我们就只能一个一个页面的去review剔除代码,效率极低。这也是促成我们决定寻求出路的原因之一。可是删代码删功能是不能解决问题,期间我们也考虑过h5的方式,跑了demo之后却发现h5方式的多次渲染, 与加载首页白屏,尽管有各种服务端渲染方案,但是我们一致觉得为了用户体验,放弃了。 [图片] 2. 对于小打卡来说,我们不能再任由项目裸奔了,需要一种开发方式来进行约束,主要是有几个诉求: 在之前的项目上,为了方便。功能与功能之间的耦合程度极其的高,各种为了使用方便而随意修改某一个方法。 1.降低页面上各个功能点的耦合程度 我们不希望同一个功能点同样的代码在页面肆意copy,这样带来了极高的维护成本。以至后面无法维护。并且功能的复用不希望是copy,前端与后端不同的是不仅是单单的逻辑复用、更有布局、样式等。 2.提供代码的可复用性、可维护性 对于一个程序员来说,如果你打开一个代码文件。映入眼帘的是密密麻麻的代码,行数达到好几千K行,我相信大家的第一反应是抗拒的,更别说去修改代码,天知道会改出什么问题。 3.降低单一文件的复杂度 4.如果是公共功能的化我们还希望它能够有自己的作用域,保持自己的独立性。 [图片] 3. 根据以上几点,我们用一个页面举例,如何去拆分一个页面,首先我们需要有以下几点认识: 决定一个页面如何组件化的前提是该页面的功能是否是有全局都需要的功能模块 功能模块是否需要与页面其他模块强耦合 单个功能模块逻辑是否过于复杂(占用代码空间过大)——>单纯是为了页面代码的可读性。 不是全拆成组件就是最好的,不能为了组件而组件化 [图片] 4. 说了这么多,其实我们应该首先应该了解下,组件的特性? 专一性(一个组件只干一件事情,或者某一类事情。)功能的高度内聚 比如说右侧的feed集上的头像、它是一个组件、就负责显示头像跟跳转,其他的事它都不参与 可配置(能够适应通过设置属性值的方式来输出不同的东西)输入影响部分输出 然后我们同时可以设置头像组件上的size属性来设置头像在不同页面下的大小样式 生命周期(组件可以在自身或者说所在页面的生命周期内可以做不同的事情)比如可以在组件生成的时候进行数的初始化、属性值的类型校验、组件销毁时并同时销毁定时器等其他任务 事件传递 (既然要让组件与页面保持独立性,那么组件与页面的通讯交互就得需要一个标准) 右侧的feed组件其实是一个组件集合、我们通过组合不同的组件然后就形成了feed组件。就跟搭积木一样、只需要引入组件就行了。特别方便。 [图片] 5. 说到组件,那么小程序早期的不支持自定义组件开发这就很让人头疼、同样的feed组件我们经历了几乎三个版本的大改动、从最开始的直接写在页面里,后台使用template方式、再到后来的自定义组件方式。所以我们的演进步骤就成了page->template->component, 这儿列了一个表格对比了下几种组件化方式的对比。 可以看到,include的方式其实是最鸡肋的,include的方式其实实际意义上我理解成更多的是代码的切割,并且还不能将(template、wxs)分出去、所以这种方式我们直接pass掉了, 而template的方式其实是我们曾经主力使用的方式、到现在我们也还在使用、相对于include来说,template有了独立的作用域、虽然css、跟js还是与页面共享的。但是已经可以做一些比较简单的事情了。 对于component来说,完完全全的组件,满足了组件的所有要求。 [图片] 6. 先说说template的方式吧,举个列子,这个是我们的使用template构建的头像组件。跟写页面的方式很像、同样是js、wxss、wxml组成。用名称来命名。但是由于微信当时没有很方的方式去引用这些文件,或者说没有一种方法可以打包供我们很方便的使用。但是比起之前直接copy代码的方式、这样通过引用的方式使用其实感觉已经好了很多了。 [图片] [图片] 7. 具体的使用方式我画了张图,对应组件内文件与页面文件的对应方式、这里对于js的引用其实我们是做了一些小动作, 我们在调用Page方法前做了一次page方法与组件方法的check,因为在page代码里我们不能保证所有的方法名不会跟组件内的方法名不会冲突,所以我们做了这个一个检查、 然后mix函数还做了另一个事情就是将page方法与组件方法合并。然后对于mix函数其实我们还可以做很多事情、、比如规范生命周期回调函数放在一个对象内,然后我们自己定义的方法放在另一个对象里,就跟vue一样。 But,在经历了一段template组件化的时间后,我们又觉得这个方式还是有点烂,为什么呢?在使用时仍然不能避免引入众多的文件、虽然我们对js文件做了处理,但是wxss的样式仍然会被污染、js与page仍然共享作用域。并不能成为一个真正的标准组件。好在后来,微信上了自定义组件的功能,接下来聊聊这个标准的微信自定义组件吧。 8. 微信提供了自定义组件的功能后我们也第一时间跟进了,相对于template这种方式来说,现在是真正的独立于页面存在。使用也比之前更为方便与简洁,右图是我们对component的一个项目目录划分。我们将component划分为了公共组件与页面组件、为什么会有页面组件, 1.是为了降低页面代码的复杂度 2.为了好看。 公共组件就不说了,一定是最基础、最通用的组件。 [图片] 9. 转向component方式后有一个问题逐渐便凸显出来了,由于组件的独立作用域,组件间的通讯就成了一个问题,接下来聊一聊组件的事件传递。微信最开始的时候提供了一种triggerEvent的方式,可是这样的方式似乎并不能满足我们某些场景下的需求。后来又提供了page下selectComponent方法来直接操作组件内部的属性与方法。然后还有就是基于我们自己的事件广播机制。这几种方式构成了小打卡现目前最主要的组件与page、组件与组件间的数据交互方式 [图片] 10. 先来说说triggerEvent模式,微信在自定义组件上可以自定义监听函数。我们在组件内将需要向外抛出的事件统一通过this.triggerEvent(‘invoke’,{handler:’fun’,data:{}})这个方法来执行。其中invoke对应了我们绑定在组件标签上的监听函数。而将需要外部执行的方法与数据通过数据的方式传给监听函数。而在page上面我通过统一的监听回调函数去自动执行需要执行的方法、这里的trigger与event都不要我们去手写在组件与page创建的时候底层就已经帮我们预置了,我们只需要关注业务开发就行。这是对于一部分需要page与组件交互的模式。而对于我们想直接操作组件方法而不需要反馈的模式就得使用selectComponent的模式 [图片] 11. 一个简单的列子:全局的toast组件。在需要弹出toast的时候我们想直接调用就行、不用在通过传值给组件、然后由组件来执行显示或隐藏。这类组件我们在组件目录里新增了一个lib的文件。在page里只需要引入这个lib文件然后就可以直接调用toast组件。lib主要是对this.selectCompent与执行逻辑的一个封装。 [图片] 12. 事件发布订阅模式:基于底层的eventBus。简化后我们用在了组件与组件之间的通讯上、特点是简单。 [图片] 13. 解决了组件间的通讯问题,可是对于公共组件的引用仍然让我们觉得麻烦与不畅快、所以我们构建了全局通用模版、它是干什么的呢。它提供给了一些基础的全局组件、比如自定义导航头、toast、loading等等。小打卡所有的页面都通过slot的方式插入到这个模版组件x-page下面。这样就解决了我们需要在每个页面引入公共组件的问题。另一个问题使用自定义导航栏的时定位起点会有状态栏下移动到屏幕左上方。会造成布局的错误。通过x-page可以很好解决这个问题而不用重新布局。并且通信问题也不用担心,都是由x-page组件作为中台来对内对外进行分发与执行。 [图片] [图片] [图片] 14. 通过以上小打卡的开发模式就基本形成。要做的事情还有很多,更多组件的玩儿法,对于现在或者将来我们正在做的。 是构建小打卡的组件与基础sdk的仓库。 拆分组件开发与业务开发。 通过npm包管理的方式来应对越来越多的小程序平台的开发。 或者通过形成小程序插件的方式供其他小伙伴使用。 [图片] [图片] 以上就是我今天分享的内容。谢谢。
2019-04-26 - 如何实现一个自定义导航栏
自定义导航栏在刚出的时候已经有很多实现方案了,但是还有大哥在问,那这里再贴下代码及原理: 首先在App.js的 onLaunch中获取当前手机机型头部状态栏的高度,单位为px,存在内存中,操作如下: [代码]onLaunch() { wx.getSystemInfo({ success: (res) => { this.globalData.statusBarHeight = res.statusBarHeight this.globalData.titleBarHeight = wx.getMenuButtonBoundingClientRect().bottom + wx.getMenuButtonBoundingClientRect().top - (res.statusBarHeight * 2) }, failure() { this.globalData.statusBarHeight = 0 this.globalData.titleBarHeight = 0 } }) } [代码] 然后需要在目录下新建个components文件夹,里面存放此次需要演示的文件 navigateTitle WXML 文件如下: [代码]<view class="navigate-container"> <view style="height:{{statusBarHeight}}px"></view> <view class="navigate-bar" style="height:{{titleBarHeight}}px"> <view class="navigate-icon"> <navigator class="navigator-back" open-type="navigateBack" wx:if="{{!isShowHome}}" /> <navigator class="navigator-home" open-type="switchTab" url="/pages/index/index" wx:else /> </view> <view class="navigate-title">{{title}}</view> <view class="navigate-icon"></view> </view> </view> <view class="navigate-line" style="height: {{statusBarHeight + titleBarHeight}}px; width: 100%;"></view> [代码] WXSS文件如下: [代码].navigate-container { position: fixed; top: 0; width: 100%; z-index: 9999; background: #FFF; } .navigate-bar { width: 100%; display: flex; justify-content: space-around; } .navigate-icon { width: 100rpx; height: 100rpx; display: flex; justify-content: space-around; } .navigate-title { width: 550rpx; text-align: center; line-height: 100rpx; font-size: 34rpx; color: #3c3c3c; font-weight: bold; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } /*箭头部分*/ .navigator-back { width: 36rpx; height: 36rpx; align-self: center; } .navigator-back:after { content: ''; display: block; width: 22rpx; height: 22rpx; border-right: 4rpx solid #000; border-top: 4rpx solid #000; transform: rotate(225deg); } .navigator-home { width: 56rpx; height: 56rpx; background: url(https://qiniu-image.qtshe.com/20190301home.png) no-repeat center center; background-size: 100% 100%; align-self: center; } [代码] JS如下: [代码]var app = getApp() Component({ data: { statusBarHeight: '', titleBarHeight: '', isShowHome: false }, properties: { //属性值可以在组件使用时指定 title: { type: String, value: '青团公益' } }, pageLifetimes: { // 组件所在页面的生命周期函数 show() { let pageContext = getCurrentPages() if (pageContext.length > 1) { this.setData({ isShowHome: false }) } else { this.setData({ isShowHome: true }) } } }, attached() { this.setData({ statusBarHeight: app.globalData.statusBarHeight, titleBarHeight: app.globalData.titleBarHeight }) }, methods: {} }) [代码] JSON如下: [代码]{ "component": true } [代码] 如何引用? 需要引用的页面JSON里配置: [代码]"navigationStyle": "custom", "usingComponents": { "navigate-title": "/pages/components/navigateTitle/index" } [代码] WXML [代码]<navigate-title title="青团社" /> [代码] 按上面步骤操作即可实现一个自定义的导航栏。 如何实现通栏的效果默认透明以及滚动更换title为白色背景,如下图所示: [图片] [图片] [图片] [图片] 最后代码片段如下: https://developers.weixin.qq.com/s/wi6Pglmv7s8P。 以下为收集到的社区老哥们的分享: @Yunior: 小程序顶部自定义导航组件实现原理及坑分享 @志军: 微信小程序自定义导航栏组件(完美适配所有手机),可自定义实现任何你想要的功能 @✨o0o有脾气的酸奶💤 [有点炫]自定义navigate+分包+自定义tabbar @安晓苏 分享一个自适应的自定义导航栏组件
2020-03-10 - 实现小程序canvas拖拽功能
组件地址 https://github.com/jasondu/wx-comp-canvas-drag 实现效果 [图片] 如何实现 使用canvas 使用movable-view标签 由于movable-view无法实现旋转,所以选择使用canvas 需要解决的问题 如何将多个元素渲染到canvas上 如何知道手指在元素上、如果多个元素重叠如何知道哪个元素在最上层 如何实现拖拽元素 如何缩放、旋转、删除元素 看起来挺简单的嘛,就把上面这几个问题解决了,就可以实现功能了;接下来我们一一解决。 如何将多个元素渲染到canvas上 定义一个DragGraph类,传入元素的各种属性(坐标、尺寸…)实例化后推入一个渲染数组里,然后再循环这个数组调用实例中的渲染方法,这样就可以把多个元素渲染到canvas上了。 如何知道手指在元素上、如果多个元素重叠如何知道哪个元素在最上层 在DragGraph类中定义了判断点击位置的方法,我们在canvas上绑定touchstart事件,将手指的坐标传入上面的方法,我们就可以知道手指是点击到元素本身,还是删除图标或者变换大小的图标上了,这个方法具体怎么判断后面会讲解。 通过循环渲染数组判断是非点击到哪个元素到,如果点击中了多个元素,也就是多个元素重叠,那第一个元素就是最上层的元素啦。 ###如何实现拖拽元素 通过上面我们可以判断手指是否在元素上,当touchstart事件触发时我们记录当前的手指坐标,当touchmove事件触发时,我们也知道这时的坐标,两个坐标取差值,就可以得出元素位移的距离啦,修改这个元素实例的x和y,再重新循环渲染渲染数组就可以实现拖拽的功能。 如何缩放、旋转、删除元素 这一步相对比较难一点,我会通过示意图跟大家讲解。 我们先讲缩放和旋转 [图片] 通过touchstart和touchmove我们可以获得旋转前的旋转后的坐标,图中的线A为元素的中点和旋转前点的连线;线B为元素中点和旋转后点的连线;我们只需要求A和B两条线的夹角就可以知道元素旋转的角度。缩放尺寸为A和B两条线长度之差。 计算旋转角度的代码如下: [代码]const centerX = (this.x + this.w) / 2; // 中点坐标 const centerY = (this.y + this.h) / 2; // 中点坐标 const diffXBefore = px - centerX; // 旋转前坐标 const diffYBefore = py - centerY; // 旋转前坐标 const diffXAfter = x - centerX; // 旋转后坐标 const diffYAfter = y - centerY; // 旋转后坐标 const angleBefore = Math.atan2(diffYBefore, diffXBefore) / Math.PI * 180; const angleAfter = Math.atan2(diffYAfter, diffXAfter) / Math.PI * 180; // 旋转的角度 this.rotate = currentGraph.rotate + angleAfter - angleBefore; [代码] 计算缩放尺寸的代码如下: [代码]// 放大 或 缩小 this.x = currentGraph.x - (x - px); this.y = currentGraph.y - (x - px); [代码]
2019-02-20 - 微信朋友圈选图效果
中秋快乐,帮社区里的小伙伴写的选图效果,仿造的微信朋友圈选图,长按拖动排序主要是用交互监听来实现的。还有几个需要处理的地方。另外在真机上的动画速度总感觉快那么一丢丢。没做预览图,详情见代码片段咯。安卓机效果没试过。。 今天是9月23,这两天接受定制改动~ 第一次发经验分享。。轻点喷。。 哦,对了,这里 wx.createSelectorQuery 有个bug。。如果选择的基础库版本在2.0.9以上,第一次打开开发者工具,要先直接点一次编译,不然会出错。。真机上没问题 代码片段:wechatide://minicode/RFLmzDmL7I2a 有小伙伴反馈,在片段上面增加内容会乱位,是因为没计算顶部偏移量,方便懒人,完善了下 新的片段:wechatide://minicode/fOTEM3mI7l3B 终于拿到安卓机器试了,果然卡得很。。要控制频率。这很尴尬,太频繁的话,安卓会卡,太不频繁呢,刚开始移动那阵子会卡。。有同学反馈,说点快了会出问题,于是又加了点击频率的限制 现在的代码片段:wechatide://minicode/xBDdCom17R3c(要重新拿安卓机测试了再看看。。) 附上gif: [图片]
2018-10-24 - 层叠轮播图
[图片] 请大佬指点下这种效果怎么做
2018-11-29