3d标签云实现过程(tagcloud.js)同步原生和 vue

news2025/4/14 0:20:02
写在前面

本来是没有准备写这个知识点,但是下载这个 js 的时候发现很多都是要钱或者是积分的,我就不明白了一个开源了这么久的 js 怎么还有人拿来挣钱的,同时还有一些只有原生 html 的例子,但是现在都是 框架主导的一些项目,显然是不行的,这篇文章就简单的写一下 怎么使用原生和 vue 分别使用 tagcloudjs 实现标签云,喜欢的可以直接拿去用,当然你也可以直接参考这个的例子写,我没有试过,但是 demo 是可行的tagcloudjs. 当然防止你们下载失败,我最后面会将源码贴出来,直接用就可以了,但是 vue 实现的和原生实现的 js 有一点点的差别,因为原来的 tagcloudjs 无法给 vue 使用。

结果展示

大概就是下面这个样子
在这里插入图片描述

原生代码实现
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div class="wrapper">
			<div class="tagcloud fl">
				<span id="pagetext">CSDN 玩家 1</span>
				<span id="pagetext">CSDN 玩家 2</span>
				<span id="pagetext">CSDN 玩家 3</span>
				<span id="pagetext">CSDN 玩家 4</span>
				<span id="pagetext">CSDN 玩家 5</span>
				<span id="pagetext">CSDN 玩家 6</span>
				<span id="pagetext">CSDN 玩家 7</span>
				<span id="pagetext">CSDN 玩家 8</span>
				<span id="pagetext">CSDN 玩家 9</span>
			</div>
		</div>
		<script src="../assets/js/tagcloud.js"></script>
		<script>
			tagcloud({
				selector: '.tagcloud', //元素选择器
				fontsize: 16, //基本字体大小, 单位px
				radius: 100, //滚动半径, 单位px
				mspeed: 'normal', //滚动最大速度, 取值: slow, normal(默认), fast
				ispeed: 'normal', //滚动初速度, 取值: slow, normal(默认), fast
				direction: 135, //初始滚动方向, 取值角度(顺时针360): 0对应top, 90对应left, 135对应right-bottom(默认)...
				keep: false //鼠标移出组件后是否继续随鼠标滚动, 取值: false, true(默认) 对应 减速至初速度滚动, 随鼠标滚动
			});
		</script>
	</body>
	<style>
		.wrapper {
			width: 50%;
			height: 300px;
			margin: 0 auto;
			margin-top: 70px;
		}

		.tagcloud {
			position: relative;
			margin-top: 0px;
		}

		.tagcloud span {
			position: absolute;
			top: 0;
			left: 0;
			cursor: pointer;
			display: block;
			padding: 11px 30px;
			color: #60A2FF;
			font-size: 16px;
			border: 1px solid #e6e7e8;
			border-radius: 18px;
			background-color: #f2f4f8;
			text-decoration: none;
			white-space: nowrap;
			-o-box-shadow: 6px 4px 8px 0 rgba(151, 142, 136, .34);
			-ms-box-shadow: 6px 4px 8px 0 rgba(151, 142, 136, .34);
			-moz-box-shadow: 6px 4px 8px 0 rgba(151, 142, 136, .34);
			-webkit-box-shadow: 6px 4px 8px 0 rgba(151, 142, 136, .34);
			box-shadow: 6px 4px 8px 0 rgba(151, 142, 136, .34);
			-ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=4,Direction=135, Color='#000000')";
			/*兼容ie7/8*/
			filter: progid:DXImageTransform.Microsoft.Shadow(color='#969696', Direction=125, Strength=9);
			/*strength是阴影大小,direction是阴影方位,单位为度,可以为负数,color是阴影颜色 (尽量使用数字)使用IE滤镜实现盒子阴影的盒子必须是行元素或以行元素显示(block或inline-block;)*/
		}

		.tagcloud a:hover {
			color: #3385cf;
		}
	</style>
</html>
给原生 HTML 实现用的tagcloud.js源码
/*
* 3d标签云
* 功能:鼠标移入标签,当前标签静止放大
* 说明:
* */

