vue2 Canvas 多边形区域绘制组件封装

news2024/11/30 8:36:22

效果预览:

CanvasBox组件

<!-- 区域设置canvas -->
<template>
    <div class="all" ref="divideBox">
        <!-- <div>
                <button @click="test">清空</button>
            </div> -->
        <img id="img" v-if="imgUrl" :src="imgUrl">
        <!-- width="700" height="450" -->
        <canvas id="mycanvas" ref="mycanvas" :width="canvasWidth" :height="canvasHeight" @mousedown="canvasDown($event)"
            @mousemove="canvasMove($event)" @mouseup="canvasUp($event)" @dblclick="doubleclick()">浏览器不支持canvas</canvas>
    </div>
</template>

<script>
export default {
    props: {
        // canvas宽度
        canvasWidth: {
            type: Number,
            default: 0
        },
        // canvas高度
        canvasHeight: {
            type: Number,
            default: 0
        },
        // 时间戳
        timeStamp: {
            type: Number,
            default: 0
        },
        // 图片
        imgUrl: {
            type: String,
            default: ""
        },
        // 是否可编辑 detail 不可编辑
        type: {
            type: String,
            default: ""
        },
        // 多边形区域
        aiDataRegionalInfoList: {
            type: Array,
            default: []
        },
        // 摄像头id
        // cameraId: {
        //     default: null
        // }
    },
    watch: {
        // 清空画布
        timeStamp() {
            this.test();
        },
        // 接收到多边形区域数据
        aiDataRegionalInfoList(val) {
            // console.log("接收到多边形区域数据", val);
            let newArray = []
            if (val && val.length > 0) {
                val.forEach(item => {
                    newArray.push({
                        "cor_x": item.x,
                        "cor_y": item.y
                    })
                })
            }
            if (newArray && newArray.length === 0) return;
            this.drawPolygon(newArray)
            // this.draw(val); 
            // this.drawPolygon([
            //     {
            //         "cor_x": 443,
            //         "cor_y": 223
            //     },
            //     {
            //         "cor_x": 672,
            //         "cor_y": 197
            //     },
            //     {
            //         "cor_x": 562,
            //         "cor_y": 368
            //     }
            // ])
        }
    },
    data() {
        return {
            isMultiple: false, // 是否支持多个多边形绘制
            observer: null,
            x: null,
            y: null,
            isdraw: false, //是否在画图形
            ctx: null, //canvas对象
            coordinates: [], //一个多边形的坐标信息 
            cor_index: 0, //当前多边形的索引
            endtip: false, //是否结束一个多边形的绘制
            all_coordinates: [], //所有多边形的信息
            isdrag: false, //是否正在拖动
            drag_index: [-1, -1], //当前拖动的多边形坐标
        }
    },
    mounted() {
        // 监听画布尺寸变化
        // this.initObserver();
        setTimeout(() => {
            //初始化画布对象
            this.initDraw()
        }, 500)

    },
    // beforeDestroy() {
    //     // 销毁监听器
    //     this.cleanupObserver();
    // },
    methods: {
        // 初始化监听器
        // initObserver() {
        //     this.observer = new MutationObserver(mutations => {
        //         mutations.forEach(mutation => {
        //             if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
        //                 this.handleResize();
        //             }
        //         });
        //     });
        //     this.observer.observe(this.$refs.divideBox, { attributes: true });
        //     this.handleResize(); // 初始化时也调用一次
        // },
        // 销毁监听器
        // cleanupObserver() {
        //     if (this.observer) {
        //         this.observer.disconnect();
        //     }
        // },
        // 监听到尺寸变化
        // handleResize() {
        //     const divideBox = this.$refs.divideBox;
        //     const canvas = this.$refs.myCanvas;
        //     if (divideBox && canvas) {
        //         const newWidth = divideBox.clientWidth;
        //         const newHeight = divideBox.clientHeight;
        //         // console.log('Divide box width:', newWidth);
        //         // console.log('Divide box height:', newHeight);
        //         // 更新 canvas 的尺寸
        //         canvas.width = newWidth;
        //         canvas.height = newHeight;
        //         // 进行其他初始化操作
        //     } else {
        //         console.error('未找到分割框或画布元素');
        //     }
        // },
        // 监听到尺寸变化
        // updateBoxWidth(width) {
        //     let widthVal = width
        //     let heightVal = width / 1920 * 1080
        //     // console.log("width", widthVal)
        //     // console.log("height", heightVal) 
        //     let pointList = JSON.parse(JSON.stringify(this.oldPointList))
        //     pointList.forEach(item => {
        //         item.x = item.x / 1920 * widthVal
        //         item.y = item.y / 1080 * heightVal
        //         item.type = item.type
        //         item.isShow = item.isShow
        //     })
        //     this.pointList = pointList
        //     // console.log("更新位置", this.pointList); 
        // },
        // updateCanvasSize() {
        //     const canvas = this.$refs.mycanvas;
        //     this.canvasWidth = canvas.clientWidth;
        //     this.canvasHeight = canvas.clientHeight;
        // },
        // 清空画布
        test() {
            this.all_coordinates = [];
            this.coordinates = [];
            this.isdraw = false;
            this.endtip = false;
            // this.ctx.clearRect(0, 0, 700, 450);
            this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
        },
        // 填充区域
        fillarea() {
            this.ctx.fillStyle = 'rgba(255, 255, 0,0.4)';
            for (let i = 0; i < this.all_coordinates.length; i++) {
                let cors = this.all_coordinates[i];
                let x0 = cors[0].cor_x;
                let y0 = cors[0].cor_y;
                this.ctx.beginPath();
                this.ctx.moveTo(x0, y0);
                for (let j = 1; j < cors.length; j++) {
                    let x = cors[j].cor_x;
                    let y = cors[j].cor_y;
                    this.ctx.lineTo(x, y);
                }
                this.ctx.fill();
                this.ctx.closePath();
            }
        },
        //初始化画布对象
        initDraw() {
            const canvas = document.querySelector("#mycanvas");
            this.ctx = canvas.getContext("2d");
            // this.ctx.strokeStyle = 'rgb(255, 255, 0)';
            this.ctx.strokeStyle = 'yellow';
        },
        // 判断是否是拖拽点
        isdragpoint(x, y) {
            if (this.all_coordinates.length == 0) {
                return false;
            }
            for (let i = 0; i < this.all_coordinates.length; i++) {
                for (let j = 0; j < this.all_coordinates[i].length; j++) {
                    let px = this.all_coordinates[i][j].cor_x;
                    let py = this.all_coordinates[i][j].cor_y;
                    if (Math.abs(x - px) <= 5 && Math.abs(y - py) <= 5) {
                        this.drag_index[0] = i;
                        this.drag_index[1] = j;
                        return true;
                    }
                }
            }
            return false;
        },
        // 画布中鼠标按下
        canvasDown(e) {
            if (this.type === 'detail') return;
            // console.log(123, e.offsetX, e.offsetY);
            // const cameraId = this.cameraId
            // if (cameraId == "" || cameraId == undefined || cameraId == null) {
            //     this.$message({
            //         message: '请先选择摄像头',
            //         type: 'warning'
            //     });
            //     return;
            // }
            // console.log("鼠标按下", this.coordinates);
            // console.log("鼠标按下", this.all_coordinates);
            let x = e.offsetX;
            let y = e.offsetY;
            if (this.isdragpoint(x, y)) {
                this.isdrag = true;
                return 0;
            }
            //画布中鼠标按下
            if (this.endtip) {//已经结束了上个多边形的绘制,把上个多边形的坐标放入数组,同时清空单个多边形数组信息
                this.endtip = false;
            }
            if (this.all_coordinates && this.all_coordinates.length == 1) {
                this.$message({
                    message: '最多只能绘制一个区域',
                    type: 'warning'
                });
                this.coordinates = []
                return;
            }
            //获取鼠标按下的坐标,放入数组中
            this.coordinates.push({ cor_x: x, cor_y: y });
            this.isdraw = true; //正在画多边形
        },
        // 画布中鼠标移动
        drawlines() {
            //把所有多边形画出来
            for (let i = 0; i < this.all_coordinates.length; i++) {
                let cors = this.all_coordinates[i];
                //前后坐标连线
                for (let j = 0; j < cors.length - 1; j++) {
                    this.ctx.beginPath();
                    let x0 = cors[j].cor_x;
                    let y0 = cors[j].cor_y;
                    let x1 = cors[j + 1].cor_x;
                    let y1 = cors[j + 1].cor_y;
                    this.ctx.moveTo(x0, y0);
                    this.ctx.lineTo(x1, y1);
                    this.ctx.stroke();
                    this.ctx.closePath();
                }
                //最后一个与第一个连线
                let begin_x = cors[0].cor_x;
                let begin_y = cors[0].cor_y;
                let end_x = cors[cors.length - 1].cor_x;
                let end_y = cors[cors.length - 1].cor_y;
                this.ctx.beginPath();
                this.ctx.moveTo(begin_x, begin_y);
                this.ctx.lineTo(end_x, end_y);
                this.ctx.stroke();
                this.ctx.closePath();
            }
        },
        //把当前绘制的多边形之前的坐标线段绘制出来
        drawline() {
            for (let i = 0; i < this.coordinates.length - 1; i++) {
                this.ctx.beginPath();
                let x0 = this.coordinates[i].cor_x;
                let y0 = this.coordinates[i].cor_y;
                let x1 = this.coordinates[i + 1].cor_x;
                let y1 = this.coordinates[i + 1].cor_y;
                this.ctx.moveTo(x0, y0);
                this.ctx.lineTo(x1, y1);
                this.ctx.stroke();
                this.ctx.closePath();
            }
        },
        // 针对的是单个多边形的所有顶点
        drawcircle() {
            //为当前的多边形端点画圆
            this.ctx.fillStyle = 'rgb(255, 255, 0)';
            for (let i = 0; i < this.coordinates.length; i++) {
                let x = this.coordinates[i].cor_x;
                let y = this.coordinates[i].cor_y;
                this.ctx.beginPath();
                this.ctx.moveTo(x, y);
                this.ctx.arc(x, y, 5, 0, Math.PI * 2);
                this.ctx.fill();
                this.ctx.closePath();
            }
        },
        // 用来在画布上标示出每个多边形顶点的位置,并且为这些顶点画出小圆圈
        drawcircles() {
            //为所有的多边形端点画圆
            this.ctx.fillStyle = 'rgb(255, 255, 0)';
            for (let i = 0; i < this.all_coordinates.length; i++) {
                let cors = this.all_coordinates[i];
                for (let j = 0; j < cors.length; j++) {
                    let x = cors[j].cor_x;
                    let y = cors[j].cor_y;
                    this.ctx.beginPath();
                    this.ctx.moveTo(x, y);
                    this.ctx.arc(x, y, 5, 0, Math.PI * 2);
                    this.ctx.fill();
                    this.ctx.closePath();
                }
            }
        },
        // 画布中鼠标抬起
        canvasUp(e) {
            if (this.isdrag) {
                this.isdrag = false;
                // 打印所有多边形的顶点坐标
                this.all_coordinates.forEach((polygon, index) => {
                    // console.log(`多边形 ${index + 1} 的顶点坐标:`);
                    polygon.forEach((vertex, vertexIndex) => {
                        // console.log(`  顶点 ${vertexIndex + 1}: (${vertex.cor_x}, ${vertex.cor_y})`);
                    });
                });
                // console.log("拖拽点后抬起", this.all_coordinates);
                this.$emit("all_coordinates", this.all_coordinates[0]);
            }
            this.drag_index = [-1, -1];
            // this.drag_index = [e.layerX, e.layerY];
            // console.log("鼠标抬起", e);
        },
        // 画布中点击后线条鼠标移动中
        canvasMove(e) {
            //画布中鼠标移动
            //没开始画或者结束画之后不进行操作
            let x = e.offsetX;
            let y = e.offsetY;
            if (this.isdrag) {
                this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
                // this.ctx.clearRect(0, 0, 700, 450);
                this.all_coordinates[this.drag_index[0]][this.drag_index[1]].cor_x = x;
                this.all_coordinates[this.drag_index[0]][this.drag_index[1]].cor_y = y;
                this.drawlines();
                this.drawcircles();
                this.fillarea();
            }
            if (this.coordinates.length == 0 || !this.isdraw || this.endtip) {
                return 0;
            }
            //获取上一个点
            let last_x = this.coordinates[this.coordinates.length - 1].cor_x;
            let last_y = this.coordinates[this.coordinates.length - 1].cor_y;
            // this.ctx.clearRect(0, 0, 700, 450); //清空画布
            this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
            this.drawline();//把之前的点连线
            this.drawcircle();
            // 如果不止一个多边形,把多边形们画出来
            if (this.all_coordinates.length != 0) {
                this.drawlines();
                this.drawcircles();
                this.fillarea();
            }
            //获取鼠标移动时的点,画线,实现线段跟踪效果。
            this.ctx.beginPath();
            this.ctx.moveTo(last_x, last_y);
            this.ctx.lineTo(x, y);
            this.ctx.strokeStyle = 'yellow';
            this.ctx.stroke();
            this.ctx.closePath();

        },
        // 双击画布结束连线
        doubleclick() {
            if (this.type === 'detail') return;
            //双击画布,在最后一个点的时候双击,自动连线第一个点,同时宣告画结束
            let x0 = this.coordinates[0].cor_x;
            let y0 = this.coordinates[0].cor_y;
            let x1 = this.coordinates[this.coordinates.length - 1].cor_x;
            let y1 = this.coordinates[this.coordinates.length - 1].cor_y;
            this.ctx.beginPath();
            this.ctx.moveTo(x0, y0);
            this.ctx.lineTo(x1, y1);
            this.ctx.stroke();
            this.ctx.closePath();
            this.isdraw = false;
            this.endtip = true
            this.drawcircle();
            this.coordinates.pop();
            this.all_coordinates.push(this.coordinates);
            this.ctx.fillStyle = 'rgba(255, 255, 0, 0.4)';
            let bx = this.coordinates[0].cor_x;
            let by = this.coordinates[0].cor_y;
            this.ctx.beginPath();
            this.ctx.moveTo(bx, by);
            for (let k = 1; k < this.coordinates.length; k++) {
                let x = this.coordinates[k].cor_x;
                let y = this.coordinates[k].cor_y;
                this.ctx.lineTo(x, y)
            }
            this.ctx.fill();
            this.ctx.closePath();
            // console.log("绘制完毕获得数据", this.coordinates)
            // console.log("绘制完毕获得全部数据", this.all_coordinates)
            this.$emit("all_coordinates", this.all_coordinates[0]);
            // console.log(666, this.all_coordinates[0]);
            this.coordinates = [];
        },
        // 接收多边形数据并绘制
        // receivePolygonData(polygonData) {
        //     if (Array.isArray(polygonData)) {
        //         // 清空画布
        //         this.test();
        //         // 绘制每个多边形
        //         polygonData.forEach(cors => {
        //             console.log(111, cors); 
        //             this.drawPolygon(cors);
        //         });
        //     }
        // },
        // 在画布中绘制多边形并添加可拖拽的顶点
        drawPolygon(coordinates) {
            // 清空画布
            this.test();
            if (coordinates.length >= 2) {
                this.ctx.beginPath();
                let x0 = coordinates[0].cor_x;
                let y0 = coordinates[0].cor_y;
                this.ctx.moveTo(x0, y0);
                // 绘制多边形的边
                for (let j = 1; j < coordinates.length; j++) {
                    let x = coordinates[j].cor_x;
                    let y = coordinates[j].cor_y;
                    this.ctx.lineTo(x, y);
                }
                // 最后一个点回到第一个点闭合多边形
                this.ctx.lineTo(x0, y0);
                this.ctx.closePath();
                this.ctx.stroke();
                // 填充多边形
                this.ctx.fillStyle = 'rgba(255, 255, 0, 0.4)';
                this.ctx.fill();
                // 绘制多边形顶点的小圆圈
                if (this.type != "detail") {
                    this.ctx.fillStyle = 'rgb(255, 255, 0)';
                    for (let j = 0; j < coordinates.length; j++) {
                        let x = coordinates[j].cor_x;
                        let y = coordinates[j].cor_y;
                        this.ctx.beginPath();
                        this.ctx.arc(x, y, 5, 0, Math.PI * 2);
                        this.ctx.fill();
                        this.ctx.closePath();
                    }
                    // 打印所有顶点的坐标
                    // console.log('绘制完成的多边形顶点坐标:', coordinates);
                    this.$emit("all_coordinates", coordinates);
                }
                let newArray = []
                newArray.push(coordinates)
                this.all_coordinates = newArray
                // console.log(666, this.all_coordinates, newArray);
            }
        }
    },
};
</script>

