canvas力导布局

news2024/9/27 5:52:24

老规矩,先上效果图

<html>

<head>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        canvas {
            display: block;
            width: 100%;
            height: 100%;
            background: #000;
        }
    </style>
</head>

<body>
    <canvas id="network"></canvas>
</body>
<script>
    class TaskQueue {
        constructor() {
            this.taskList = []
            this.hasTaskDone = false
            this.status = 'do' // do or stop

            this.requestAnimationFrame = null
            this.requestAnimationFrameDrawBind = this.requestAnimationFrameDraw.bind(this)
        }
        addTask(func) {
            this.taskList.push(func)
            if (this.requestAnimationFrame === null) {
                this.addRequestAnimationFrame()
                this.do()
            }
        }
        do() {
            this.status = 'do'
            new Promise(res => {
                this.taskList[0] && this.taskList[0]()
                this.taskList.shift()
                this.hasTaskDone = true
                res()
            }).then(() => {
                if (this.status === 'do' && this.taskList.length) {
                    this.do()
                }
            })
        }
        stop() {
            this.status = 'stop'
        }
        requestAnimationFrameDraw() {
            this.stop()
            if (this.hasTaskDone && this.reDraw) {
                this.hasTaskDone = false
                this.reDraw()
            }
            if (this.taskList.length) {
                this.addRequestAnimationFrame()
                this.do()
            } else {
                this.clearRequestAnimationFrame()
            }
        }
        addRequestAnimationFrame() {
            this.requestAnimationFrame = window.requestAnimationFrame(this.requestAnimationFrameDrawBind)
        }
        clearRequestAnimationFrame() {
            window.cancelAnimationFrame(this.requestAnimationFrame)
            this.requestAnimationFrame = null
        }
        removeEvent() {
            this.stop()
            this.clearRequestAnimationFrame()
        }
    }

    class Layout extends TaskQueue {
        constructor(opt) {
            super(opt)

            this.qIndex = opt.layout.qIndex
            this.fStableL = opt.layout.fStableL
            this.fIndex = opt.layout.fIndex
            this.count = opt.layout.count || opt.nodes.length * Math.ceil(opt.nodes.length / 5)
            this.countForce = 0
        }
        doLayout() {
            this.countForce++
            if (this.countForce >= this.count) {
                return
            }

            // 计算开始
            this.forceComputed(this.arc, this.line)
            setTimeout(() => {
                this.addTask(() => {
                    this.doLayout();
                })
            })
        }
        forceComputed(nodes) {
            nodes.forEach(item => {
                item.translateX = 0
                item.translateY = 0
            })
            nodes.forEach((curNode, index) => {
                // 库仑力计算
                for (let i = index + 1; i < nodes.length; i++) {
                    let otherNode = nodes[i]
                    if (otherNode) {
                        this.computedXYByQ(curNode, otherNode)
                    }
                }
                // 弹簧力计算
                if (curNode.fromArcs?.length) {
                    curNode.fromArcs.forEach(id => {
                        let fromNode = nodes.filter(node => {
                            return node.id === id
                        })[0]
                        if (fromNode) {
                            this.computedXYByK(curNode, fromNode)
                        }
                    })
                }
                // 中心拉力
                if (curNode.fromArcs?.length) {
                    this.computedXYByK(curNode, {
                        xy: {
                            x: this.canvas.width / 2,
                            y: this.canvas.height / 2
                        }
                    })
                }
            })

            // let maxTranslate = 1
            // nodes.forEach(item => {
            //     if(item.translateX && Math.abs(item.translateX) > maxTranslate){
            //         maxTranslate = Math.abs(item.translateX)
            //     }
            //     if(item.translateY && Math.abs(item.translateY) > maxTranslate){
            //         maxTranslate = Math.abs(item.translateY)
            //     }
            // })
            // nodes.forEach(item => {
            //     if(item.translateX){
            //         item.x += item.translateX / maxTranslate
            //     }
            //     if(item.translateY){
            //         item.y += item.translateY / maxTranslate
            //     }
            // })
            nodes.forEach(item => {
                if (item.translateX) {
                    item.xy.x += item.translateX
                }
                if (item.translateY) {
                    item.xy.y += item.translateY
                }
            })
        }
        computedXYByQ(node1, node2) {
            let x1 = node1.xy.x
            let y1 = node1.xy.y
            let x2 = node2.xy.x
            let y2 = node2.xy.y
            let xl = x2 - x1
            let yl = y2 - y1
            let angle = Math.PI
            if (!xl) {
                if (y2 > y1) {
                    angle = -Math.PI / 2
                } else {
                    angle = Math.PI / 2
                }
            } else if (!yl) {
                if (x2 > x1) {
                    angle = 0
                } else {
                    angle = Math.PI
                }
            } else {
                angle = Math.atan(yl / xl)
            }
            let r = Math.sqrt(Math.pow(xl, 2) + Math.pow(yl, 2))
            if (r < 1) {
                r = 1
            }
            // 库仑力 r越大,库仑力越小
            let node1Q = (node1.fromNodes?.length || 0) + (node1.toNodes?.length || 0) + 1
            let node2Q = (node2.fromNodes?.length || 0) + (node2.toNodes?.length || 0) + 1
            let f = this.qIndex * node1Q * node2Q / Math.pow(r, 2)
            let fx = f * Math.cos(angle)
            let fy = f * Math.sin(angle)

            node1.translateX = node1.translateX
            node1.translateY = node1.translateY
            node2.translateX = node2.translateX
            node2.translateY = node2.translateY

            // node1.translateX -= fx
            // node2.translateX += fx
            // node1.translateY -= fy
            // node2.translateY += fy
            if (x2 > x1) {
                if (fx > 0) {
                    node1.translateX -= fx
                    node2.translateX += fx
                } else {
                    node1.translateX += fx
                    node2.translateX -= fx
                }
            } else {
                if (fx > 0) {
                    node1.translateX += fx
                    node2.translateX -= fx
                } else {
                    node1.translateX -= fx
                    node2.translateX += fx
                }
            }
            if (y2 > y1) {
                if (fy > 0) {
                    node1.translateY -= fy
                    node2.translateY += fy
                } else {
                    node1.translateY += fy
                    node2.translateY -= fy
                }
            } else {
                if (fy > 0) {
                    node1.translateY += fy
                    node2.translateY -= fy
                } else {
                    node1.translateY -= fy
                    node2.translateY += fy
                }
            }
        }
        computedXYByK(node1, node2) {
            let x1 = node1.xy.x
            let y1 = node1.xy.y
            let x2 = node2.xy.x
            let y2 = node2.xy.y
            let xl = x2 - x1
            let yl = y2 - y1
            let angle = Math.PI
            if (!xl) {
                if (y2 > y1) {
                    angle = -Math.PI / 2
                } else {
                    angle = Math.PI / 2
                }
            } else if (!yl) {
                if (x2 > x1) {
                    angle = 0
                } else {
                    angle = Math.PI
                }
            } else {
                angle = Math.atan(yl / xl)
            }
            let r = Math.sqrt(Math.pow(xl, 2) + Math.pow(yl, 2))
            if (r > this.fStableL * 2) {
                r = this.fStableL * 2
            } else if (r < 1) {
                r = 1
            }
            // 弹簧力
            let f = this.fIndex * (r - this.fStableL)
            let fx = f * Math.cos(angle)
            let fy = f * Math.sin(angle)

            node1.translateX = node1.translateX
            node1.translateY = node1.translateY
            node2.translateX = node2.translateX
            node2.translateY = node2.translateY

            if (f > 0) {
                // 拉力
                if (x2 > x1) {
                    if (fx > 0) {
                        node1.translateX += fx
                        node2.translateX -= fx
                    } else {
                        node1.translateX -= fx
                        node2.translateX += fx
                    }
                } else {
                    if (fx > 0) {
                        node1.translateX -= fx
                        node2.translateX += fx
                    } else {
                        node1.translateX += fx
                        node2.translateX -= fx
                    }
                }
                if (y2 > y1) {
                    if (fy > 0) {
                        node1.translateY += fy
                        node2.translateY -= fy
                    } else {
                        node1.translateY -= fy
                        node2.translateY += fy
                    }
                } else {
                    if (fy > 0) {
                        node1.translateY -= fy
                        node2.translateY += fy
                    } else {
                        node1.translateY += fy
                        node2.translateY -= fy
                    }
                }
            } else {
                // 弹力
                if (x2 > x1) {
                    if (fx > 0) {
                        node1.translateX -= fx
                        node2.translateX += fx
                    } else {
                        node1.translateX += fx
                        node2.translateX -= fx
                    }
                } else {
                    if (fx > 0) {
                        node1.translateX += fx
                        node2.translateX -= fx
                    } else {
                        node1.translateX -= fx
                        node2.translateX += fx
                    }
                }
                if (y2 > y1) {
                    if (fy > 0) {
                        node1.translateY -= fy
                        node2.translateY += fy
                    } else {
                        node1.translateY += fy
                        node2.translateY -= fy
                    }
                } else {
                    if (fy > 0) {
                        node1.translateY += fy
                        node2.translateY -= fy
                    } else {
                        node1.translateY -= fy
                        node2.translateY += fy
                    }
                }
            }

        }
    }

    class View extends Layout {
        constructor(opt) {
            super(opt)
            this.canvas = opt.canvas
            this.dpr = window.devicePixelRatio || 1

            this.nodes = opt.nodes
            this.paths = opt.paths

            this.circleStyle = opt.circleStyle
            this.lineStyle = opt.lineStyle

            this.line = []
            this.arc = []

            this.init()
        }
        init() {
            if (!this.canvas) {
                return
            }

            if (this.canvas.width !== Math.floor(this.canvas.offsetWidth * this.dpr) || this.canvas.height !== Math.floor(this.canvas.offsetHeight * this.dpr)) {
                this.canvas.width = Math.floor(this.canvas.offsetWidth * this.dpr)
                this.canvas.height = Math.floor(this.canvas.offsetHeight * this.dpr)
            }
            this.ctx = this.canvas.getContext('2d')

            this.addData(this.nodes, this.paths)
        }
        addData(nodes, paths) {
            if (nodes && nodes.length) {
                this.addArc(nodes)
            }
            if (paths && paths.length) {
                this.addLine(paths)
            }

            super.countForce = 0
            super.doLayout()
        }
        addArc(nodes) {
            // 数据多时可以考虑将初始化随机坐标范围与数据量做等比函数
            nodes.forEach(node => {
                this.arc.push({
                    id: node.id,
                    fromArcs: [],
                    toArcs: [],
                    xy: {
                        x: this.rand(0, this.canvas.width),
                        y: this.rand(0, this.canvas.height)
                    }
                })
            })
        }
        addLine(paths) {
            paths.forEach(path => {
                let fromArc = this.arc.filter(node => {
                    return node.id === path.from
                })[0]
                let toArc = this.arc.filter(node => {
                    return node.id === path.to
                })[0]
                fromArc.toArcs.push(toArc.id)
                toArc.fromArcs.push(fromArc.id)
                if (fromArc && toArc) {
                    this.line.push({
                        id: path.id,
                        from: path.from,
                        to: path.to,
                        fromArc,
                        toArc
                    })
                }
            })
        }
        reDraw() {
            this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
            this.draw()
        }
        draw() {
            this.line.forEach(item => {
                this.drawLine(item)
            })
            this.arc.forEach(item => {
                this.drawArc(item)
            })
        }
        drawLine(data) {
            this.ctx.save()
            this.ctx.translate(this.canvas.width / 2, this.canvas.height / 2)
            this.ctx.scale(this.scaleC, this.scaleC)
            this.ctx.translate(-this.canvas.width / 2, -this.canvas.height / 2)

            this.ctx.beginPath()
            this.ctx.lineWidth = this.lineStyle.width
            this.ctx.strokeStyle = this.lineStyle.color
            this.ctx.moveTo(data.fromArc.xy.x, data.fromArc.xy.y)
            this.ctx.lineTo(data.toArc.xy.x, data.toArc.xy.y)
            this.ctx.stroke()
            this.ctx.closePath()
            this.ctx.restore()
        }
        drawArc(data) {
            this.ctx.save()
            this.ctx.translate(this.canvas.width / 2, this.canvas.height / 2)
            this.ctx.scale(this.scaleC, this.scaleC)
            this.ctx.translate(-this.canvas.width / 2, -this.canvas.height / 2)

            this.ctx.beginPath()
            this.ctx.fillStyle = this.circleStyle.background
            this.ctx.arc(data.xy.x, data.xy.y, this.circleStyle.r, 0, 2 * Math.PI)
            this.ctx.fill()
            this.ctx.closePath()

            this.ctx.restore()
        }
        rand = (n, m) => {
            var c = m - n + 1
            return Math.floor(Math.random() * c + n)
        }
    }

    // 测试数据
    let data = {
        "nodes": [
            {
                "id": "36"
            },
            {
                "id": "50"
            },
            {
                "id": "20077"
            },
            {
                "id": "1090"
            },
            {
                "id": "1078"
            },
            {
                "id": "10007"
            },
            {
                "id": "20039"
            },
            {
                "id": "1074"
            },
            {
                "id": "20058"
            },
            {
                "id": "1062"
            },
            {
                "id": "10001"
            },
            {
                "id": "20076"
            },
            {
                "id": "1089"
            },
            {
                "id": "20038"
            },
            {
                "id": "1068"
            },
            {
                "id": "20057"
            },
            {
                "id": "1081"
            },
            {
                "id": "20070"
            },
            {
                "id": "1034"
            },
            {
                "id": "1077"
            },
            {
                "id": "10002"
            },
            {
                "id": "10003"
            },
            {
                "id": "20069"
            },
            {
                "id": "1002"
            },
            {
                "id": "47"
            },
            {
                "id": "10010"
            },
            {
                "id": "14"
            },
            {
                "id": "42"
            },
            {
                "id": "94"
            },
            {
                "id": "16"
            },
            {
                "id": "41"
            },
            {
                "id": "64"
            },
            {
                "id": "20002"
            },
            {
                "id": "73"
            },
            {
                "id": "1001"
            },
            {
                "id": "10009"
            },
            {
                "id": "10008"
            },
            {
                "id": "10006"
            },
            {
                "id": "10005"
            },
            {
                "id": "10004"
            },
            {
                "id": "33"
            },
            {
                "id": "10"
            },
            {
                "id": "18"
            },
            {
                "id": "70"
            },
            {
                "id": "98"
            },
            {
                "id": "20"
            },
            {
                "id": "24"
            },
            {
                "id": "20001"
            }
        ],
        "paths": [
            {
                "id": "606",
                "from": "50",
                "to": "36"
            },
            {
                "id": "346",
                "from": "20077",
                "to": "1090"
            },
            {
                "id": "343",
                "from": "1078",
                "to": "10007"
            },
            {
                "id": "382",
                "from": "20039",
                "to": "1074"
            },
            {
                "id": "419",
                "from": "20058",
                "to": "1062"
            },
            {
                "id": "344",
                "from": "1078",
                "to": "10001"
            },
            {
                "id": "356",
                "from": "20076",
                "to": "1089"
            },
            {
                "id": "439",
                "from": "20038",
                "to": "1068"
            },
            {
                "id": "417",
                "from": "20057",
                "to": "1081"
            },
            {
                "id": "358",
                "from": "20070",
                "to": "1078"
            },
            {
                "id": "438",
                "from": "20038",
                "to": "1034"
            },
            {
                "id": "248",
                "from": "1077",
                "to": "10002"
            },
            {
                "id": "249",
                "from": "1077",
                "to": "10003"
            },
            {
                "id": "364",
                "from": "20069",
                "to": "1077"
            },
            {
                "id": "4797",
                "from": "1002",
                "to": "10003"
            },
            {
                "id": "4787",
                "from": "1002",
                "to": "10002"
            },
            {
                "id": "223",
                "from": "1002",
                "to": "10003"
            },
            {
                "id": "222",
                "from": "1002",
                "to": "10002"
            },
            {
                "id": "2659",
                "from": "1002",
                "to": "47"
            },
            {
                "id": "4777",
                "from": "1002",
                "to": "10001"
            },
            {
                "id": "4867",
                "from": "1002",
                "to": "10010"
            },
            {
                "id": "1466",
                "from": "14",
                "to": "1002"
            },
            {
                "id": "1437",
                "from": "42",
                "to": "1002"
            },
            {
                "id": "1414",
                "from": "94",
                "to": "1002"
            },
            {
                "id": "1411",
                "from": "16",
                "to": "1002"
            },
            {
                "id": "1395",
                "from": "16",
                "to": "1002"
            },
            {
                "id": "1382",
                "from": "41",
                "to": "1002"
            },
            {
                "id": "1377",
                "from": "64",
                "to": "1002"
            },
            {
                "id": "436",
                "from": "20002",
                "to": "1002"
            },
            {
                "id": "2658",
                "from": "73",
                "to": "1002"
            },
            {
                "id": "4856",
                "from": "1001",
                "to": "10009"
            },
            {
                "id": "4846",
                "from": "1001",
                "to": "10008"
            },
            {
                "id": "4836",
                "from": "1001",
                "to": "10007"
            },
            {
                "id": "4826",
                "from": "1001",
                "to": "10006"
            },
            {
                "id": "4816",
                "from": "1001",
                "to": "10005"
            },
            {
                "id": "4806",
                "from": "1001",
                "to": "10004"
            },
            {
                "id": "4796",
                "from": "1001",
                "to": "10003"
            },
            {
                "id": "4786",
                "from": "1001",
                "to": "10002"
            },
            {
                "id": "4776",
                "from": "1001",
                "to": "10001"
            },
            {
                "id": "221",
                "from": "1001",
                "to": "10001"
            },
            {
                "id": "4866",
                "from": "1001",
                "to": "10010"
            },
            {
                "id": "1469",
                "from": "33",
                "to": "1001"
            },
            {
                "id": "1459",
                "from": "10",
                "to": "1001"
            },
            {
                "id": "1448",
                "from": "18",
                "to": "1001"
            },
            {
                "id": "1406",
                "from": "70",
                "to": "1001"
            },
            {
                "id": "1396",
                "from": "47",
                "to": "1001"
            },
            {
                "id": "1369",
                "from": "98",
                "to": "1001"
            },
            {
                "id": "1365",
                "from": "20",
                "to": "1001"
            },
            {
                "id": "1363",
                "from": "24",
                "to": "1001"
            },
            {
                "id": "406",
                "from": "20001",
                "to": "1001"
            }
        ]
    }
    // canvas dom
    const canvas = document.getElementById('network');

    new View({
        canvas,
        nodes: data.nodes,
        paths: data.paths,
        circleStyle: {
            r: 10,
            background: '#FFFFFF'
        },
        lineStyle: {
            width: 1,
            color: '#FFFFFF'
        },
        layout: {
            qIndex: 2000, // 库仑力系数,值越大,库仑力越大
            fStableL: 80,
            fIndex: 0.1, // 拉力系数,数值越大,力越大
        }
    })
