1. BUG

1.1 BUG触发情况

  在使用vis.js绘图时,加入两个节点A和B之间既存在一条从A指向B的边,同时也存在一条从B指向A的边,那么这个绘图库就会崩溃。

1.2 BUG解析

  vis.js是动态计算两个节点之间位置的,然后将其在页面上展示出来,而在上述介绍的情况下,在计算A和B之间的距离时,代码中会出现除0的BUG,导致程序崩溃。

2. 解决方案

  源码有3万多行,为了找这个BUG花了一周的时间,最终确定了出问题的函数。

  在vis.js源码第12258行(版本更新后位置可能不同),有个_calculateNodeForces()函数,源码如下:

  

/**
* Calculate the forces the nodes apply on eachother based on a repulsion field.
* This field is linearly approximated.
*
* @private
*/
_calculateNodeForces: function () {
var dx, dy, angle, distance, fx, fy, combinedClusterSize,
repulsingForce, node1, node2, i, j; var nodes = this.calculationNodes;
var nodeIndices = this.calculationNodeIndices; // approximation constants
var a_base = -2 / 3;
var b = 4 / 3; // repulsing forces between nodes
var nodeDistance = this.constants.physics.repulsion.nodeDistance;
var minimumDistance = nodeDistance; // we loop from i over all but the last entree in the array
// j loops from i+1 to the last. This way we do not double count any of the indices, nor i == j
for (i = 0; i < nodeIndices.length - 1; i++) {
node1 = nodes[nodeIndices[i]];
for (j = i + 1; j < nodeIndices.length; j++) {
node2 = nodes[nodeIndices[j]];
combinedClusterSize = node1.clusterSize + node2.clusterSize - 2; dx = node2.x - node1.x;
dy = node2.y - node1.y;
distance = Math.sqrt(dx * dx + dy * dy); minimumDistance = (combinedClusterSize == 0) ? nodeDistance : (nodeDistance * (1 + combinedClusterSize * this.constants.clustering.distanceAmplification));
var a = a_base / minimumDistance;
if (distance < 2 * minimumDistance) {
if (distance < 0.5 * minimumDistance) {
repulsingForce = 1.0;
}
else {
repulsingForce = a * distance + b; // linear approx of 1 / (1 + Math.exp((distance / minimumDistance - 1) * steepness))
} // amplify the repulsion for clusters.
repulsingForce *= (combinedClusterSize == 0) ? 1 : 1 + combinedClusterSize * this.constants.clustering.forceAmplification;
repulsingForce = repulsingForce / distance; fx = dx * repulsingForce;
fy = dy * repulsingForce; node1.fx -= fx;
node1.fy -= fy;
node2.fx += fx;
node2.fy += fy;
}
}
}
}
};

  这里面有个distance变量,已标红,就是这个变量在我们介绍的情况下会为0,然后它又作为一个被除数,所以程序崩溃。

  修改后的代码如下:

  

/**
* Calculate the forces the nodes apply on eachother based on a repulsion field.
* This field is linearly approximated.
*
* @private
*/
_calculateNodeForces: function () {
var dx, dy, angle, distance, fx, fy, combinedClusterSize,
repulsingForce, node1, node2, i, j; var nodes = this.calculationNodes;
var nodeIndices = this.calculationNodeIndices; // approximation constants
var a_base = -2 / 3;
var b = 4 / 3; // repulsing forces between nodes
var nodeDistance = this.constants.physics.repulsion.nodeDistance;
var minimumDistance = nodeDistance; // we loop from i over all but the last entree in the array
// j loops from i+1 to the last. This way we do not double count any of the indices, nor i == j
for (i = 0; i < nodeIndices.length - 1; i++) {
node1 = nodes[nodeIndices[i]];
for (j = i + 1; j < nodeIndices.length; j++) {
node2 = nodes[nodeIndices[j]];
combinedClusterSize = node1.clusterSize + node2.clusterSize - 2; dx = node2.x - node1.x;
dy = node2.y - node1.y;
distance = Math.sqrt(dx * dx + dy * dy);
if(distance == 0){
distance = 0.001;
} minimumDistance = (combinedClusterSize == 0) ? nodeDistance : (nodeDistance * (1 + combinedClusterSize * this.constants.clustering.distanceAmplification));
var a = a_base / minimumDistance;
if (distance < 2 * minimumDistance) {
if (distance < 0.5 * minimumDistance) {
repulsingForce = 1.0;
}
else {
repulsingForce = a * distance + b; // linear approx of 1 / (1 + Math.exp((distance / minimumDistance - 1) * steepness))
} // amplify the repulsion for clusters.
repulsingForce *= (combinedClusterSize == 0) ? 1 : 1 + combinedClusterSize * this.constants.clustering.forceAmplification;
repulsingForce = repulsingForce / distance; fx = dx * repulsingForce;
fy = dy * repulsingForce; node1.fx -= fx;
node1.fy -= fy;
node2.fx += fx;
node2.fy += fy;
}
}
}
}
};

  加上一个判断让它不要为0即可。