<style lang="scss" scoped>
.all {
    position: relative;
    width: 100%;
    height: 100%;
    // border: 2px solid red;
    border: 1px solid yellow;
}

#mycanvas {
    // border: 1px solid red;
    // width: 100%;
    // height: 100%;
    // width: 700px;
    // height: 45px;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    // border: 2px solid red;
}

#img {
    width: 100%;
    height: 100%;
    user-select: none;
}
</style>
<CanvasBox v-if="canvasIsShow" :imgUrl="imgUrl" :aiDataRegionalInfoList="aiDataRegionalInfoList"
                :canvasWidth="canvasWidth" :canvasHeight="canvasHeight" :timeStamp="timeStamp"
                @all_coordinates="getCoordinates" :type="type" />
      // 默认隐藏canvas
      canvasIsShow: false,
      // 子组件背景图片
      imgUrl: "",
      // 子组件多边形区域
      aiDataRegionalInfoList: [],
      // 子组件canvas宽度
      canvasWidth: 0,
      // 子组件canvas高度
      canvasHeight: 0,
      timeStamp: 0,
      // 记录新增->add  修改->edit  查看->detail
      type: "",




    // 接收到绘制后多边形数据
    getCoordinates(val) {
      // console.log("接收到canvas区域数据", val);
      let newArray = []
      if (val && val.length > 0) {
        val.forEach(item => {
          newArray.push({
            x: this.autoPageSizeToDefault(item.cor_x, item.cor_y).x,
            y: this.autoPageSizeToDefault(item.cor_x, item.cor_y).y,
          })
        })
      }
      this.form.aiDataRegionalInfoList = newArray
    },


    // 清空画布
    clearCanvas() {
      this.timeStamp = Date.now();
      this.aiDataRegionalInfoList = []
      this.form.aiDataRegionalInfoList = []
    },

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

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

