gojs 如何实现虚线(蚂蚁线)动画?
在绘制 dag 图时,通过节点和来箭头的连线来表示节点彼此之间的关系。而节点常常又带有状态,为了更好的表示节点之间的流程关系,loading 状态的节点,与后续节点之间,需要用 动画着的虚线 表示,表示正在处理中,处理完才会变成实线。原理同页面没加载出来之间,加个 loading 提示,能提供更好的交互体验。
- 那么如何用 gojs 实现这个效果呢?虚线,及虚线动画
- 虚线及虚线动画的背后原理是什么?
- 虚线为什么又叫蚂蚁线?
- 纯 css 可以实现吗?
一、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 个关键的属性:strokeDashArray、strokeDashOffset。
文档上有这么两行说明:
For more information, see Stroke Line Dash Array (w3.org),see Stroke Line Dash Offset (w3.org)
背后就是 canvas,及其两个属性 setLineDash、lineDashOffset
参考:
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]
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 实用高级用法
大家,新年好! 历史文章: 数据可视化 gojs 简单使用介绍 gojs 如何实现虚线(蚂蚁线)动画? 本文介绍的是在使用 gojs 制作图的过程中,你可能会碰到的问题的一些解决方案. gojs 是一 ...
- iOS 一个小动画效果-b
近期工作不忙,来一个需求感觉棒棒的,是一个比较简单的页面,如下图(图1) 图1 应该很简单吧,没什么大的功能,就是一个展示,一个拨打电话,拨打电话不需要说,几行代码搞定,基本UI也不用说了,刚培训完的 ...
- WPF炫酷UI及动画
偶然看见了一张图,感觉挺好看的,花了点时间将他转化成了我代码仓库的一部分.虽然不难但也费时间.其中除了背景是百度的一张底图,其他所有内容均通过WPF的Path.Line.TextBlock.Borde ...
- 数据可视化-gojs插件使用技巧总结
随着云计算时代的到来,由于Web技术的快速革新以及为了提供高质量的用户体验,数据可视化成为了前端技术发展的一大方向.为了解决这个问题,现如今涌现了很多优秀的第三方的javascript图形库,比如hi ...
- CSS 奇思妙想边框动画
今天逛博客网站 -- shoptalkshow,看到这样一个界面,非常有意思: 觉得它的风格很独特,尤其是其中一些边框. 嘿嘿,所以来一篇边框特辑,看看运用 CSS,可以在边框上整些什么花样. bor ...
- 像画笔一样慢慢画出Path的三种方法(补充第四种)
今天大家在群里大家非常热闹的讨论像画笔一样慢慢画出Path的这种效果该如何实现. 北京-LGL 博客号@ligl007发起了这个话题.然后各路高手踊跃发表意见.最后雷叔 上海-雷蒙 博客号@雷蒙之星 ...
- 用Canvas写桌球游戏!!!
声明:本文为原创文章,如需转载,请注明来源WAxes,谢谢! 昨天上班的时候闲着无事,就用Canvas写了个桌球游戏来玩玩....所以就拿这游戏上来水一发.或许对一些刚学canvas的人有帮助. 话说 ...
- 可视化图表库--goJS
GoJS是Northwoods Software的产品.Northwoods Software创立于1995年,专注于交互图控件和类库.旗下四款产品: GoJS:用于在HTML上创建交互图的纯java ...
- 【Web动画】SVG 线条动画入门
通常我们说的 Web 动画,包含了三大类. CSS3 动画 javascript 动画(canvas) html 动画(SVG) 个人认为 3 种动画各有优劣,实际应用中根据掌握情况作出取舍,本文讨论 ...
随机推荐
- 初学js正则表达式之密码强度验证
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Android数据存取
Android数据存取 一.SharedPreferencesc存取数据 SharedPreferences是使用键值对的方式来存储数据的,也就是在保存一条数据时,需要给这条数据提供一个对应的键,这样 ...
- 【Netty】最透彻的Netty原理架构解析
这可能是目前最透彻的Netty原理架构解析 本文基于 Netty 4.1 展开介绍相关理论模型,使用场景,基本组件.整体架构,知其然且知其所以然,希望给大家在实际开发实践.学习开源项目方面提供参考. ...
- 数组实现堆栈——Java实现
1 package struct; 2 3 4 //接口 5 interface IArrayStack{ 6 //栈的容量 7 int length(); 8 //栈中元素个数(栈大小) 9 int ...
- zabbix之监控Nginx连接数
#;下载Nginx (编译的时候必须加上此选项 --with-http_stub_status_module) 官网地址:http://nginx.org/en/docs/http/ngx_http_ ...
- 【Linux】【Services】【SaaS】Docker+kubernetes(1. 基础概念与架构图)
1.简介 1.1. 背景:公司正在进行敏捷开发环境的搭建,以取代传统的架构,好处大大的,我就不赘述了.公司原来负责这个项目的同事要转组,我只好交给另外同事继续,但是为了防止同样的事情,我也需要深入了 ...
- 【Java 8】函数式接口(一)—— Functional Interface简介
什么是函数式接口(Functional Interface) 其实之前在讲Lambda表达式的时候提到过,所谓的函数式接口,当然首先是一个接口,然后就是在这个接口里面只能有一个抽象方法. 这种类型的接 ...
- 使用beanUtils封装对象的servlet
package com.hopetesting.web.servlet;import com.hopetesting.dao.UserDao;import com.hopetesting.domain ...
- java多线程2:Thread中的方法
静态方法: Thread类中的静态方法表示操作的线程是"正在执行静态方法所在的代码块的线程". 为什么Thread类中要有静态方法,这样就能对CPU当前正在运行的线程进行操作.下面 ...
- Nginx 中 location 的匹配顺序
nginx中location的匹配模式有以下几种: 精确匹配:以=开头,只有完全匹配才能生效,例子location = /uri 非正则匹配:以^~开头,^表示非.~表示正则,例子location ^ ...