</script>

</html>

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

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

相关文章

1600*C. k-Tree(DP)

Problem - 431C - Codeforces 解析&#xff1a; #include<bits/stdc.h> using namespace std; #define int long long const int mod1e97,N110; int n,k,d,dp[N][2]; signed main(){scanf("%lld%lld%lld",&n,&k,&d);dp[0][0]1;for(int i1;i<n;…

Elasticsearch基础篇(四):Elasticsearch的基础介绍与索引设置

Elasticsearch的基础介绍与索引设置 一、Elasticsearch概述Elasticsearch简介什么是全文检索引擎Elasticsearch 应用案例 二、索引和文档的概念1. 索引&#xff08;Index&#xff09;2. 文档&#xff08;Document&#xff09; 三、倒排索引&#xff08;Inverted Index&#xff…

2.3 为何使用Pthreads

轻量 和进程相比&#xff0c;系统在创建和管理线程时的开销要小的多&#xff0c;这里通过比较调用fork()创建进程和pthread_create()创建线程时的耗时开销来说明。下表中的耗时为执行了50000次创建操作对应的耗时&#xff0c;单位为秒。 注意&#xff1a;由于是在具有多核的对称…

Pro有Pro的样,但适合是最好的!iPhone 15与15 Pro应该买哪一款