相关文章

FineReport 标题冻结,冻结表头,冻结行列

先进行重复标题行和重复标题列设置&#xff0c;然后再进行分页冻结设置 1、冻结列 SELECT * FROM S人员花名册选定列 – 右击 – 设置重复标题列 2、冻结行 选定行 – 右击 – 设置重复标题行 3、重复与冻结设置 模板 – 重复与冻结设置 冻结重复标题有分页冻结和填报…

Leecode刷题之路第20天之有效的括号

题目出处 20-有效的括号-题目出处 题目描述 给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 1.左括号必须用相同类型的右括号闭合…

GraphRAG:知识图谱+RAG技术

由于RAG的一些缺陷&#xff0c;最近工作中用到了GraphRAG&#xff0c;可以简单理解为知识图谱RAG工作&#xff0c;在进行QFS与深度推理上表现良好。老板希望&#xff0c;在类似于库存管理、预测上面&#xff0c;可以结合更多的上下文信息和逻辑关系&#xff0c;进行推理和结果的…

一文带你了解,2024年世界职业院校技能大赛该如何备赛

2024年世界职业院校技能大赛&#xff08;以下简称“大赛”&#xff09;即将拉开帷幕&#xff0c;这不仅是一次展示职业院校学生专业技能的舞台&#xff0c;更是促进国际职业教育交流与合作的重要契机。为了确保参赛队伍能在比赛中取得优异成绩&#xff0c;以下是一些具体建议&a…

