分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > IT知识

vis.js绘图库的一个BUG以及源码修正

发布时间:2023-09-06 01:38责任编辑:傅花花关键词:js

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以及源码修正

原文地址:https://www.cnblogs.com/14061216chen/p/8338128.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved