长期以来,我们一直在准备对Smartcalls进行更新,这是用于拨出电话的可视化编辑器,现在它发生了。今天,在剪裁的基础上,我们将讨论UI / UX的更改,并在演示模式下进行深入了解,以了解如何驯服JointJS。实际发生了什么变化?
最明显的是-一个新的名称和URL,这意味着可以在相应的链接voximplant.com/kit上找到Voximplant Kit 。我们还修改了注册页面,现在是这样的:尽管概念保持不变,但产品界面已发生了很大变化,变得更加用户友好。顶部菜单移至左侧,这使浏览块更加合理和方便。此外,现在还可以对脚本和录音进行分组和排序,按号码搜索以及带有简短信息的广告牌,包括新的指标-成功呼叫的平均持续时间和花费的总金额。至于集成:用户友好的界面进入了邮件设置,并且在Dialogflow,SIP,全局变量选项卡上,出现了按ID和主机对文件进行搜索和排序的操作。总的来说,很多新颖而酷!在我们的博客中了解有关更改的更多信息。但是最重要的是编辑
演示模式(扰流板:这是主要的杀手级功能)。实时脚本执行,突出显示所涉及的块,并在执行后-调用(流和日志)的结果,使脚本的调试更加轻松和快捷。您可以在此处观看演示模式的视频,也可以在注册Voximplant Kit后自行进行测试。以及如何实现所有这些,我们将在下一节中介绍。编辑器的新功能:- 撤消/重做(下图中的1);
- 热键(2);
- 弹出菜单,您可以一键式对齐块和块之间的链接,更改比例,使用miniMap,将脚本展开为全屏显示并共享(复制或另存为png)(3);
- 右键单击上下文菜单;
- 复制块-不仅在同一脚本内,而且在不同脚本之间,甚至(!)不同的帐户之间;
- 锁定/解锁块-可以移动锁定的块,但是无法进行编辑以避免不必要的更改;
- 颜色变化-在视觉上,您可以选择几个“相关”块;
- 按使用块的名称和内容进行搜索;
- “交互式菜单”块-只需拖放即可交换位置中的端口(答案选项)的功能。
我们揭示卡片
现在该弄清楚代码中如何实现块动画了。编辑器调用我们的HTTP API方法-StartScenarios-运行云脚本。Voximplant云启动脚本并将其提供给media_access_url编辑器。从这一刻起,编辑器每秒拉出media_access_url,以接收有关脚本如何“遍历”块的响应信息-基于此数据,编辑器突出显示必要的块并为它们之间的连接添加动画效果。历史记录是具有以下字段的JSON对象:- 时间戳
- idSource-初始块;
- idTarget-最后一块;
- 端口-端口(1个块中可能有多个输出)。
借助这些自定义和服务变量,前端可以了解在测试期间它将传递给哪个块。他怎么理解的?进行视觉构造时(添加了一个新块),将立即为其分配一个ID,然后将其在历史记录中用作idSource / idTarget。为了实现此功能,我们使用了JointJS库,但是有一些自写代码。让我们从主要的selectBlock()方法开始,它的工作方式如下:我们遍历运动历史记录数组(idSource,idTarget),并在找到起点和终点后立即查找它们之间的连接:const link = this.editor.getTestLink(sourceCell, portId);
如果它们之间存在连接,则为沿通讯线运行的球设置动画:if (link) this.setLinkAnimation(link);
在this.testHistory的每次更新之后,都会调用selectBlock()方法。由于传递的多个块可以一次到达this.testHistory,因此我们每700毫秒递归调用一次selectBlock(这是动画化从一个块到另一个块的运动所花费的大约时间):setTimeout(this.selectBlock, 700);
此方法的所有代码如下。注意第7行和第10行的selectTestBlock和getTestLink方法-现在我们将分别讨论它们: | selectBlock ():无效 { |
| 如果 (此。historyIndex < 此。testHistory 。长度) { |
| const i = this 。historyIndex ; |
| const targetCellId = this.testHistory[i].idTarget; |
| const sourceCellId = this.testHistory[i].idSource; |
| const portId = this.testHistory[i].port; |
| const targetCell = this.editor.selectTestBlock(targetCellId); |
| const sourceCell = this.editor.getCell(sourceCellId); |
| if (sourceCell && targetCell) { |
| const link = this.editor.getTestLink(sourceCell, portId); |
| if (link) this.setLinkAnimation(link); |
| } |
| this.historyIndex += 1; |
| 的setTimeout (此。selectBlock , 700 ); |
| } |
| } |
建立联系
getTestLink()方法有助于获得块之间的连接-它基于getConnectedLinks(),getConnectedLinks()是内置的JointJS方法,该方法接收块输入并返回链接数组。在我们的实现中,我们在结果数组中查找带有端口的链接,其中source属性的值为portId:link = this.graph.getConnectedLinks(cell, {outbound : true}).find(item => {
return item.get('source').port === portId;
然后,如果有链接,则突出显示它:return link ? (link.toFront() && link) : null;
方法代码:getTestLink(sourceCell: Cell, portId: string): Link {
let link = null;
if (sourceCell && sourceCell.id) {
let cell = null;
if (sourceCell.type === 'ScenarioStart' || sourceCell.type === 'IncomingStart') {
cell = this.getStartCell()
} else {
cell = this.graph.getCell(sourceCell.id);
}
link = this.graph.getConnectedLinks(cell, {outbound : true}).find(item => {
return item.get('source').port === portId;
});
}
return link ? (link.toFront() && link) : null;
}
可以通过JointJS完全实现奔跑球的动画(请参见demo)。我们移到当前区块
当需要选择最后一块并将画布移动到该块时,我们调用selectTestBlock()方法。这里我们得到块中心的坐标:const center = cell.getBBox().center();
然后调用setTestCell()为块着色:editor.tester.setTestCell(cell);
最后,我们使用自编写的zoomToCell()函数将其缩放到其中心(这是最有趣的,但最后是关于它的):editor.paperController.zoomToCell(center, 1, false);
方法代码:selectTestBlock(id: string): Cell {
const cell = (id === 'ScenarioStart') ? editor.tester.getStartCell() : editor.graph.getCell(id);
if (cell) {
const center = cell.getBBox().center();
editor.tester.setTestCell(cell);
editor.paperController.zoomToCell(center, 1, false);
}
return cell;
}
着色方法:找到我们块的SVG元素,并添加CSS类.tested使块颜色:setTestCell(cell: Cell): void {
const view = cell.findView(this.paper);
if (view) view.el.classList.add('is-tested');
}
平滑缩放
最后,zoomToCell()! JointJS有一个内置的方法可以沿着X和Y轴移动画布,起初他们想拿它。但是,此方法使用transform作为SVG标签的属性,它不支持Firefox +浏览器中的平滑动画,而仅使用CPU。我们做了一个小技巧-写了我们的函数zoomToCell(),实质上,它执行相同的操作,但是将转换强制转换为内联CSS,这允许使用GPU进行渲染(因为WebGL已连接到进程)。因此,解决了跨浏览器兼容性的问题。我们的功能不仅使画布沿XY移动,还允许我们通过使用变换矩阵同时缩放(缩放)。.animate-viewport类的will-change属性告诉浏览器该元素将被更改,并且必须应用优化,包括使用GPU,transition属性设置将画布移动到块的平滑度:.animate-viewport {
will-change: transform;
transition: transform 0.5s ease-in-out;
我们所有的方法代码如下:public zoomToCell(center: g.Point, zoom: number, offset: boolean = true): void {
this.updateGridSize();
const currentMatrix = this.paper.layers.getAttribute('transform');
const { a, b, c, d, e, f } = this.zoomMatrix(zoom, center, offset);
this.paper.layers.style.transform = currentMatrix;
setTimeout(() => {
this.paper.layers.classList.add('animate-viewport');
this.paper.layers.style.transform = `matrix(${ a }, ${ b }, ${ c }, ${ d }, ${ e }, ${ f })`;
const duration = parseFloat(getComputedStyle(this.paper.layers)['transitionDuration']) * 1000;
setTimeout(() => {
this.paper.layers.classList.remove('animate-viewport');
this.paper.layers.style.transform = null;
this.paper.matrix(newMatrix);
this.paper.trigger('paper:zoom');
this.updateGridSize();
this.paper.trigger('paper:update');
}, duration);
}, 100);
}
事实证明,有时甚至最高级的文件也都需要完成一个文件:)我们希望您喜欢挖鲸的内部(无论听起来多么令人毛骨悚然)。我们希望您使用Voximplant Kit等成功开发!