【第2章 开始学习C++】函数

文章目录 导语使用有返回值的函数函数变体用户定义的函数用户定义的有返回值的函数 导语 函数用于创建 C 程序的模块&#xff0c; 对 C 的 OOP 定义至关重要。 C 函数分两种&#xff1a; 有返回值的和没有返回值的。 使用有返回值的函数 有返回值的函数将生成一个值&#x…

MySQL SELECT 查询(二):复杂查询的实现

MySQL SELECT 查询&#xff08;二&#xff09;&#xff1a;复杂查询的实现 文章目录 MySQL SELECT 查询&#xff08;二&#xff09;&#xff1a;复杂查询的实现1. 多表查询1.1 常见错误&#xff1a;笛卡尔积与属性归属1.2 连接条件与规范1.3 连接类型1.4 SQL99 连接特性 2. SQL…

C++红黑树(简单易懂)

C红黑树 红黑树红黑树的概念 红黑树节点的定义红黑树的插入颜色变化红黑树的插入拷贝构造红黑树的验证全部代码实现红黑树与AVL树的比较红黑树的应用 &#x1f30f;个人博客主页&#xff1a;个人主页 红黑树 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在…

Java并发 - 线程池

文章目录 总体设计常见线程池FixedThreadPoolCachedThreadPoolSingleThreadPoolThreadPoolExecutor 核心参数工作原理生产者消费者模型创建线程池提交任务任务提交方式任务提交流程executeaddWorker Worker队列线程运行 runWoker获取任务销毁工作线程线程池关闭shutdown/shutdo…