vis.js绘图库的一个BUG以及源码修正的更多相关文章

  1. 一个普通的 Zepto 源码分析(二) - ajax 模块

    一个普通的 Zepto 源码分析(二) - ajax 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块,以 ...

  2. 一个普通的 Zepto 源码分析(三) - event 模块

    一个普通的 Zepto 源码分析(三) - event 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块, ...

  3. 一个普通的 Zepto 源码分析(一) - ie 与 form 模块

    一个普通的 Zepto 源码分析(一) - ie 与 form 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核 ...

  4. 随手用python写一个下载jdk源码爬虫

    最近在研读jdk源码,网上找了下资源,发现都不完整. 后来新发现了一个有完整源码的地方,主要包括了java,c,c++的东西,装逼需要,就想拿来玩玩.但是,找了好多种下载打开的方式,发现都不对.于是, ...

  5. 推荐一个很棒的JS绘图库Flot

    Flot是Ole Laursen开发的基于JQuery的纯JavaScript实现的绘图库,Flot使用起来非常简单,绘图效果相当绚丽,而且还支持一些图片的操作功能,例如图片的缩放.可以看一下Flot ...

  6. Web程序员开发App系列 - 开发我的第一个App,源码下载

    Web程序员开发App系列 Web程序员开发App系列 - 认识HBuilder Web程序员开发App系列 - 申请苹果开发者账号 Web程序员开发App系列 - 调试Android和iOS手机代码 ...

  7. (转)轻量级JS焦点图/轮换图myFocus V2源码下载及安装教程

    myFocus是一个专注于焦点图/轮换图制作的JS库,它小巧而且是完全独立的JS库,用它可以轻松的制作出网上绝大部分常见的焦点图(甚至包括flash焦点图),而且制作出的焦点图体积也非常的小(1KB左 ...

  8. js实现轮播图效果(附源码)--原生js的应用

    1.js实现轮播图效果 <!DOCTYPE html><html lang="en"><head> <meta charset=" ...

  9. 一个学习 Koa 源码的例子

    作者: MarkLin 学习目标: 原生 node 封装 中间件 路由 Koa 原理 一个 nodejs 的入门级 http 服务代码如下, // index.js const http = requ ...

随机推荐

  1. php大流量高并发解决方案

    一.硬件 提升硬件,影响因素有: 带宽-硬盘读写速度-内存大小-cpu处理速度   二.软件 反向代理负载均衡 mysql : 1.优化你的sql和索引 2.加缓存,memcached,redis 3 ...

  2. c++ 智能指针、函数指针和指针函数

    智能指针: 1.内存泄漏memory leak :是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出. 2.内存溢出 out of me ...

  3. 数据同步canal服务端介绍

    1.下载安装包 canal&github的地址,最权威的学习canal相关知识的地方 https://github.com/alibaba/canal 在下面的wiki列表中找到AdminGu ...

  4. OpenCV——直方图计算、寻早最值位置和对比匹配(判断两幅图的相似程度)

  5. easyui 如何引入

    一:引入easyui 1:参考官网:http://www.jeasyui.net/ 2:引入 整个文件夹:themes,包括:icon.css.image 等等 3:引入easyui.css      ...

  6. 【转】php容易犯错的10个地方

    原文地址: http://www.toptal.com/php/10-most-common-mistakes-php-programmers-make 译文地址:http://codecloud.n ...

  7. Java Web乱码分析及解决方案

    1.  什么是URL编码. URL编码是一种浏览器用来打包表单输入的格式,浏览器从表单中获取所有的name和其对应的value,将他们以name/value编码方式作为URL的一部分或者分离的发送到服 ...

  8. python利用beautifulSoup写爬虫

    python BeautifulSoup模块的安装 安装包下载地址:http://www.crummy.com/software/BeautifulSoup/#Download 文档:http://w ...

  9. Git配置用户名与邮箱

    1.用户名和邮箱地址的作用 用户名和邮箱地址是本地git客户端的一个变量 每次commit都会用用户名和邮箱纪录. github的contributions统计就是按邮箱来统计的. 2.查看用户名和邮 ...

  10. python面试题(四)

    一.数据类型 1.字典 1.1 现有字典 dict={‘a’:24,‘g’:52,‘i’:12,‘k’:33}请按字典中的 value 值进行排序? sorted(dict.items(),key=l ...