gojs实现蚂蚁线动画效果


Posted in Javascript onFebruary 18, 2022

在绘制 dag 图时,通过节点和来箭头的连线来表示节点彼此之间的关系。而节点常常又带有状态,为了更好的表示节点之间的流程关系,loading 状态的节点,与后续节点之间,需要用 动画着的虚线 表示,表示正在处理中,处理完才会变成实线。原理同页面没加载出来之间,加个 loading 提示,能提供更好的交互体验。

  • 那么如何用 gojs 实现这个效果呢?虚线,及虚线动画
  • 虚线及虚线动画的背后原理是什么?
  • 虚线为什么又叫蚂蚁线?
  • 纯 css 可以实现吗?

一、gojs 实现

gojs 的基础使用,可参考之前写的文章数据可视化 gojs 简单使用介绍

举例:国庆快到了,出游,从上海到北京,假设当前正在途径安徽到山东的路上。用 gojs 绘制出来如下:

gojs实现蚂蚁线动画效果

1. 绘图

<!-- 容器 -->
<div id="myDiagramDiv" style="height:600px;width:100%;border:1px solid black"></div>
<!-- 引入gojs -->
<script src="https://unpkg.com/gojs/release/go.js"></script>
// 生成器
const $ = go.GraphObject.make;

// 定义容器,myDiagramDiv 为容器 id
const diagram = $(go.Diagram, 'myDiagramDiv');

// 节点模板,描述了如何构造每个节点
diagram.nodeTemplate = $(go.Node, "Auto", // 框自动适应文本
  $(go.Shape, "RoundedRectangle", new go.Binding("fill", "color")),
  $(go.TextBlock, {margin: 5}, new go.Binding("text", "name"))
);

// 定义model, 描述节点信息和连线信息
diagram.model = new go.GraphLinksModel(
  [ // 节点
    { key: 'shanghai', name: "出发地 上海", color: "lightblue" },
    { key: 'jiangsu', name: "途径地 江苏", color: "pink" },
    { key: 'anhui', name: "途径地 安徽", color: "pink" },
    { key: 'shandong', name: "途径地 山东", color: "orange"},
    { key: 'hebei', name: "途径地 河北", color: "orange" },
    { key: 'tianjin', name: "途径地 天津", color: "orange" },
    { key: 'beijing', name: "目的地 北京", color: "lightgreen" }
  ],
  [ // 连线
    { from: "shanghai", to: "jiangsu" },
    { from: "jiangsu", to: "anhui" },
    { from: "anhui", to: "shandong" },
    { from: "shandong", to: "hebei" },
    { from: "hebei", to: "tianjin" },
    { from: "tianjin", to: "beijing" }
  ]
);

至此,一个简单的出游途径地关系图就绘制好了,但是没有虚线动画。

2. 虚线实现

观察实现的图中既有实线,也有虚线,所以这儿需要用到 templateMap

定义实线及虚线模板

// 定义集合,存储实线、虚线模板
const templmap = new go.Map()
const color = '#000'

// 默认连线模板
const defaultTemplate = $(
  go.Link,
  $(go.Shape, { stroke: color, strokeWidth: 1 }),
  $(go.Shape, { toArrow: 'Standard', fill: color, stroke: color, strokeWidth: 1 })
)

// 虚线连线模板,关键属性:strokeDashArray: [6, 3]
const dashedTemplate = $(
  go.Link,
  // name: 'dashedLink',后面动画用到
  $(go.Shape, { name: 'dashedLink', stroke: color, strokeWidth: 1, strokeDashArray: [6, 3] }),
  $(go.Shape, { toArrow: 'Standard', fill: color, stroke: color, strokeWidth: 1 })
)

templmap.add('', defaultTemplate)
// dashed 为名称,描述时用属性 category: 'dashed' 指定
templmap.add('dashed', dashedTemplate)

diagram.linkTemplateMap = templmap

model 数据找到需要描述为虚线的边,加如属性:category: 'dashed',名称需要和定义模板指定的名称一致

{ from: "anhui", to: "shandong", category: 'dashed' },

至此,实线、虚线,都绘制好了。接下来就是最后的动画了。

3. 让虚线动起来

找到虚线,更改属性:strokeDashOffset

有两种方式

  • 方式1:go.Animation,会导致节点端口交互时连线操作有粘粘效果