维修数据屏:重塑热力公司运维管理新格局

在热力公司的运维管理中&#xff0c;高效的报修和维修流程是确保系统稳定运行的关键。随着科技的发展&#xff0c;维修数据屏的出现为热力公司的运维工作带来了重大变革。 一、传统热力运维面临的挑战 过去&#xff0c;热力公司在报修和维修方面存在诸多问题&#xff0c;给运维…

基于Java的超市管理系统(源码+定制+解答)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

创建包含可导入浏览器信任的SSL自签名证书

问题&#xff1a;现在的三大浏览器&#xff0c;chrome、edge、firefox 一般都默认启用https检查&#xff0c;这就要求我们自建的局域网内的网址和其他诸如nextcloud、photoprism、tiddlywiki等应用也必须要有证书。解决方法是使用openssl自己生成一个。由此则会再衍生出一个问题…

哪款宠物空净运行吸毛好、噪音小?希喂、霍尼韦尔、安德迈测评!

作为宠物领域目前最火热的产品&#xff0c;宠物空气净化器的讨论度一直很高。身为铲屎官的我在产品刚出的时候就购入了一台&#xff0c;结果让我非常失望&#xff01; 抛开产品效果不提&#xff0c;它运行起来的声音实在太大了&#xff01;我家猫根本不愿意靠近&#xff0c;每…

