前言:

制作灵感来源于 http://species-in-pieces.com/ 这个网站,此网站作者是来自阿姆斯特丹的设计师 Bryan James,其借用纯CSS技术表现出30种濒危动物的碎片拼图形象,用转瞬即逝的动画来暗示这些动物目前的处境。

首先,所有动物形象都是借助 clip-path 这一 css3 属性通过各 三角拼接而成,这一属性不仅可以画 三角 还可以画出任意形状。

为了实现一个这样的动画编辑器,工具方面使用了浏览器的 Canvas2d 和 localStorage,代码风格上 大量使用了 fp 风格的代码。

代码风格:

一个比较典型的设计如下:

      // 获取画布 div
      let drawboardGetter = () => $(".polygon-wrap");

这里 $ 是实现的一个简易原型,并未引入 jQuery,可以使代码精简。

使用这些自定义 getter 函数的目的是来代替所有 纯函数 不纯的部分,这样即便整个纯函数链有不纯的部分,也不影响各种功能链的正常运行,因为这些 getter 的引用变更不会引发任何错误。

实现步骤:

第一步新建一个 html 文件来完成编辑器的功能。

作为一个编辑器,首先要能手动画三角形,可用一个 canvas 来记录鼠标点击处的位置,起到一个提示三角形大概轮廓的效果:

数据方面分别区分两种单元,图案 和 三角形,三角形组成图案,图案之间可以切换,用 函数+组合 的方式生成一个实例,使其具备功能:

      // 一个图案的点管理器
      let pmgInstance = null;
      let pointArrMgGetter = () => pmgInstance || (pmgInstance = mkPointArrMaker(basicArrMaker()));

显然生成的 点数组 getter 都会具备相同的数据结构,因此可以像一个相同类型的变量一样穿梭于各种外部函数之间。

然后设计下编辑器的 ui 部分,是可拖动可隐藏的还有之前停留位置的记录功能,可拖动和可隐藏的设计随便拿一个编辑器比如 ps,unity-editor 这种对功能框都有这种设计,为了更方便使用,我还设计了一个右键点击编辑器空白处可以隐藏编辑器的功能,这样不用去点一般在右上角很小的关闭按钮,实际使用起来我个人感觉很流畅。

      // 使一个 div 可以被鼠标拖动
      const mkDragable = (div, propTopHandler, eventHandler) => { /* ... */ }

上面这个函数会让一个 div 变成可被拖动并在某些时机触发相应的钩子;

动画部分全部是借助 css 实现的,也就是浏览器默认的绘图功能,那作为一个编辑器就要有随时能准确更新 css 的功能,具体点就是更新 style 标签里的内容,使它变成 freeStyle:(ps:用来实现 数据 => css代码 功能函数也必不可少)

      // 插入css规则
      const {
        insertCssRule,
        alterCssByClassName,
        alterMainCss,
        inserKeyframeRule,
        alterCssByKeyFrameName,
      } = (() => { /* */ }

代码层 状态模式 这种设计也是必须的,因为用户在使用鼠标点击的时候 最基本的就可能处在三种情形: 三角形形状编辑,三角形位置编辑,绘制三角形。

        // 状态切换器
        function tabToState(mode, val = true) { /**/ }

事件绑定方面有经验的开发会选择事件派发,简而言之就是绑在父元素,性能理论上也会好些。

回到 html 部分,为了用最简洁的方式实现三角形的动画过渡,这里我使用了 div 复用的设计,说白了一个舞台两场戏,都是原来那群龙套。

这里就还需要设计一个所有 div 如何按顺序开始变换到自己在下一副图案中位置的问题,这个对最终效果的展示至关重要,后面会展示对比效果。

      // 某个 div 开始跳舞
      const mkDivUiWork = (singleConfig, arrSource) => (i) => {
        // 三角形重置
        singleConfig.showDomFrameConfig(arrSource[i].dom, 0);
        // 是否在舞台上
        arrSource[i].show = true;
      };

这里的封装是为了将这个群演 div 的戏份储存起来,这样后面总导演就能安排他们的出场时机。

万事具备,实现功能就顺理成章了,不过肯定有很多细节可以完善和优化的地方。

鉴于我的艺术素养有限,就从临摹开始来完成动画图形,这里开个 nodejs 服务用来将网站截图存储本地,去掉跨域限制后画到浏览器里面,然后就可以仿照着临摹了,临摹这里有两个要注意的地方,第一个是叠加的两个三角形后面的三角形要靠想象力先画出来,因为暂时没有新增调整三角间层级的功能,先绘制的三角形层级会比后绘制的高;第二是默认临摹出的三角形是无法自动获取被临摹三角的颜色的,需要点击 临摹取色 进入取色状态,填充点击在画板上此位置取到的像素颜色。

特点设计:

局部的编辑器也做了区分,比如双击一个三角就可以调出仅 针对 三角形形状编辑功能和三角形位置编辑功能的 编辑器,而其余的两个 图案编辑器 和 临摹图案编辑器是显示出来可以让用户点击的,流程设计大概如下:

临摹图案编辑器显示图案 => 单击连点临摹绘制三角形 => 双击三角形可编辑位置和形状 => 打开图案编辑器保存图案

双击三角形调出编辑器即可以用按钮切换编辑位置和形状的功能,也可以直接右键鼠标实现功能的快速切换)

