前端用JavaScript实现桑基图(Sankey图)

2023-09-18 07:49:03

前端用JavaScript实现桑基图(Sankey图)

桑基图(Sankey图),是流图的一种,常用来展示事物的数量、发展方向、数据量大小等,在可视化分析中经常使用。

本文,演示如何在前端用JavaScript绘制桑基图。注:本例使用JShaman数据展示JS代码混淆加密流程。

先看效果:

因为已有成熟的库可用,比如,可以使用d3引擎,所以sankey的实现较为简单。

众所周知,JShaman是国内知名的JS代码混淆加密平台,我们将用JShaman英文版的混淆返回内容做为数据源,绘制一张JS代码混淆加密流程桑基图。

JShaman数据采集,直接复制即可:

用d3实现桑基图绘制,核心代码如下,文末会提供完整代码。

绘图成功:

桑基图效果说明:从图中,可以看到JShaman对JS代码的混淆加密流程:初始的JS代码,先转为AST(抽象语法树),再进行String reverse、Dead Code Insertion、Eval Encryption等数十种混淆加密操作,生成了新的AST,最后再根据AST重新生成JS代码,这便是JS代码混淆加密的完整流程,由图可以让人一目了然的知晓全过程。

最后,附上完整代码,如果您也需要绘制桑基图,可以参考此代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="./libs/d3/d3.min.js"></script>
<script src="./libs/d3-sankey/d3-sankey.js"></script>
<script src="./libs/d3-sankey-util.js"></script>
</head>
<body>
<div id="obfuscate_sankey"></div>
<script>
obfuscate_result = {
"status": [
{
"feature": "JavaScript 2 AST",
"time": "2023/09/14 07:56:36",
"status": 282
},
{
"feature": "Encode JSON",
"time": "2023/09/14 07:56:36",
"status": 0
},
{
"feature": "Encode Regexp",
"time": "2023/09/14 07:56:36",
"status": 0
},
{
"feature": "String reverse",
"time": "2023/09/14 07:56:36",
"status": 2
},
{
"feature": "Dead Code Insertion",
"time": "2023/09/14 07:56:36",
"status": 4
},
{
"feature": "Rename Private Identifiers",
"time": "2023/09/14 07:56:36",
"status": 2
},
{
"feature": "Rename Global Identifiers",
"time": "2023/09/14 07:56:36",
"status": 2
},
{
"feature": "Rename Global Functions",
"time": "2023/09/14 07:56:36",
"status": 1
},
{
"feature": "Rename Private Functions",
"time": "2023/09/14 07:56:36",
"status": 0
},
{
"feature": "AST Executing",
"time": "2023/09/14 07:56:36",
"status": 9
},
{
"feature": "Property Indirection",
"time": "2023/09/14 07:56:36",
"status": 34
},
{
"feature": "Assignment To Function",
"time": "2023/09/14 07:56:36",
"status": 6
},
{
"feature": "Numbers To Expressions",
"time": "2023/09/14 07:56:36",
"status": 9
},
{
"feature": "VM Executing",
"time": "2023/09/14 07:56:36",
"status": 15
},
{
"feature": "Expression To Function",
"time": "2023/09/14 07:56:36",
"status": 30
},
{
"feature": "Boolean Encoding",
"time": "2023/09/14 07:56:36",
"status": 30
},
{
"feature": "Eval Encryption",
"time": "2023/09/14 07:56:36",
"status": 27
},
{
"feature": "Encode Strings",
"time": "2023/09/14 07:56:36",
"status": 33
},
{
"feature": "Control Flow Flattening",
"time": "2023/09/14 07:56:36",
"status": 15
},
{
"feature": "Control Flow Shrinking",
"time": "2023/09/14 07:56:36",
"status": 3
},
{
"feature": "String Array",
"time": "2023/09/14 07:56:36",
"status": 41
},
{
"feature": "String Array Encoding",
"time": "2023/09/14 07:56:36",
"status": 41
},
{
"feature": "AST 2 JavaScript",
"time": "2023/09/14 07:56:36",
"status": 5086
}
]
}
var label = [{"name":"JavaScript"},{"name":"AST"}];
var source = [0];
var target =[1];
var value = [obfuscate_result.status[0].status];
for(i=1; i<obfuscate_result.status.length-1; i++){

label.push({"name":obfuscate_result.status[i].feature + " " + obfuscate_result.status[i].status} );
source.push(1)
target.push(i+1);
if(obfuscate_result.status[i].status == 0){
obfuscate_result.status[i].status =1;
}
value.push(obfuscate_result.status[i].status);
source.push(i+1)
target.push(obfuscate_result.status.length);
value.push(obfuscate_result.status[i].status);
}
label.push({"name":"AST"});
label.push({"name":"ObFuscated JavaScript"});
source.push(label.length-2)
target.push(label.length-1);
value.push(obfuscate_result.status[obfuscate_result.status.length-1].status);
var sankey_data= {}
sankey_data.nodes = label;
sankey_data.links = [];
for(i=0;i<source.length;i++){
sankey_data.links.push({"source":source[i],"target":target[i],"value":value[i]});
}
renderSankey({
el: 'obfuscate_sankey',
layoutStyle: {
width: 1000,
height: 680
},
data: sankey_data
})