定焦镜头可以改变焦距吗?

1、问题背景 焦距是镜头的一个固有光学特性&#xff0c;和镜头设计相关&#xff0c;所谓定焦镜头&#xff0c;焦距肯定是固定不变的。 但有个问题一直有点疑惑&#xff0c;焦距是镜头中心到焦点的距离&#xff0c;当我们拧动镜头调焦的过程&#xff0c;就是为了使得焦点成像在传…

信息安全保障人员认证(CISAW)全攻略

由中国网络安全审查认证和市场监管大数据中心耗时六年&#xff0c;汇聚业界专家、企业翘楚、高校及研究机构学者共同精心打磨而成的针对信息安全保障的不同专业技术方向、应用领域和保障岗位&#xff0c;依循国际标准 ISO/IEC 17024《人员认证机构通用要求》所构建的、多层次的…

LabVIEW提高开发效率技巧----减少UI更新频率

在LabVIEW开发中&#xff0c;图形化用户界面&#xff08;UI&#xff09;的更新频率对程序的响应速度有着显著影响。频繁的UI更新会占用大量资源&#xff0c;导致系统性能下降。本文将详细介绍如何通过减少UI更新频率来提升LabVIEW程序的运行效率&#xff0c;从多个角度进行分析…

TCP/UDP通信协议

TCP通讯时序 下图是一次TCP通讯的时序图。TCP连接建立断开。包含大家熟知的三次握手和四次挥手。 在这个例子中&#xff0c;首先客户端主动发起连接&#xff08;connet&#xff09;、发送请求&#xff0c;然后服务器端响应请求&#xff0c;然后客户端主动关闭连接。两条竖线表…

多功能校准仪怎么进行计量校准?

多功能校准仪计量校准是计量行业常会进行的一种校准&#xff0c;因为其多功能校准仪的普遍适用性&#xff0c;以及其计量校准技术也是在行业内比较通用&#xff0c;那么具体多功能校准仪计量校准怎么进行呢&#xff1f; 校准方法 一、在多功能校准仪的输出范围内&#xff0c;布…

观察者模式的思考

观察者模式由来 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为型设计模式&#xff0c;它的起源可以追溯到20世纪90年代初&#xff0c;由设计模式四人帮&#xff08;Erich Gamma, Richard Helm, Ralph Johnson 和 John Vlissides&#xff09;在其著作《设计模…

反走样算法(MSAA、TAA、FXAA、DLSS)

光栅化的采样过程会导致图形走样,走样有很多种形式: 锯齿 摩尔纹 走样的本质原因是采样速度跟不上信号变化的速度 采样频率低,使得我们将连续变化的信号离散化. 反走样方法 anti-alisaing MSAA 多重采样反走样 超采样 优点&#xff1a; 对几何反走样效果良好 缺点…

razor TagHelper 汇总、HtmlHelper 汇总

Tag Helper Tag Helpers 的范围由 addTagHelper 和 removeTagHelper 进行控制&#xff0c;并且 “!” 为退出字符。 addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers // 手动高亮 asp-for 》》 Label <label asp-for"userName"></label>》》生…