三角本身的动画也是在双击三角弹出编辑器上通过增减关键帧实现(具体就是变更 css 样式里 keyframe 的帧设置):

最后就是图案间动画的切换了,因为前面已经实现了 freeStyle,因而一旦一幅图的 freeStyle 被切到了另一幅图的 freeStyle,此时浏览器的绘图引擎在 transition 的影响下就开始自动工作了:

但是由于所有群演是同时开始动作的,就会让人眼花缭乱看不过来,之前提到封装每个群演的行为这时候就起作用了,我们可以安排他们一个一个按顺序执行,这里其实可以用各种缓动函数来 控制,比如开场缓慢,中场热烈,收尾迅速,就像原来网站里的动物间切换的律动效果一样。

这里用一个固定间隔 200 ms 来展示效果,当然这个固定间隔不仅可以提前配置也可以实时更改:

其实到这里除了出场间隔还有一个问题,就是三角形的绘制顺序问题。举个例子,群演 小黑 在剧本A(图案A)中是在西北角位置,在剧本B(图案B)中却被安排到了东南角位置,那么转场过程中,小黑 就不得不从西北角跑到东南角,这给观众带来的观影体验请参照(周星驰在喜剧之王中演死人龙套的场景),小黑 明显抢戏了。

因此在图案绘制过程中我都是遵循从右下到左上的绘图顺序,这样图案间的过渡就会流畅很多。但显然这是治标不治本的解决方案,小黑应该遵循就近原则自动补位。

这也是我还没实现的功能,不过思路也比较清晰,因为所有三角位置都清楚的情况下通过计算调整两场群演间的映射关系就可以了。还有的问题包括两个图案所用三角(群演)数量不匹配的问题,上图结尾可以发现新的群演是通过天外飞仙的方式登场的,可能需要调整下出场效果。

最后和原网站对比,可以发现编辑器还缺少的一些功能,比如应该可以配置背景图,可以配置图案的整体动画,动物身体下的阴影动画配置,这些都是可以列计划完成的。