</script>
</body>
</html>

更多推荐

操作系统期末复习笔记

文章目录操作系统第1章计算机系统概述1指令执行的基本指令周期2中断分类与中断处理过程2.1中断的定义2.2中断分类2.3中断的意义2.4无中断2.5有中断2.6中断和指令周期2.7中断处理的过程3处理多中断的两种方法3.1顺序中断处理(禁止中断)3.2嵌套中断处理4存储器4.1存储器层次层次结构的特点4.2二级存储器(

语义分割笔记(二):DeepLab V3对图像进行分割(自定义数据集从零到一进行训练、验证和测试)

文章目录一、语义分割介绍1.1语义分割和实例分割的区别1.2DeepLab系列对比二、代码下载2.1代码测试2.2视频学习三、数据集准备3.1Json转png3.2数据集划分四、模型训练五、模型测试六、模型评估一、语义分割介绍语义分割是计算机视觉中的一项技术,旨在将图像中的每个像素分配给特定的类别。它与目标检测不同,目

【map、set的封装】

目录前言一、map、set的框架搭建二、map、set的迭代器的封装2.1、map、set的迭代器的初步封装2.2、map、set的const迭代器的封装2.2.1、set的const迭代器的封装2.2.2、map的const迭代器的封装三、operator[]四、代码实现前言本文的代码是基于前一篇文章的红黑树的代码来

vue类与样式的绑定&&列表渲染

目录1.类与样式的绑定1.1绑定HTMLclass1.2绑定数组1.3绑定内联样式绑定数组2.列表渲染2.1v-for​2.2v-for与对象2.3在v-for里使用范围值​1.类与样式的绑定1.1绑定HTMLclass我们可以给:class(v-bind:class的缩写)传递一个对象来动态切换class:<div:

java操作es集群模糊查询等

首先引入依赖<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.17.13</version></dependency

linux安装配置 flume

目录一解压安装包二配置部署(1)修改配置(2)下载工具(3)创建配置文件(4)启动监听测试(5)flume监控文件一解压安装包这里提供了网盘资源链接:https://pan.baidu.com/s/1Z0aItCHMybYpXkt3_RUaVw?pwd=s6pg提取码:s6pg这里安装包是放到/opt/install文

Java中List转字符串的方法

一、使用String.join方法在Java8之后,String类增加了一个静态方法join(),可以方便地将列表中的元素连接成字符串。//创建ListList<String>list=Arrays.asList("Google","Baidu","Taobao");//以逗号分隔的形式输出整个列表Stringresu

微服务保护

1.初识Sentinel1.1.雪崩问题及解决方案1.雪崩问题微服务中,服务间调用关系错综复杂,一个微服务往往依赖于多个其它微服务。如图,如果服务提供者I发生了故障,当前的应用的部分业务因为依赖于服务I,因此也会被阻塞。此时,其它不依赖于服务I的业务似乎不受影响。但是,依赖服务I的业务请求被阻塞,用户不会得到响应,则t

在c#中使用CancellationToken取消任务

目录🚀介绍:🐤简单举例🚀IsCancellationRequested🚀ThrowIfCancellationRequested🐤在控制器中使用🚀通过异步方法的参数使用cancellationToken🚀api结合ThrowIfCancellationRequested()🚀介绍:Cancellatio

POJ 3185 The Water Bowls 反转+点灯游戏

一、题目大意有20盏灯(其实20盏灯数据量太少了,1e7我觉得差不多都可以过)放在同一行,点亮某一盏灯,它左右两边的灯也会亮,然后边缘特殊考虑,电亮两端的灯,只会照亮它相邻的那一个。二、解题思路这其实就是一个反转问题,我们从第二盏灯开始循环到第20盏灯,对于每一次循环的i,我们计算出i-1的灯是否亮着,如果i-1亮着,

Golang 中的匿名变量详解

在Golang中,可以使用匿名变量来忽略不需要的返回值或占位符。匿名变量是一种特殊类型的变量,可以简化代码并提高可读性。本文将详细介绍匿名变量的定义、特性和使用方法。什么是匿名变量?在Golang中,匿名变量是一种没有显式声明名称的变量,通常用于在需要临时存储值但不需要在后续代码中使用该值的情况。匿名变量的声明方式是使

热文推荐