你正在考虑升级到最近发布的iPhone 15系列,但你不确定你应该选择iPhone 15还是iPhone 15 Pro。以下是两款手机的功能以及高级Pro升级功能。 从性能和摄像头功能到设计和定价,我们正在挖掘每一个差异,以便你能够根据自己的需求和预算选择最佳手机。 iPhone 15与iPhone 15 P…

el-form简单封装一个列表页中的搜索栏

父组件如何使用 代码中注释很多, 应该很容易理解 <template><div><wgySearchv-model"searchDefault":fields"searchFields"reset"reset"submit"submit"><!-- 通过 slot 自定义的组件 传啥都行 --><te…

段码屏学习

文章目录 1.液晶屏和OLED屏2.液晶屏原理3.码段屏原理4.单色点阵屏原理5.彩色点阵屏原理6.HT1621驱动LCD段码屏 1.液晶屏和OLED屏 答&#xff1a; 液晶屏&#xff1a;码段屏、单色点阵屏、彩色点阵屏。 OLED屏&#xff1a;消费类电子产品多&#xff0c;贵。 2.液晶屏原理 …

三相智能电表逆相序的原因及解决方法

随着电力系统的快速发展&#xff0c;智能电表已逐渐替代传统电表&#xff0c;成为我国电力系统的重要组成部分。在众多类型的智能电表中&#xff0c;三相智能电表以其高精度、稳定性和智能化程度&#xff0c;被广泛应用于工商业及居民用电领域。然而&#xff0c;在使用过程中&a…

