自定义复杂AntV/G6案例
一、效果图
二、源码
/**
*
* Author: me
* CreatDate: 2024-08-22
*
* Description: 复杂G6案例
*
*/
<template><div class="moreG6-wapper"><div id="graphContainer" ref="graphRef" class="graph-content"></div></div>
</template><script>
import G6 from "@antv/g6";
export default {name: "moreG6",components: {},props: {},data() {return {graph: null, // G6 实例graphData: {nodes: [],edges: [],},dataList: [{name: "第一阶段",aimData: [{title: "张三",aim: "战胜李四",type: 1,},{title: "李四",aim: "战胜张三",type: 2,},],eventData: [{time: "1948年11月6日",isLeft: true, // 在左边还是在右边dataList: {title: "发现王五正在收缩",type: 1,domain: "综合",describe: "发现王五正在收缩,当即转入追击",children: [{title: "张三攻占a区,没发现李四",type: 1,domain: "战斗",describe: "",},{title: "李四调动李白",type: 1,domain: "战斗",describe: "",},],},},{time: "1948年11月7日",isLeft: false,dataList: {title: "张三团守a州,同时向b州东进",type: 2,domain: "综合",describe: "张三团守a州,令小红、小兰两人回b州东进",children: [{title: "李四在b官邸",type: 2,domain: "战斗",describe: "",},],},},],},{name: "第二阶段",aimData: [{title: "小红",aim: "战胜王五",type: 1,},{title: "小兰",aim: "战胜王五",type: 1,},{title: "王五",aim: "战胜张三",type: 2,},],eventData: [{time: "1948年11月6日",isLeft: true,dataList: {title: "发现王五正在收缩",type: 1,domain: "综合",describe: "发现王五正在收缩,当即转入追击",children: [{title: "张三攻占a区,没发现李四",type: 1,domain: "战斗",describe: "",},{title: "李四调动李白",type: 1,domain: "战斗",describe: "",},{title: "李四造谣张三",type: 1,domain: "舆论",describe: "",},],},},{time: "1948年11月7日",isLeft: false,dataList: {title: "张三团守a州",type: 2,domain: "综合",describe: "张三团守a州,令小红、小兰两人回徐州东进",children: [{title: "李四在b官邸",type: 2,domain: "前进",describe: "",},{title: "小兰垄断李四的口粮",type: 2,domain: "商战",describe: "",},],},},],},{name: "第三阶段",},{name: "第四阶段",},],bgColor: "#0B1E4C",stageSize: [110, 40],aimSize: [150, 30],eventSize: [176, 46],eventContentSize: [182, 90],eventDataSize: [120, 40],stageSpace: 100,openSpace: 40,aimSpace: 150,eventSpace: 220,domainW: 28,};},mounted() {this.$nextTick(() => {this.initData();this.initGraph();this.drawGraph();});},methods: {/*** 根据数据生成节点和边数据*/initData() {const that = this;const dom = this.$refs.graphRef;const centerX = dom.offsetWidth / 2;this.dataList.forEach((stage, index) => {const pl = ((stage.partieList?.length || 0) / 2) * that.aimSize[1];let eventLen = 0;if (index === 0) {stage.y = 40 + pl;} else {eventLen = this.dataList[index - 1].eventData?.length || 0;stage.y =this.dataList[index - 1].y +eventLen * that.eventSpace +that.stageSpace * 2 +pl;}// 1.阶段总线const stageNde = {id: `stageNode${index}`, // 元素的 idlabel: stage.name, // 标签文字x: centerX,y: stage.y,type: "rect", // 元素的图形size: that.stageSize, // 元素的大小// 标签配置属性labelCfg: {positions: "center", // 标签在元素中的位置// 包裹标签样式属性的字段 style 与标签其他属性在数据结构上并行style: {fill: "#fff", // 填充色,这里是文字颜色fontSize: 16,// fontWeight: "bold",fontFamily: "黑体",},},// 包裹样式属性的字段 style 与其他属性在数据结构上并行style: {lineWidth: 2,fill: "#0F3664", // 元素的填充色stroke: "#fff", // 元素的描边色radius: 20, // 圆角},// 锚点anchorPoints: [[1, 0.5], // 右中[0.5, 1], // 下中],};this.graphData.nodes.push(stageNde);if (index !== 0) {const stageLine = {id: `stageLine${index}`,source: `stageNode${index - 1}`, // 和上面的保持一致target: `stageNode${index}`,type: "line", // 边形状style: {lineWidth: 2,color: "#fff",opacity: 0.7, // 边透明度},};this.graphData.edges.push(stageLine);}// 2.阶段-目标数据if (stage.aimData && stage.aimData.length) {const adl = stage.aimData.length;// 目标数据stage.aimData.forEach((aim, aimIndex) => {// aimNodeY 先大概吧,后面再重新计算优化一下const aimNodeY =stage.y + (that.aimSize[1] + 10) * aimIndex - pl - adl * 12;// 目标标题const aimNode = {id: `aimNode${index}${aimIndex}`,label: aim.title + "目标",x: centerX + that.stageSize[0] + that.openSpace * 2.5,y: aimNodeY,type: "rect",size: that.aimSize,labelCfg: {style: {textAlign: "center",fill: "#fff",fontSize: 14,fontFamily: "黑体",},},style: {lineWidth: 0,fill: aim.type === 1 ? "#E16E76" : "#1685F3",radius: [0, 15, 15, 0],},anchorPoints: [[0, 0.5],[1, 0.5],],};this.graphData.nodes.push(aimNode);// 目标内容const aimContentNode = {id: `aimContentNode${index}${aimIndex}`,label: aim.aim,x: centerX + that.stageSize[0] + that.openSpace * 6.5,y: aimNodeY,type: "rect",size: [0, 40],labelCfg: {positions: "left",style: {textAlign: "left",fill: "#fff",fontSize: 14,opacity: 0.7,fontFamily: "黑体",},},style: {lineWidth: 0,fill: that.bgColor,},anchorPoints: [[0, 0.5]],};this.graphData.nodes.push(aimContentNode);// 连线const aimLine = {id: `aimLine${index}${aimIndex}`,source: `stageNode${index}`,target: `aimNode${index}${aimIndex}`,type: "cubic-horizontal", // 边形状style: {lineWidth: 1,fill: "transparent", // 设置透明背景色opacity: 0.7,},};const aimContentLine = {id: `aimContentLine${index}${aimIndex}`,source: `aimNode${index}${aimIndex}`,target: `aimContentNode${index}${aimIndex}`,type: "line", // 边形状style: {lineWidth: 1,fill: "#ffffff",opacity: 0.7,},};this.graphData.edges.push(aimLine);this.graphData.edges.push(aimContentLine);});}// 3.时间事件数据if (stage.eventData && stage.eventData.length) {stage.eventData.forEach((event, eventIndex) => {event.x = event.isLeft? -centerX + that.stageSize[0] + that.openSpace * 4: centerX + that.stageSize[0] + that.openSpace * 4;event.y =stage.y +eventIndex * that.eventSpace +that.aimSize[1] +that.openSpace * 2.5; // 先大概吧,后面再重新计算优化一下// 时间const timeNode = {id: `timeNode${index}${eventIndex}`,label: event.time,x: event.isLeft ? centerX - 10 : centerX + 10,y: event.y - 16,type: "rect",size: [0, 40],labelCfg: {positions: event.isLeft ? "right" : "left",style: {textAlign: event.isLeft ? "right" : "left",fill: "#fff",fontSize: 14,opacity: 0.8,fontFamily: "黑体",},},style: {lineWidth: 0,fill: that.bgColor,},};this.graphData.nodes.push(timeNode);// 事件标题const eventNode = {id: `eventNode${index}${eventIndex}`,label: that.fittingString(event.dataList.title, 9),labelInit: event.dataList.title,x: event.isLeft? -event.x - that.domainW + 12: event.x + that.domainW - 12,y: event.y,type: "rect",size: that.eventSize,labelCfg: {positions: event.isLeft ? "right" : "left",style: {textAlign: "center",fill: "#fff",fontSize: 14,fontFamily: "黑体",},},style: {lineWidth: 0,fill: event.dataList.type === 1 ? "#E16E76" : "#1685F3",radius: event.isLeft ? [24, 0, 0, 24] : [0, 24, 24, 0],},anchorPoints: [[0, 0.5],[1, 0.5],],};this.graphData.nodes.push(eventNode);// 领域const realmNode = {id: `realmNode${index}${eventIndex}`,label: [...event.dataList.domain].join("\n"),x: event.isLeft? -event.x + that.openSpace * 2 + 6: event.x - that.openSpace * 2 - 6,y: event.y,type: "rect",size: [that.domainW, that.eventSize[1]],labelCfg: {positions: "center",style: {textAlign: "center",fill: "#fff",fontSize: 14,fontFamily: "黑体",},},style: {lineWidth: 1,fill: event.dataList.type === 1 ? "#E16E76" : "#1685F3",stroke: event.dataList.type === 1 ? "#EDA9AE" : "#76B7F8", // 元素的描边色},};this.graphData.nodes.push(realmNode);// 内容const eventContentNode = {id: `eventContentNode${index}${eventIndex}`,label: event.dataList.describe? that.divideString(event.dataList.describe, 11, 4): "暂无描述",labelInit: event.dataList.describe,x: event.isLeft ? -event.x + 9 : event.x - 9,y: event.y + that.eventSize[1] + 22,type: "rect",size: that.eventContentSize,labelCfg: {positions: "center",style: {textAlign: "center",fill: "#fff",fontSize: 14,fontFamily: "黑体",},},style: {lineWidth: 1,fill: "#3C4B70",stroke: "#5C6988", // 元素的描边色opacity: 0.9,},};this.graphData.nodes.push(eventContentNode);// 连线const eventLine = {id: `eventLine${index}${eventIndex}`,source: `stageNode${index}`,target: `eventNode${index}${eventIndex}`,type: "polyline", // 边形状style: {lineWidth: 1,fill: "transparent",opacity: 0.7,},};this.graphData.edges.push(eventLine);// 4.时间事件后面的列表if (event.dataList.children && event.dataList.children.length) {event.dataList.children.forEach((eventData, eventDataIndex) => {const x =event.x +that.eventSize[0] +that.openSpace * 3 +eventDataIndex *(that.eventDataSize[0] + that.openSpace * 1.4);const y = event.y + that.openSpace;// 标题const eventDataNode = {id: `eventDataNode${index}${eventIndex}${eventDataIndex}`,label: that.fittingString(eventData.title, 6),labelInit: eventData.title,x: event.isLeft? -x - that.domainW + 14: x + that.domainW - 14,y: y,type: "rect",size: that.eventDataSize,labelCfg: {positions: event.isLeft ? "right" : "left",style: {textAlign: "center",fill: "#fff",fontSize: 14,fontFamily: "黑体",},},style: {lineWidth: 0,fill: event.dataList.type === 1 ? "#E16E76" : "#1685F3",},anchorPoints: [[0.5, 0]],};this.graphData.nodes.push(eventDataNode);// 领域const realmNode02 = {id: `realmNode${index}${eventIndex}${eventDataIndex}02`,label: [...eventData.domain].join("\n"),x: event.isLeft ? -x + 60 : x - 60,y: y,type: "rect",size: [that.domainW, that.eventDataSize[1]],labelCfg: {positions: "center",style: {textAlign: "center",fill: "#fff",fontSize: 14,fontFamily: "黑体",},},style: {lineWidth: 1,fill: event.dataList.type === 1 ? "#E16E76" : "#1685F3",stroke: event.dataList.type === 1 ? "#EDA9AE" : "#76B7F8", // 元素的描边色},};this.graphData.nodes.push(realmNode02);// 内容const eventContentNode02 = {id: `eventContentNode${index}${eventIndex}${eventDataIndex}02`,label: eventData.describe? that.divideString(eventData.describe, 9, 3): "暂无描述",labelInit: eventData.describe,x: event.isLeft ? -x : x,y: y + that.eventDataSize[1] + 18,type: "rect",size: [that.eventDataSize[0] + that.domainW,that.eventContentSize[1] * 0.85,],labelCfg: {positions: "center",style: {textAlign: "center",fill: "#fff",fontSize: 14,fontFamily: "黑体",},},style: {lineWidth: 1,fill: "#3C4B70",stroke: "#5C6988",opacity: 0.9,},};this.graphData.nodes.push(eventContentNode02);// 连线const eventLine = {id: `eventLine${index}${eventIndex}${eventDataIndex}`,source: `eventNode${index}${eventIndex}`,target: `eventDataNode${index}${eventIndex}${eventDataIndex}`,type: "polyline", // 边形状style: {lineWidth: 1,fill: "transparent", // 透明色opacity: 0.7,},};this.graphData.edges.push(eventLine);});}});}});},/*** 初始化graph实例*/initGraph() {// 缩略图const minimap = new G6.Minimap({size: [window.innerWidth / 6, window.innerHeight / 4],});// 提示框const tooltip = new G6.Tooltip({offsetX: 10,offsetY: 10,size: [100, 100],itemTypes: ["node"], // 允许出现 tooltip 的 item 类型// 自定义 tooltip 内容getContent: (e) => {const outDiv = document.createElement("div");outDiv.style.width = "fit-content";outDiv.innerHTML = `<div style="max-width:200px;">${e.item.getModel().labelInit || e.item.getModel().label}</div>`;return outDiv;},// 哪些要设置提示框shouldBegin: (e) => {const id = e.item.getModel().id;const a = id.includes("eventNode");const b = id.includes("eventContentNode");const c = id.includes("eventDataNode");const is = a || b || c;return is;},});// 容器节点const dom = this.$refs.graphRef;// 配置参数const options = {container: "graphContainer", // 画布的容器idwith: dom.offsetWidth, // 画布宽度height: dom.offsetHeight, // 画布高度minZoom: 0.2,maxZoom: 5,// 图交互模式modes: {default: ["drag-canvas", "zoom-canvas"], // 允许拖拽画布、缩放画布},plugins: [tooltip, minimap], // 插件};// 实例化this.graph = new G6.Graph(options);// 自适应this.resizeView();// 监听窗口大小变化window.addEventListener("resize", this.resizeView);},/*** 画图*/drawGraph() {// 清除画布元素this.graph.clear();// 数据源this.graph.data(this.graphData);// 渲染this.graph.render();},/*** 自适应*/resizeView() {const dom = this.$refs.graphRef;if (dom && this.graph) {this.graph.changeSize(dom.offsetWidth, dom.offsetHeight); // 修改画布大小// this.graph.fitCenter(); // 移至中心}},/*** 字符串等长划分-入口事件* @param str 字符串* @param len 一行的长度* @param row 行数*/divideString(str, len, row = 3) {str = this.fittingString(str, len * row - 2);const result = this.divideHandle(str, len);return result.join("\n");},/*** 字符串等长划分* @param str 字符串* @param len 划分的长度*/divideHandle(str, len) {if (str.length <= len) {return [str];}const chunk = str.substring(0, len);const arr = [chunk, ...this.divideHandle(str.substring(len), len)];return arr;},/*** 截取字符串,超出多少len省略* @param str 字符串* @param len 长度*/fittingString(str, len) {if (str.length <= len) {return str;}const result = str.substring(0, len) + "…";return result;},},beforeDestroy() {this.graph && this.graph.destroy();},watch: {},
};
</script><style lang='scss' scoped>
.moreG6-wapper {height: 100%;background: #0b1e4c;.graph-content {width: 100%;height: 96%;::v-deep .g6-tooltip {border: 1px solid #e2e2e2;border-radius: 4px;font-size: 12px;color: #545454;background-color: rgba(255, 255, 255, 0.9);padding: 10px 8px;box-shadow: rgb(174, 174, 174) 0px 0px 10px;}::v-deep .g6-minimap {position: absolute;right: 0;top: 61px;background-color: #0b1e4c;}}
}
</style>
三、记录说明
-
当前使用版本:
"@antv/g6": "^4.8.21"
-
官方文档节点形状为shape,但是在不记得哪个版本后,
shape
改为type
,当时整了好久,形状就是不生效,原来是字段改变了,这个坑要注意 -
初步接触就有这么个界面需求,官方文档有点乱,且不全面,新手小白上路属实有点头皮发麻,后来也琢磨出来一些:
- 官方案例实现不了的,自己画
- 无非就是两个要点:节点、边
- 像这案例一样的不能使用居中api的,得自己计算节点的位置
- 实现不了的不影响使用的小功能,就干掉它,不要了…
-
期间遇到还没解决的问题:
- 使用
image
内置节点,自己的图片显示有问题 polyline
样式的连线拐点问题,本来定在边角的锚点,但是拐点太多了不齐整,后来就直接锚点在中间了…- 本来有个节点收缩/展开的功能,后来没做了,这个后面再研究研究…
- 使用
相关文章:

自定义复杂AntV/G6案例
一、效果图 二、源码 /** * * Author: me * CreatDate: 2024-08-22 * * Description: 复杂G6案例 * */ <template><div class"moreG6-wapper"><div id"graphContainer" ref"graphRef" class"graph-content"></d…...

Golang | Leetcode Golang题解之第419题棋盘上的战舰
题目: 题解: func countBattleships(board [][]byte) (ans int) {for i, row : range board {for j, ch : range row {if ch X && !(i > 0 && board[i-1][j] X || j > 0 && board[i][j-1] X) {ans}}}return }...

CCF刷题计划——LDAP(交集、并集 how to go)
LDAP 计算机软件能力认证考试系统 不知道为什么,直接给我报一个运行错误,得了0分。但是我在Dev里,VS里面都跑的好好的,奇奇怪怪。如果有大佬路过,请帮小弟看看QWQ。本题学到的:交集set_intersection、并集…...

谷歌论文提前揭示o1模型原理:AI大模型竞争或转向硬件
Open AI最强模型o1的护城河已经没有了?仅在OpenAI发布最新推理模型o1几日之后,海外社交平台 Reddit 上有网友发帖称谷歌Deepmind在 8 月发表的一篇论文内容与o1模型原理几乎一致,OpenAI的护城河不复存在。 谷歌DeepMind团队于今年8月6日发布…...

【ShuQiHere】 探索数据挖掘的世界:从概念到应用
🌐 【ShuQiHere】 数据挖掘(Data Mining, DM) 是一种从大型数据集中提取有用信息的技术,无论是在商业分析、金融预测,还是医学研究中,数据挖掘都扮演着至关重要的角色。本文将带您深入了解数据挖掘的核心概…...

LabVIEW提高开发效率技巧----使用事件结构优化用户界面响应
事件结构(Event Structure) 是 LabVIEW 中用于处理用户界面事件的强大工具。通过事件驱动的编程方式,程序可以在用户操作时动态执行特定代码,而不是通过轮询(Polling)的方式不断检查界面控件状态。这种方式…...

【前端】ES6:Set与Map
文章目录 1 Set结构1.1 初识Set1.2 实例的属性和方法1.3 遍历1.4 复杂数据结构去重 2 Map结构2.1 初识Map2.2 实例的属性和方法2.3 遍历 1 Set结构 它类似于数组,但成员的值都是唯一的,没有重复的值。 1.1 初识Set let s1 new Set([1, 2, 3, 2, 3]) …...

Java 之网络编程小案例
1. 多发多收 描述: 编写一个简单的聊天程序,客户端可以向服务器发送多条消息,服务器可以接收所有消息并回复。 代码示例: 服务器端 (Server.java): import java.io.*; import java.net.*; import java.util.concurrent.Execut…...

Spring Boot:现代化Java应用开发的艺术
目录 什么是Spring Boot? 为什么选择Spring Boot? Spring Boot的核心概念 详细步骤:创建一个Spring Boot应用 步骤1:使用Spring Initializr创建项目 步骤2:解压并导入项目 步骤3:构建和配置项目 po…...

Redis五种基本数据结构的使用
Redis具有五种基本数据类型:String(字符串)、Hash(哈希)、List(列表)、Set(集合)、SortedSet(有序集合),下面示意它们的使用。 String类数据类型的使用 增:添加数据(set)、添加多个数据(mset)、添加数据时指定过期时间(setex) 删…...

【QT】系统-下
欢迎来到Cefler的博客😁 🕌博客主页:折纸花满衣 🏠个人专栏:QT 目录 👉🏻QTheadrun() 👉🏻QMutex👉🏻QWaitCondition👉🏻Q…...

java和kotlin 可以同时运行吗
Java 和 Kotlin 可以同时运行在同一个项目中,这主要得益于 Kotlin 对 Java 的互操作性。Kotlin 被设计为与 Java 100% 兼容,这意味着 Kotlin 代码可以很容易地调用 Java 代码,反之亦然。这种设计使得 Kotlin 能够无缝集成到现有的 Java 项目中…...

2024最新版 Tuxera NTFS for Mac 2023绿色版图文安装教程
在数字化时代,数据的存储和传输变得至关重要。Mac用户经常需要在Windows NTFS格式的移动硬盘上进行读写操作,然而,由于MacOS系统默认不支持NTFS的写操作,这就需要我们寻找一款高效的读写软件。Tuxera NTFS for Mac 2023便是其中…...

npm发布插件超级简单版
在开源的世界里,每个人都有机会成为贡献者,甚至是创新的引领者。您是否有过这样的想法:开发一个解决特定问题的小工具,让他成为其他开发者手中的利器?今天,我们就来一场实战训练,学习如何将你的…...

C# 访问Access存取图片
图片存入ole字段,看有的代码是获取图片的字节数组转换为base64字符串,存入数据库;显示图片是把base64字符串转换为字节数组再显示;直接存字节数组可能还好一点; 插入的时候用带参数的sql写法比较好;用拼接…...

正则表达式中常见字符的用法介绍
正则表达式(Regular Expression,简称Regex)是一种文本模式描述的方法,包括普通字符(如a到z之间的字母)和特殊字符(称为“元字符”)。正则表达式使用单个字符串来描述、匹配一系列符合…...

Vue3.0组合式API:依赖注入provide和inject实现跨层组件的通信
Vue3.0组合式API系列文章: 《Vue3.0组合式API:setup()函数》 《Vue3.0组合式API:使用reactive()、ref()创建响应式代理对象》 《Vue3.0组合式API:computed计算属性、watch监听器、watchEffect高级监听器》 《Vue3.0组合式API&…...

VSCode中配置C/C++环境
在Visual Studio Code(VSCode)中配置C/C环境是一个相对直接且功能强大的过程,它能让开发者利用VSCode的诸多便利功能来编写、编译和调试C/C代码。以下是一个详细的步骤指南,涵盖了从安装必要的软件到配置编译器、调试器以及VSCode…...

vue实现鼠标滚轮控制页面横向滑动
先看效果 20240919_095531 1.首先创建一个xScroll.vue组件 <template><div class"main" v-size-ob"mainSize"><div class"v-scroll"><div class"content"><slot></slot></div></div>…...

【Git使用】删除Github仓库中的指定文件/文件夹
前言: 上篇文章带大家上传了第一个项目至github,那要是想删除仓库中的指定文件夹怎么办?在Github中 仓库是无法通过鼠标操作直接删除文件和文件夹的,那只能通过 git 命令来执行删除操作。接下来就带大家进行操作。 详细步骤: 一…...

Iptables命令常用命令
前言:下是一些非常实用的 iptables 命令合集,涵盖网络攻击防护和日常网络安全防护 1. 查看当前规则 iptables -L -v -n查看现有的所有规则,-v 显示详细信息,-n 禁止解析IP地址和端口以加快显示速度。 2. 清空所有规则 iptables -F清除所有已…...

前端开发之原型模式
介绍 原型模式本质就是借用一个已有的实例做原型,在这原型基础上快速复制出一个和原型一样的一个对象。 class CloneDemo {name clone democlone(): CloneDemo {return new CloneDemo()} } 原型原型链 函数(class)都有显示原型 prototyp…...

分布式缓存服务Redis版解析与配置方式
一、Redis分布式缓存服务概述 Redis是一款高性能的键值对(Key-Value)存储系统,通常用作分布式缓存服务。它基于内存运行,支持丰富的数据类型,并具备高并发、低延迟的特点,非常适合用于缓存需要频繁访问的数…...

WordPress建站钩子函数及使用
目录 前言: 使用场景: 一、常用的wordpress钩子(动作钩子、过滤器钩子) 1、动作钩子(Action Hooks) 2、过滤器钩子(Filter Hooks) 二、常用钩子示例 1、添加自定义 CSS 和 JS…...

Qt 模型视图(二):模型类QAbstractItemModel
文章目录 Qt 模型视图(二):模型类QAbstractItemModel1.基本概念1.1.模型的基本结构1.2.模型索引1.3.行号和列号1.4.父项1.5.项的角色1.6.总结 Qt 模型视图(二):模型类QAbstractItemModel 模型/视图结构是一种将数据存储和界面展示分离的编程方法。模…...

算法打卡 Day41(动态规划)-理论基础 + 斐波那契数 + 爬楼梯 + 使用最小花费爬楼梯
文章目录 理论基础Leetcode 509-斐波那契数题目描述解题思路 Leetcode 70-爬楼梯题目描述解题思路 Leetcode 746-用最小花费爬楼梯题目描述解题思路 理论基础 动态规划,简称 DP,其中的每一个状态一定是由上一个状态推导出来的,而贪心算法没有…...

鸿蒙环境服务端签名直传文件到OSS
本文介绍如何在鸿蒙环境下将文件上传到OSS。 背景信息 鸿蒙环境是当下比较流行的操作环境,与服务端签名直传的原理类似,鸿蒙环境上传文件到OSS是利用OSS提供的PutObject接口来实现文件上传到OSS。关于PutObject的详细介绍,请参见PutObject。…...

计算机毕业设计Python+Flask微博情感分析 微博舆情预测 微博爬虫 微博大数据 舆情分析系统 大数据毕业设计 NLP文本分类 机器学习 深度学习 AI
首先安装需要的python库, 安装完之后利用navicat导入数据库文件bili100.sql到mysql中, 再在pycharm编译器中连接mysql数据库,并在设置文件中将密码修改成你的数据库密码。最后运行app.py,打开链接,即可运行。 B站爬虫数…...

solidwork剪裁实体
之前是这样: 效果如下:...

Junit与Spring Test简单使用
Junit与Spring Test简单使用 Junit5简介Junit5 注解Junit5与Spring结合 差异概览MockingMockBeanSpyBeanDemo 注意事项 又要写测试代码了,总结记录一下。 Junit5简介 与单一模块设计的Junit4不同,Junit5引入了模块化架构,由三个主要子项目组成: JUnit Pl…...