function animation () {
  const animation = new go.Animation();
  // 虚线动画
  diagram.links.each((link) => {
    const dashedLink = link.findObject("dashedLink");
    if (dashedLink) {
      animation.add(dashedLink, "strokeDashOffset", 10, 0)
    }
  });

  animation.easing = go.Animation.EaseLinear;
  // Run indefinitely
  animation.runCount = Infinity;
  animation.start();
}
animation()
  • 方式2:timeout
function animation () {
  const loop = () => {
    animationTimer = setTimeout(() => {
      const oldskips = diagram.skipsUndoManager;
      diagram.skipsUndoManager = true;
      // 虚线动画
      diagram.links.each((link) => {
        const dashedLinkShape = link.findObject("dashedLink");
        if (dashedLinkShape) {
          const off = dashedLinkShape.strokeDashOffset - 3;
          // 设置(移动)笔划划动画
          dashedLinkShape.strokeDashOffset = (off <= 0) ? 60 : off;
        }
      });

      diagram.skipsUndoManager = oldskips;
      loop();
    }, 180);
  }
  loop()
}
animation()

动画的两种方式,如果没有节点端口连线交互,建议用第一种方式实现,库的动画(可能内部做了优化)。如果想更灵活的控制动画或者第一种实现不了时,那么请用第二种方式。

至此,整个效果就完成了。

二、虚线及虚线动画背后的原理

上面的代码,主要用到了 2 个关键的属性:strokeDashArraystrokeDashOffset

文档上有这么两行说明:

For more information, see Stroke Line Dash Array (w3.org),see Stroke Line Dash Offset (w3.org)

背后就是 canvas,及其两个属性 setLineDashlineDashOffset

参考:

mdn - setLineDah:一个Array数组。一组描述交替绘制线段和间距(坐标空间单位)长度的数字。 如果数组元素的数量是奇数, 数组的元素会被复制并重复。

代码示例:

function drawDashedLine(pattern) {
  ctx.beginPath();
  ctx.setLineDash(pattern);
  ctx.moveTo(0, y);
  ctx.lineTo(300, y);
  ctx.stroke();
  y += 20;
}

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let y = 15;

drawDashedLine([]);
drawDashedLine([1, 1]);
drawDashedLine([10, 10]);
drawDashedLine([20, 5]);
drawDashedLine([15, 3, 3, 3]);
drawDashedLine([20, 3, 3, 3, 3, 3, 3, 3]);
drawDashedLine([12, 3, 3]);  // Equals [12, 3, 3, 12, 3, 3]

gojs实现蚂蚁线动画效果

mdn - lineDashOffset:设置虚线偏移量的属性

代码示例:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var offset = 0;

function draw() {
  ctx.clearRect(0,0, canvas.width, canvas.height);
  ctx.setLineDash([4, 2]);
  ctx.lineDashOffset = -offset;
  ctx.strokeRect(10,10, 100, 100);
}

function march() {
  offset++;
  if (offset > 16) {
    offset = 0;
  }
  draw();
  setTimeout(march, 20);
}

march();

三、虚线的一些概念

虚线:(数学概念)以点或者短线画成的断续的线,多用于几何图形或者标记。

为什么虚线称为蚂蚁线?
在图像影像软件中表示选区的动态虚线,因为虚线闪烁的样子像是一群蚂蚁在跑,所以俗称蚂蚁线。
在Photoshop,After Effect等软件中比较常见。

蚂蚁线:动物的一种本能现象,领头的蚂蚁以随机的路线走向食物或洞穴,第二只蚂蚁紧跟其后以相同的路线行走,每一个后来的蚂蚁紧跟前面蚂蚁行走,排成一条线的现象。

虚线的特征:流动性

四、css 绘制边框虚线

利用 css 的 border-style 绘制,有两个属性值:

  • dotted:显示为一系列圆点。标准中没有定义两点之间的间隔大小,视不同实现而定。圆点半径是 border-width 计算值的一半。
  • dashed:显示为一系列短的方形虚线。标准中没有定义线段的长度和大小,视不同实现而定。

具体参考 mdn - border-style

css 原生属性能实现虚线效果,但是要在此基础上实现动画,不容易。但是可以用 css 的其他属性来实现。

示例:

<div class="container">蚂蚁线</div>
.container {
  width: 100px;
  height: 100px;
  padding: 5px;
  border: 1px solid transparent;
  background: linear-gradient(white, white) padding-box,
    repeating-linear-gradient(-45deg, black 0, black, 25%, transparent 0, transparent 50%) 0% 0% / 0.6em 0.6em;
  animation: ants 10s linear infinite;
}

@keyframes ants {
  to {
    background-position: 100% 100%;
  }
}