window.tagcloud = (function(win, doc) { // ns
    // 判断对象
    function isObject (obj) {
        return Object.prototype.toString.call(obj) === '[object Object]';
    }

    // 构造函数
    function TagCloud (options) {
        var self = this;

        self.config = TagCloud._getConfig(options);
        self.box = self.config.element;   //组件元素
        self.fontsize = self.config.fontsize; //平均字体大小
        self.radius = self.config.radius; //滚动半径
        self.depth = 2 * self.radius;   //滚动深度
        self.size = 2 * self.radius;    //随鼠标滚动变速作用区域

        self.mspeed = TagCloud._getMsSpeed(self.config.mspeed);
        self.ispeed = TagCloud._getIsSpeed(self.config.ispeed);
        self.items = self._getItems();

        self.direction = self.config.direction;   //初始滚动方向
        self.keep = self.config.keep; //鼠标移出后是否保持之前滚动

        //初始化
        self.active = false;   //是否为激活状态
        self.lasta = 1;
        self.lastb = 1;
        self.mouseX0 = self.ispeed * Math.sin(self.direction * Math.PI / 180);    //鼠标与滚动圆心x轴初始距离
        self.mouseY0 = -self.ispeed * Math.cos(self.direction * Math.PI / 180);   //鼠标与滚动圆心y轴初始距离
        self.mouseX = self.mouseX0;   //鼠标与滚动圆心x轴距离
        self.mouseY = self.mouseY0;   //鼠标与滚动圆心y轴距离
        self.index = -1;

        //鼠标移入
        TagCloud._on(self.box, 'mouseover', function () {
            self.active = true;
        });
        //鼠标移出
        TagCloud._on(self.box, 'mouseout', function () {
            self.active = false;
        });

        //鼠标在内移动
        TagCloud._on(self.keep ? win : self.box, 'mousemove', function (ev) {
            var oEvent = win.event || ev;
            var boxPosition = self.box.getBoundingClientRect();
            self.mouseX = (oEvent.clientX - (boxPosition.left + self.box.offsetWidth / 2)) / 5;
            self.mouseY = (oEvent.clientY - (boxPosition.top + self.box.offsetHeight / 2)) / 5;
        });

        for (var j = 0, len = self.items.length; j < len; j++) {
            self.items[j].element.index=j;

            //鼠标移出子元素,当前元素静止放大
            self.items[j].element.onmouseover = function(){
                self.index = this.index;
            };

            //鼠标移出子元素,当前元素继续滚动
            self.items[j].element.onmouseout = function(){
                self.index = -1;
            };
        }

        //定时更新
        TagCloud.boxs.push(self.box);
        self.update(self);    //初始更新
        self.box.style.visibility = "visible";
        self.box.style.position = "relative";
        self.box.style.minHeight = 1.2 * self.size + "px";
        self.box.style.minWidth = 2.5 * self.size + "px";
        for (var j = 0, len = self.items.length; j < len; j++) {
            self.items[j].element.style.position = "absolute";
            self.items[j].element.style.zIndex = j + 1;
        }
        self.up = setInterval(function() {
            self.update(self);
        }, 30);
    }

    //实例
    TagCloud.boxs = []; //实例元素数组
    // 静态方法们
    TagCloud._set = function (element) {
        if (TagCloud.boxs.indexOf(element) == -1) {//ie8不支持数组的indexOf方法
            return true;
        }
    };

    //添加数组IndexOf方法
    if (!Array.prototype.indexOf){
        Array.prototype.indexOf = function(elt /*, from*/){
            var len = this.length >>> 0;
            var from = Number(arguments[1]) || 0;
            from = (from < 0)
                ? Math.ceil(from)
                : Math.floor(from);
            if (from < 0)
                from += len;

            for (; from < len; from++){
                if (from in this && this[from] === elt)
                    return from;
            }
            return -1;
        };
    }


    TagCloud._getConfig = function (config) {
        var defaultConfig = {   //默认值
            fontsize: 16,       //基本字体大小, 单位px
            radius: 60,         //滚动半径, 单位px
            mspeed: "normal",   //滚动最大速度, 取值: slow, normal(默认), fast
            ispeed: "normal",   //滚动初速度, 取值: slow, normal(默认), fast
            direction: 135,     //初始滚动方向, 取值角度(顺时针360): 0对应top, 90对应left, 135对应right-bottom(默认)...
            keep: true          //鼠标移出组件后是否继续随鼠标滚动, 取值: false, true(默认) 对应 减速至初速度滚动, 随鼠标滚动
        };

        if(isObject(config)) {
            for(var i in config) {
                if(config.hasOwnProperty(i)) {//hasOwnProperty()用来判断一个属性是定义在对象本身而不是继承自原型链
                    defaultConfig[i] = config[i]; //用户配置
                }
            }
        }

        return defaultConfig;// 配置 Merge
    };
    TagCloud._getMsSpeed = function (mspeed) {    //滚动最大速度
        var speedMap = {
            slow: 1.5,
            normal: 3,
            fast: 5
        };
        return speedMap[mspeed] || 3;
    };
    TagCloud._getIsSpeed = function (ispeed) {    //滚动初速度
        var speedMap = {
            slow: 10,
            normal: 25,
            fast: 50
        };
        return speedMap[ispeed] || 25;
    };
    TagCloud._getSc = function(a, b) {
        var l = Math.PI / 180;
        //数组顺序0,1,2,3表示asin,acos,bsin,bcos
        return [
            Math.sin(a * l),
            Math.cos(a * l),
            Math.sin(b * l),
            Math.cos(b * l)
        ];
    };

    TagCloud._on = function (ele, eve, handler, cap) {
        if (ele.addEventListener) {
            ele.addEventListener(eve, handler, cap);
        } else if (ele.attachEvent) {
            ele.attachEvent('on' + eve, handler);
        } else {
            ele['on' + eve] = handler;
        }
    };

    // 原型方法
    TagCloud.prototype = {
        constructor: TagCloud, // 反向引用构造器

        update: function () {
            var self = this, a, b;

            if (!self.active && !self.keep) {
                self.mouseX = Math.abs(self.mouseX - self.mouseX0) < 1 ? self.mouseX0 : (self.mouseX + self.mouseX0) / 2;   //重置鼠标与滚动圆心x轴距离
                self.mouseY = Math.abs(self.mouseY - self.mouseY0) < 1 ? self.mouseY0 : (self.mouseY + self.mouseY0) / 2;   //重置鼠标与滚动圆心y轴距离
            }

            a = -(Math.min(Math.max(-self.mouseY, -self.size), self.size) / self.radius ) * self.mspeed;
            b = (Math.min(Math.max(-self.mouseX, -self.size), self.size) / self.radius ) * self.mspeed;

            if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) { return; }

            self.lasta = a;
            self.lastb = b;

            var sc = TagCloud._getSc(a, b);

            for (var j = 0, len = self.items.length; j < len; j++) {

                var rx1 = self.items[j].x,
                    ry1 = self.items[j].y*sc[1] + self.items[j].z*(-sc[0]),
                    rz1 = self.items[j].y*sc[0] + self.items[j].z*sc[1];

                var rx2 = rx1 * sc[3] + rz1 * sc[2],
                    ry2 = ry1,
                    rz2 = rz1 * sc[3] - rx1 * sc[2];

                if(self.index==j){

                    self.items[j].scale = 1; //取值范围0.6 ~ 3
                    self.items[j].fontsize = 16;
                    self.items[j].alpha = 1;
                    self.items[j].element.style.zIndex = 99;
                }else{
                    var per = self.depth / (self.depth + rz2);
                    self.items[j].x = rx2;
                    self.items[j].y = ry2;
                    self.items[j].z = rz2;

                    self.items[j].scale = per; //取值范围0.6 ~ 3
                    self.items[j].fontsize = Math.ceil(per * 2) + self.fontsize - 6;
                    self.items[j].alpha = 1.5 * per - 0.5;
                    self.items[j].element.style.zIndex = Math.ceil(per*10-5);
                }
                self.items[j].element.style.fontSize = self.items[j].fontsize + "px";
                self.items[j].element.style.left = self.items[j].x + (self.box.offsetWidth - self.items[j].offsetWidth) / 2 + "px";
                self.items[j].element.style.top = self.items[j].y + (self.box.offsetHeight - self.items[j].offsetHeight) / 2 + "px";
                self.items[j].element.style.filter = "alpha(opacity=" + 100 * self.items[j].alpha + ")";
                self.items[j].element.style.opacity = self.items[j].alpha;
            }
        },

        _getItems: function () {
            var self = this,
                items = [],
                element = self.box.children, // children 全部是Element
                length = element.length,
                item;

            for (var i = 0; i < length; i++) {
                item = {};
                item.angle = {};
                item.angle.phi = Math.acos(-1 + (2 * i + 1) / length);
                item.angle.theta = Math.sqrt((length + 1) * Math.PI) * item.angle.phi;
                item.element = element[i];
                item.offsetWidth = item.element.offsetWidth;
                item.offsetHeight = item.element.offsetHeight;
                item.x = self.radius * 1.5 * Math.cos(item.angle.theta) * Math.sin(item.angle.phi);
                item.y = self.radius * 1.5 * Math.sin(item.angle.theta) * Math.sin(item.angle.phi);
                item.z = self.radius * 1.5 * Math.cos(item.angle.phi);
                item.element.style.left = item.x + (self.box.offsetWidth - item.offsetWidth) / 2 + "px";
                item.element.style.top = item.y + (self.box.offsetHeight - item.offsetHeight) / 2 + "px";
                items.push(item);
            }

            return items;   //单元素数组
        }



    };

    if (!doc.querySelectorAll) {//ie7不支持querySelectorAll,所以要重新定义
        doc.querySelectorAll = function (selectors) {
            var style = doc.createElement('style'), elements = [], element;
            doc.documentElement.firstChild.appendChild(style);
            doc._qsa = [];

            style.styleSheet.cssText = selectors + '{x-qsa:expression(document._qsa && document._qsa.push(this))}';
            window.scrollBy(0, 0);
            style.parentNode.removeChild(style);

            while (doc._qsa.length) {
                element = doc._qsa.shift();
                element.style.removeAttribute('x-qsa');
                elements.push(element);
            }
            doc._qsa = null;
            return elements;
        };
    }

    return function (options) { // factory
        options = options || {}; // 短路语法
        var selector = options.selector || '.tagcloud', //默认选择class为tagcloud的元素
            elements = doc.querySelectorAll(selector),
            instance = [];
        for (var index = 0, len = elements.length; index < len; index++) {
            options.element = elements[index];
            if (!!TagCloud._set(options.element)) {
                instance.push(new TagCloud(options));
            }
        }
        return instance;
    };

})(window, document);