许战海战略文库|主品牌老化:企业增长面临的关键挑战

在今天&#xff0c;大部分行业的竞争环境已经从匀速变化迭代为加速变化&#xff0c;主品牌老化成为企业增 长面临的重要挑战&#xff0c;这一点已经变得非常明显。技术革新、产业革命以及顾客需求的演变势不 可挡&#xff0c;跨周期竞争已经成为常态。在这种情况下&#xff0c;…

传统但是很简单的计算Renko大小方法,FPmarkets1分钟分享

Renko图表是一种经典的技术分析工具&#xff0c;其计算方法较为传统。交易者通常需要手动设置以点数表示的常量值来确定Renko砖块的大小。 今天FPmarkets1分钟分享&#xff0c;传统但是很简单的计算Renko大小方法&#xff0c;不用指标&#xff0c;就可以使用Excel电子表格来计…

北京怎么开股票账户?哪家证券公司股票开户佣金最低?

北京怎么开股票账户&#xff1f;哪家证券公司股票开户佣金最低&#xff1f; 开设股票账户可以去证券营业部或者线上找客户经理进行开户具体步骤如下&#xff1a; 准备好本人有效身份证明证件&#xff08;如居民身份证、护照等&#xff09;及银行卡。 填写开户申请表&#xff…

亚马逊,速卖通,敦煌产品测评补单攻略:低成本、高安全实操指南

