Smartcalls如何成为Voximplant Kit的品牌-品牌重塑和杀手features


长期以来,我们一直在准备对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');
   //   svg-,        center
   //   ,     style
   const { a, b, c, d, e, f } = this.zoomMatrix(zoom, center, offset);
   //  FireFox    ,       
   this.paper.layers.style.transform = currentMatrix;
   //    FF  ,     ,    
   setTimeout(() => {
     //  CSS- .animate-viewport,    - transition;
     //    style      - transition
     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;
     //        style;
     //      joint
     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等成功开发!

All Articles