gojs实现蚂蚁线动画效果

到此这篇关于gojs实现蚂蚁线动画效果的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 事件处理、鼠标拖动效果实现方法详解
May 11 Javascript
原生js实现给指定元素的后面追加内容
Apr 10 Javascript
js点击出现悬浮窗效果不使用JQuery插件
Jan 20 Javascript
javascript函数中参数传递问题示例探讨
Jul 31 Javascript
Javascript removeChild()删除节点及删除子节点的方法
Dec 27 Javascript
JavaScript禁止用户多次提交的两种方法
Jul 24 Javascript
webpack 2.x配置reactjs基本开发环境详解
Aug 08 Javascript
vue.js-div滚动条隐藏但有滚动效果的实现方法
Mar 03 Javascript
浅谈vue 单文件探索
Sep 05 Javascript
JS/jQuery实现获取时间的方法及常用类完整示例
Mar 07 jQuery
Vue-CLI 3 scp2自动部署项目至服务器的方法
Jul 24 Javascript
原型和原型链 prototype和proto的区别详情
Nov 02 Javascript
uni-app 微信小程序授权登录的实现步骤
Feb 18 #Javascript
详解TypeScript的基础类型
Feb 18 #Javascript
详解jQuery的核心函数和事件处理
Feb 18 #jQuery
JavaScript事件的委托(代理)的用法示例详解
Feb 18 #Javascript
vue项目中的支付功能实现(微信支付和支付宝支付)
Feb 18 #Vue.js
vue3获取当前路由地址
Feb 18 #Vue.js
如何利用React实现图片识别App
You might like
php xml常用函数的集合(比较详细)
2013/06/06 PHP
学习php中的正则表达式
2014/08/17 PHP
php创建、获取cookie及基础要点分析
2015/01/26 PHP
php中mkdir()函数的权限问题分析
2016/09/24 PHP
PHP查询分页的实现代码
2017/06/09 PHP
TP5(thinkPHP5框架)基于bootstrap实现的单图上传插件用法示例
2019/05/29 PHP
Thinkphp5.0 框架使用模型Model添加、更新、删除数据操作详解
2019/10/11 PHP
一个高效的JavaScript压缩工具下载集合
2007/03/06 Javascript
javascript 函数调用规则
2009/08/26 Javascript
js中escape对应的C#解码函数 UrlDecode
2012/12/16 Javascript
Jquery插件easyUi表单验证提交(示例代码)
2013/12/30 Javascript
javascript 模拟坦克大战游戏(html5版)附源码下载
2014/04/08 Javascript
jQuery实现强制cookie过期方法汇总
2015/05/22 Javascript
js+cookies实现悬浮购物车的方法
2015/05/25 Javascript
javaScript实现滚动新闻的方法
2015/07/30 Javascript
js 求时间差的实现代码
2016/04/26 Javascript
JS实现兼容火狐及IE iframe onload属性的遮罩层隐藏及显示效果
2016/08/23 Javascript
node+express制作爬虫教程
2016/11/11 Javascript
微信小程序 地图(map)实例详解
2016/11/16 Javascript
手机移动端实现 jquery和HTML5 Canvas的幸运大奖盘特效
2016/12/06 Javascript
vue中如何让子组件修改父组件数据
2018/06/14 Javascript
利用Angular7开发一个Radio组件的全过程
2019/07/11 Javascript
详解elementui之el-image-viewer(图片查看器)
2019/08/30 Javascript
python创建列表和向列表添加元素的实现方法
2017/12/25 Python
Django 内置权限扩展案例详解
2019/03/04 Python
Python实现中值滤波去噪方式
2019/12/18 Python
五种Python转义表示法
2020/11/27 Python
python中slice参数过长的处理方法及实例
2020/12/15 Python
魔幻般冒泡背景的CSS3按钮动画
2016/02/27 HTML / CSS
Amara美国站:英国高端家居礼品网站,世界各地的奢侈家具品牌
2017/07/26 全球购物
园林施工员岗位职责
2013/12/11 职场文书
管理标语大全
2014/06/24 职场文书
公司总经理岗位职责范本
2014/08/15 职场文书
CSS 使用 resize 实现图片拖拽切换预览功能(强大功能)
2021/08/23 HTML / CSS
Python中的matplotlib绘制百分比堆叠柱状图,并为每一个类别设置不同的填充图案
2022/04/20 Python
CSS实现鼠标悬浮动画特效
2023/05/07 HTML / CSS