随着电商平台的发展和消费者对产品质量的要求提升&#xff0c;测评补单成为了商家们提升销售和用户口碑的关键环节。然而&#xff0c;如何在保持成本低廉的同时确保操作安全&#xff0c;一直是卖家们面临的挑战。今天林哥分享一些实用的技巧和策略&#xff0c;帮助卖家们产品的…

docker 安装 neo4j

1. 安装所需的软件包 yum install -y yum-utils device-mapper-persistent-data lvm2 2. 设置阿里云仓库(国内仓库稳定) yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo3. 查看docker容器版本 yum list docker-ce --showdupl…

小白看得懂的 Transformer (图解)

来源&#xff1a;Python数据科学 来源&#xff1a;Python数据科学本文约7200字&#xff0c;建议阅读14分钟在本文中&#xff0c;我们将研究Transformer模型&#xff0c;理解它的工作原理。1.导语 谷歌推出的BERT模型在11项NLP任务中夺得SOTA结果&#xff0c;引爆了整个NLP界。…

低代码自动翻页采集山姆商品数据

1 前言 山姆超市以会员经营为主&#xff0c;会员需要向商家购买会员卡才可以获得购物权&#xff0c;享受更多的优惠和折扣&#xff0c;这种模式实际上是通过高质量的商品和服务吸引顾客忠诚度&#xff0c;建立"忠诚顾客"的经营模式。山姆超市的商品销售以大批次和整箱…