spieces-in-pieces动画编辑器的更多相关文章

  1. 【咸鱼教程】Wing动画编辑器创建精美(一般-_-)开场动画

    游戏中会用着一些简单的动画,公司一般使用的dragonbones制作,导出二进制格式或者MC来使用.感觉一些简单动画直接使用动画编辑器更加简便些. 引擎版本:5.0.14wing版本:4.1.0 一 ...

  2. 【v2.x OGE教程 11】 动画编辑器帮助文档

    ] 动画编辑器帮助文档 版本号 日期 作者 说明 1.0 2014-9-3 橙子游戏 文档创建       一.简单介绍 动画编辑器用于游戏动画的可视化编辑,支持序列帧动画和关键帧动画.通过解析生成的 ...

  3. cocos creator 动画编辑器以及骨骼动画的使用

    一.普通动画的设置 1.添加动画组件 a.添加空节点=>添加动画组件 b.新建Clip文件=>打开编辑模式添加动画编辑(并且把添加的clip文件拖动到右边面板的Default Clip 与 ...

  4. Egret Wing4.0.3 动画编辑器

    一 exml上摆放组件 切换动画编辑 创建动画组,命名test1. 选中一个对象,创建动画(必须选中一个对象后,+号才会亮.且一个对象只能创建一个动画) 之后和Flash差不多.在时间轴插入关键帧. ...

  5. Mecanim动画编辑器 - 加入动画层实现并行动作

    1.创建新的状态层 a) 通过下图的1button创建一个新的层   b) 通过下图2属性设置图层的权重.假设为0,则该图层的状态不会影响到总的状态机  c) Mask是设置动画的Avatar的关联节 ...

  6. cocos2dx骨骼动画Armature源码分析(一)

    源码分析一body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-to ...

  7. Flash动画

    Flash (交互式矢量图和Web动画标准) Flash是由macromedia公司推出的交互式矢量图和 Web 动画的标准,由Adobe公 司收购.做Flash动画的人被称之为闪客.网页设计者使用 ...

  8. android游戏动画特效的一些处理

    游戏中避免不了需要一些动画特效的处理,有些是不方便用美术或者美工来处理的,那么就由我们程序猿来搞了.直接进入正题. 首先是Animation,Animation针对view,可以控制view的位移.缩 ...

  9. Cocos2d-x——CocosBuilder官方帮助文档翻译3 动画

    Working with Animations 动画 You can use CocosBuilder for creating character animations, animating com ...

随机推荐

  1. c++中运行lua

    video 下载lua源码将src下面除了 lua.c和luac.c 的文件全部添加到项目中 #include <iostream> #include "lua.hpp" ...

  2. ng 基础

    文档 组件的工作只管用户体验,而不用顾及其它. 它应该提供用于数据绑定的属性和方法,以便作为视图和应用逻辑的中介者 组件应该把诸如从服务器获取数据.验证用户输入或直接往控制台中写日志等工作委托给各种服 ...

  3. ES进行date_histogram时间聚合,聚合结果时间不正确问题

    在做项目中,有一个需求是统计本周内每天的漏洞数量,我选用的是ES中的date_histogram函数来进行聚合统计: 但是出现了一个问题,聚合出来的结果和想要统计的结果时间不一致,如下图所示 时间区间 ...

  4. [转]在ROS下使用zeroconf配置多机通信

    原文地址:http://www.corvin.cn/635.html,转载主要方便随时查阅,如有版权要求,请及时联系. 0x00 为何需要配置ROS多机通信 众所周知ROS是分布式系统,因此可以将机器 ...

  5. 第34天学习打卡(GUI编程之组件和容器 frame panel 布局管理 事件监听 多个按钮共享一个事件 )

    GUI编程 组件 窗口 弹窗 面板 文本框 列表框 按钮 图片 监听事件 鼠标 键盘事件 破解工具 1 简介 GUi的核心技术:Swing AWT 1.界面不美观 2.需要jre环境 为什么要学习GU ...

  6. CSS的定位布局(position)

    定位 static(默认值) 没有开启定位 relative 相对定位的性质 包含块(containing block)概念 没有开启定位时包含块就是当前元素最近的祖先块元素 开启绝对定位后的元素包含 ...

  7. 后端程序员之路 47、Hadoop hdfs

    Hadoop的核心是HDFS和MapReduce,而两者只是理论基础,不是具体可使用的高级应用,Hadoop旗下有很多经典子项目,比如HBase.Hive等,这些都是基于HDFS和MapReduce发 ...

  8. while、do...while和for循环

    一.循环 1.1 定义 当满足一定条件的时候,重复执行某一段代码的操作 while和for和do...while是java中的循环 二.while循环 2.1 定义 int i = 0: 初始化值 w ...

  9. Android Studio|IntelliJ IDEA Git使用小技巧

    一 分支管理 1. 新建分支 在master的基础上创建新分支dev 2. 推送分支 将新建的分支dev推送到远程 3. 切换分支 4. 合并分支 当我们在dev分支完成代码修改并测试通过后 需要将d ...

  10. 二叉树、平衡二叉树、红黑树、B树、B+树与B*树

    转: 二叉树.平衡二叉树.红黑树.B树.B+树与B*树 一.二叉树 1️⃣二叉查找树的特点就是左子树的节点值比父亲节点小,而右子树的节点值比父亲节点大,如图: 基于二叉查找树的这种特点,在查找某个节点 ...