vue 实现
<template>
	<div class="tagcloud">
		<span v-for="i in 10">CSDN 玩家{{ i}}</span>
	</div>
</template>

<script setup>
	import { onMounted } from 'vue';
	import { tagcloud } from '../../src/assets/tagcloud.js'
	onMounted(() => {
		tagcloud({
			selector: '.tagcloud', //元素选择器
			fontsize: 16, //基本字体大小, 单位px
			radius: 100, //滚动半径, 单位px
			mspeed: 'normal', //滚动最大速度, 取值: slow, normal(默认), fast
			ispeed: 'normal', //滚动初速度, 取值: slow, normal(默认), fast
			direction: 135, //初始滚动方向, 取值角度(顺时针360): 0对应top, 90对应left, 135对应right-bottom(默认)...
			keep: false //鼠标移出组件后是否继续随鼠标滚动, 取值: false, true(默认) 对应 减速至初速度滚动, 随鼠标滚动
		});
	})
</script>
  • style 同原生的一致,这里不贴代码了,避免文章太长你们看着烦
给 vue 实现用的 tagcloud.js
export const tagcloud = (function (win = window, doc = document)

将原生js 中的第一行代码改为上面的即可,将 tagcloud 导出去就可以给 vue 直接使用了,这里需要注意的一点是用的时候需要保证页面DOM 元素全部加载结束再执行 tagcloud 的方法,否则是无法加载出来的,这个和 echartsjs 用法是保持一致的,因为这些图形类的 js 使用的前提条件就是你的 DOM 元素需要存在,否则都是徒劳,当你没有效果的时候检查一下是不是 DOM 加载失败了或者是没有加载出来即可

写在后面

以上就是关于 tagcloudjs 用法的讲解了,整好最近我手里有需求需要用到这块,顺手将这个分享出去,大家用的时候有什么问题随时下面留言即可!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1239771.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2017年全国硕士研究生入学统一考试管理类专业学位联考数学试题——解析版

文章目录 2017 级考研管理类联考数学真题解析一、问题求解&#xff08;本大题共 5 小题&#xff0c;每小题 3 分&#xff0c;共 45 分&#xff09;下列每题给出 5 个选项中&#xff0c;只有一个是符合要求的&#xff0c;请在答题卡上将所选择的字母涂黑。真题&#xff08;2017-…

Android : ListView + BaseAdapter-2简单应用

​​容器与适配器&#xff1a;​​​​​ http://t.csdnimg.cn/ZfAJ7 实体类 News.java package com.example.mylistviewadapter2.entity;public class News {private String title;private String content;private int img;public News(String title, String conte…

蓝桥杯物联网_STM32L071_2_继电器控制

CubeMX配置&#xff1a; Function.c及Function.h&#xff1a; #include "Function.h" #include "gpio.h" void Function_LD5_ON(void){HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_RESET); }void Function_LD5_OFF(void){HAL_GPIO_WritePin(LD5_…

O2OA(翱途)开发平台 V8.2已发布,更安全、更高效、更开放

尊敬的 O2OA (翱途) 平台合作伙伴、用户以及亲爱的开发小伙伴们&#xff0c;V8.2 版本已正式发布&#xff0c;大家可以去官网上下载最新版本。 上次 8.1 的发布是在 9 月 1 日&#xff0c;又过去两个多月&#xff0c;O2OA 研发团队始终踏踏实实地做好产品的研发及优化工作&…

01背包与完全背包学习总结

背包问题分类见下图 参考学习点击&#xff1a;代码随想录01背包讲解 01背包问题&#xff1a; 核心思路&#xff1a; 1、先遍历物品个数&#xff0c;再遍历背包容量。因为容量最先是最大的&#xff0c;往背包里放物品&#xff0c;所以背包容量在慢慢减少&#xff0c;但背包容量…

【数据结构】动态顺序表详解

目录 1.顺序表的概念及结构 2.动态顺序表的实现 2.1创建新项目 2.2动态顺序表的创建 2.3接口的实现及测其功能 2.3.1初始化 2.3.2尾插 2.3.3头插 2.3.4尾删&头删 2.3.5打印&从任意位置插入 2.3.6删除任意位置的数据 2.3.7查找 2.3.8销毁顺序表 3.结语 He…

AIGC,ChatGPT AI绘画 Midjourney 注册流程详细步骤

AI 绘画,Midjourney完成高清图片绘制,轻松掌握AI工具。 前期准备: ① 一个能使用的谷歌账号 ② 可以访问外网 Midjourney注册 1.进入midjourney官网https://www.midjourney.com 点击左下角”Join the Beta”,就可以注册,第一次使用的小伙伴会弹出提示,只需要点击Acc…

Python开发运维:Celery连接Redis

目录 一、理论 1.Celery 二、实验 1.Windows11安装Redis 2.Python3.8环境中配置Celery 三、问题 1.Celery命令报错 2.执行Celery命令报错 3.Win11启动Celery报ValueErro错误 一、理论 1.Celery (1) 概念 Celery是一个基于python开发的分布式系统&#xff0c;它是简单…

Nevron Vision for .NET 2023.1 Crack

Nevron Vision for .NET 适用于桌面和 Web 应用程序的高级数据可视化 Nevron Vision for .NET提供最全面的组件&#xff0c;用于构建面向 Web 和桌面的企业级数据可视化应用程序。 该套件中的组件具有连贯的 2D 和 3D 数据可视化效果&#xff0c;对观众产生巨大的视觉冲击力。我…

Vue3常用操作

一、Vue3项目构建 1、安装最新版本vue npm create vuelatest 2、选择需要的配置 3、进入项目 cd 项目名称 4、下载依赖 npm install 5、启动项目 npm run dev

oracle面试相关的,Oracle基本操作的SQL命令

文章目录 数据库-Oracle〇、Oracle用户管理一、Oracle数据库操作二、Oracle表操作1、创建表2、删除表3、重命名表4、增加字段5、修改字段6、重名字段7、删除字段8、添加主键9、删除主键10、创建索引11、删除索引12、创建视图13、删除视图 三、Oracle操作数据1、数据查询2、插入…

MySQL面试,MySQL事务,MySQL锁,MySQL集群,主从,MySQL分区,分表,InnoDB

文章目录 数据库-MySQLMySQL主从、集群模式简单介绍1、主从模式 Replication2、集群模式3、主从模式部署注意事项 UNION 和 UNION ALL 区别分库分表1.垂直拆分2、水平拆分 MySQL有哪些数据类型1、整数类型**&#xff0c;2、实数类型**&#xff0c;3、字符串类型**&#xff0c;4…

【西行纪年番】孙悟空对战阴界王,素衣奄奄一息,巨灵拳霸气一击

Hello,小伙伴们&#xff0c;我是拾荒君。 《西行纪年番》第20集已更新。为了救回素衣&#xff0c;孙悟空想尽办法&#xff0c;最后他拜托沙悟净帮忙&#xff0c;终于成功把自己传送到阴界。原来&#xff0c;素衣的魂魄被阴界王藏在了他制造的人偶之中。沙悟净提醒孙悟空必须在…

为UE和Unity开发者准备的Godot指南

为UE和Unity开发者准备的Godot指南 ——两位大哥打架&#xff0c;请带上我 这两天游戏行业又开始热闹了&#xff0c;昨天两条信息直接刷爆朋友圈&#xff0c;最大的两家游戏引擎公司怼起来了。 《为Unity开发者准备的虚幻引擎指南》&#xff1a; 为Unity开发者准备的虚幻引擎指…

不存在类型变量 A, T 的实例,使 Collector<T, A, List<T>> 符合 Supplier<R>

报错信息 原因: 不存在类型变量 A, T 的实例&#xff0c;使 Collector<T, A, List<\T>> 符合 Supplier<\R> 来源 测试Stream流的map方法&#xff0c;做算法习惯基本类型定义数组。 map方法:Stream API的一部分。允许以一种声明式的方式处理数据&#xff0c…

Shell判断:模式匹配:case(三)

系统管理工具箱 1、需求&#xff1a;Linux提供的丰富的管理命令&#xff0c;用户管理&#xff0c;内存管理&#xff0c;磁盘管理&#xff0c;进程管理&#xff0c;日志管理&#xff0c;文件管理&#xff0c;软件管理&#xff0c;网络管理等等数十个工具包。如果你能通过shell编…

大二第五周总结

你知道的&#xff0c;向来如此&#xff0c;从来没人关心&#xff0c;世人从来只看重结果。对你了解越多的人&#xff0c;往你心里面捅刀子的时候也是最狠&#xff0c;不过跟之前不一样了&#xff0c;又不是曾经那个任人欺负的小孩儿了&#xff0c;所有的努力在别人眼里就是屁都…

【资深硬件工程师总结-千兆以太网设计指南】

文章目录 01通用PCB布线指南02标志焊盘中的接地过孔区示例03EMI注意事项04ESD注意事项 资深硬件工程师总结-千兆以太网设计指南 本应用笔记旨在帮助客户使用Microchip的10/100/1000 Mbps以太网器件系列设计PCB。本文档提供有关PCB布线的建 议&#xff0c; PCB 布线是保持信号完…

hp惠普Victus Gaming Laptop 15-fa1025TX/fa1005tx原装出厂Win11系统ISO镜像

光影精灵9笔记本电脑原厂W11系统22H2恢复出厂时开箱状态一模一样 适用型号&#xff1a;15-fa1003TX&#xff0c;15-fa1005TX&#xff0c;15-fa1007TX&#xff0c;15-fa1025TX 链接&#xff1a;https://pan.baidu.com/s/1fBPjed1bhOS_crGIo2tP1w?pwduzvz 提取码&#xff1a…

10、信息打点——APP小程序篇抓包封包XP框架反编译资产提取

APP信息搜集思路 外在——抓包封包——资产安全测试 抓包&#xff08;Fiddle&茶杯&burp&#xff09;封包&#xff08;封包监听工具&#xff09;&#xff0c;提取资源信息 资产收集——资源提取——ICO、MAD、hash——FOFA等网络测绘进行资产搜集 外在——功能逻辑 内在…