401-视频与网络应用篇-网络分层和常见网络协议

常使用的网络有广域网&#xff08;WAN&#xff09;、城域网、局域网&#xff08;LAN&#xff09;&#xff0c;一般我们遇到的场景是广域网和局域网&#xff0c;广域网就是常说的外网&#xff0c;而局域网一般用于学校、公司等场合。在家庭路由器中对应WAN口和LAN口。网络是极为…

学生宿舍智能电表改造解决方案

随着科技的发展和人们对环保意识的提高&#xff0c;节能减排已经成为当今社会的重要议题。学生宿舍作为学生生活、学习的重要场所&#xff0c;其能源消耗问题日益受到关注。为了提高学生宿舍的能源利用效率&#xff0c;降低能源消耗&#xff0c;智能电表改造成为了一种有效的解…

3、字符设备驱动框架和开发步骤

一、Linux内核对文件的分类 Linux的文件种类 1、-&#xff1a;普通文件2、d&#xff1a;目录文件3、p&#xff1a;管道文件4、s&#xff1a;本地socket文件5、l&#xff1a;链接文件6、c&#xff1a;字符设备7、b&#xff1a;块设备 Linux内核按驱动程序实现模型框架的不同&…

深图SONTU医用X射线高压发生器维修SONTU-HFG50

X射线高压发生器的高压开不起来常见故障分析&#xff1a; 这是X射线荧光光谱仪较常见的故障&#xff0c;一般发生在开机时&#xff0c;偶尔也发生在仪器运行中。故障的产生原因可以从三个方面去分析&#xff1a;1、X射线防护系统;2、内部水冷系统;3、高压发生器及X射线光管。 …

离散傅里叶变换(DFT)的推导及C语言实现

1、傅里叶变换&#xff08;FT&#xff09; 傅里叶变换&#xff08;连续时间傅里叶变换&#xff09;是该部分内容的理论基础&#xff0c;回顾一下&#xff1a; 傅里叶变换&#xff1a; 傅里叶逆变换&#xff1a; 以上是连续时间傅里叶变换&#xff0c;但计算机只能处理离散的数…

practical on mifare

抽象的。 mifare Classic 是市场上使用最广泛的非接触式智能卡。 其设计和实施细节由制造商保密。 本文研究了该卡的体系结构以及卡与读卡器之间的通信协议。 然后&#xff0c;它提供了一种实用的、低成本的攻击&#xff0c;可以从卡的内存中恢复秘密信息。 由于伪随机生成器的…