当前位置: 首页 > news >正文

自定义复杂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题棋盘上的战舰

题目&#xff1a; 题解&#xff1a; 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 计算机软件能力认证考试系统 不知道为什么&#xff0c;直接给我报一个运行错误&#xff0c;得了0分。但是我在Dev里&#xff0c;VS里面都跑的好好的&#xff0c;奇奇怪怪。如果有大佬路过&#xff0c;请帮小弟看看QWQ。本题学到的&#xff1a;交集set_intersection、并集…...

谷歌论文提前揭示o1模型原理:AI大模型竞争或转向硬件

Open AI最强模型o1的护城河已经没有了&#xff1f;仅在OpenAI发布最新推理模型o1几日之后&#xff0c;海外社交平台 Reddit 上有网友发帖称谷歌Deepmind在 8 月发表的一篇论文内容与o1模型原理几乎一致&#xff0c;OpenAI的护城河不复存在。 谷歌DeepMind团队于今年8月6日发布…...

【ShuQiHere】 探索数据挖掘的世界:从概念到应用

&#x1f310; 【ShuQiHere】 数据挖掘&#xff08;Data Mining, DM&#xff09; 是一种从大型数据集中提取有用信息的技术&#xff0c;无论是在商业分析、金融预测&#xff0c;还是医学研究中&#xff0c;数据挖掘都扮演着至关重要的角色。本文将带您深入了解数据挖掘的核心概…...

LabVIEW提高开发效率技巧----使用事件结构优化用户界面响应

事件结构&#xff08;Event Structure&#xff09; 是 LabVIEW 中用于处理用户界面事件的强大工具。通过事件驱动的编程方式&#xff0c;程序可以在用户操作时动态执行特定代码&#xff0c;而不是通过轮询&#xff08;Polling&#xff09;的方式不断检查界面控件状态。这种方式…...

【前端】ES6:Set与Map

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

Java 之网络编程小案例

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

Spring Boot:现代化Java应用开发的艺术

目录 什么是Spring Boot&#xff1f; 为什么选择Spring Boot&#xff1f; Spring Boot的核心概念 详细步骤&#xff1a;创建一个Spring Boot应用 步骤1&#xff1a;使用Spring Initializr创建项目 步骤2&#xff1a;解压并导入项目 步骤3&#xff1a;构建和配置项目 po…...

Redis五种基本数据结构的使用

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

【QT】系统-下

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;QT 目录 &#x1f449;&#x1f3fb;QTheadrun() &#x1f449;&#x1f3fb;QMutex&#x1f449;&#x1f3fb;QWaitCondition&#x1f449;&#x1f3fb;Q…...

java和kotlin 可以同时运行吗

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

2024最新版 Tuxera NTFS for Mac 2023绿色版图文安装教程

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

npm发布插件超级简单版

在开源的世界里&#xff0c;每个人都有机会成为贡献者&#xff0c;甚至是创新的引领者。您是否有过这样的想法&#xff1a;开发一个解决特定问题的小工具&#xff0c;让他成为其他开发者手中的利器&#xff1f;今天&#xff0c;我们就来一场实战训练&#xff0c;学习如何将你的…...

C# 访问Access存取图片

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

正则表达式中常见字符的用法介绍

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

Vue3.0组合式API:依赖注入provide和inject实现跨层组件的通信

Vue3.0组合式API系列文章&#xff1a; 《Vue3.0组合式API&#xff1a;setup()函数》 《Vue3.0组合式API&#xff1a;使用reactive()、ref()创建响应式代理对象》 《Vue3.0组合式API&#xff1a;computed计算属性、watch监听器、watchEffect高级监听器》 《Vue3.0组合式API&…...

VSCode中配置C/C++环境

在Visual Studio Code&#xff08;VSCode&#xff09;中配置C/C环境是一个相对直接且功能强大的过程&#xff0c;它能让开发者利用VSCode的诸多便利功能来编写、编译和调试C/C代码。以下是一个详细的步骤指南&#xff0c;涵盖了从安装必要的软件到配置编译器、调试器以及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仓库中的指定文件/文件夹

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

Iptables命令常用命令

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

前端开发之原型模式

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

分布式缓存服务Redis版解析与配置方式

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

WordPress建站钩子函数及使用

目录 前言&#xff1a; 使用场景&#xff1a; 一、常用的wordpress钩子&#xff08;动作钩子、过滤器钩子&#xff09; 1、动作钩子&#xff08;Action Hooks&#xff09; 2、过滤器钩子&#xff08;Filter Hooks&#xff09; 二、常用钩子示例 1、添加自定义 CSS 和 JS…...

Qt 模型视图(二):模型类QAbstractItemModel

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

算法打卡 Day41(动态规划)-理论基础 + 斐波那契数 + 爬楼梯 + 使用最小花费爬楼梯

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

鸿蒙环境服务端签名直传文件到OSS

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

计算机毕业设计Python+Flask微博情感分析 微博舆情预测 微博爬虫 微博大数据 舆情分析系统 大数据毕业设计 NLP文本分类 机器学习 深度学习 AI

首先安装需要的python库&#xff0c; 安装完之后利用navicat导入数据库文件bili100.sql到mysql中&#xff0c; 再在pycharm编译器中连接mysql数据库&#xff0c;并在设置文件中将密码修改成你的数据库密码。最后运行app.py&#xff0c;打开链接&#xff0c;即可运行。 B站爬虫数…...

solidwork剪裁实体

之前是这样&#xff1a; 效果如下&#xff1a;...

Junit与Spring Test简单使用

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