【JS】原生js实现矩形框的绘制/拖动/拉伸

news2025/1/18 8:24:05

1、要点及功能描述

通过js监听mouse事件来实现矩形框的绘制,再通过区分点击的是边角还是其他位置来实现矩形框的拉伸和拖动,并且在拖动和拉伸时,都做了边界限制,当拉伸或拖动 到边界时,就不能继续拉伸拖动了。当然在相关开发时,还是需要你对一些常规的offsetLeft,offsetX等的dom属性了解哟~

现在这种主要用来做canvas截图部分的矩形框展示,想要了解canvas截图的可以看我另外两篇博客,分别是pdf的截图绘制和图片的截图绘制。当然本篇博客主要侧重于对矩形框的实现喔~

【PDF】Canvas绘制PDF及截图 

canvas图像绘制(图像放大、缩小、拖动和截图)

2、效果图展示

3、原理讲解

3.1、变量详解

    const dom = document.getElementById('out-box')
    const rect  = document.getElementById('rect')
    const origin = dom.getBoundingClientRect()
    const parentBorder = Number(getComputedStyle(dom, null).borderWidth.split('px')[0]) // 父元素边框 如果你明确知道边框宽度,就不需要这行,直接赋值就行
    const childBorder = Number(getComputedStyle(rect, null).borderWidth.split('px')[0]) // 子元素边框 如果你明确知道边框宽度,就不需要这行,直接赋值就行

dom:外层盒子,鼠标下手开始绘制的地方

rect: 矩形框,其实矩形框并不是凭空绘制出来的,只是先将其宽高置为0,并且定位到负无限处,所以在页面上看不到,在绘制时,通过控制矩形框的定位及宽高来进行展示,这也是我进行绘制/拖动/拉伸的核心思想

    .rect{
      position: absolute;
      box-shadow: 0 0 0 1999px rgba(0, 0, 0, .4);
      left: -9999px;
      top: 0;
      width: 0;
      height: 0;
      border: 2px solid orange;
      cursor: move;
    }

origin: 其实就是外层盒子的相对于页面的属性,有用处

parentBorder和childBorder就是你外层盒子和矩形盒子的边框,其实可要可不要,但是主要为了好看(你可以直接赋值就行,这跟影响不大)

3.2、绘制方法讲解 

startMouse:这里left和top,就是在onmousedown开始下笔时,就确定了当前矩形框的定位,用本身下笔时的clientX,clientY去减去外层盒子的偏移,就能得到矩形在外层盒子的定位(类似于offsetLeft,offsetTop,但是这里不能用offsetLeft,offsetTop,不过你也可以自己去试试)

        const left = e.clientX - origin.x
        const top = e.clientY - origin.y
        rect.style.left = left + 'px'
        rect.style.top = top + 'px'

3.3、判断当前是拖动还是拉伸讲解

 mousedownHandle:当点击矩形框边角时,你肯定是想要拉伸矩形框,当点击其他位置时,你肯定想要拖动矩形框。

在矩形框内部点击,就可以使用offset相关属性,你所点击的位置,就是offsetX,offsetY,这俩属性是相对于当前dom内部的点击位置的,而offsetWidth,offsetHeight是当前dom的宽高,differenec是模糊距离,有时候你得设置一个点击的范围,只要点击点在那个范围内,就是拉伸,反之亦然。

      const startX = e.offsetX
      const startY = e.offsetY
      const width = e.target.offsetWidth
      const height = e.target.offsetHeight
      const difference = 10 // 点击四边角10 px范围为拉伸,其他为拖动,这个值可以根据你需要的来调整

 当然,最好的方式就是有八个拉伸点,除了这八个拉伸点,其余位置都是被拖拽的地方,下面方法就是判断是哪个拉伸点的(这个也蛮好理解,不信你打开你的截图软件,是不是有8个能被拉伸的小方块),除去这八个点以外,其他都是返回[-1, -1],以来标识拖动

      let left = 0 // 0 => left, 1 => middle, 2 => right, -1 => 点击的位置不能被拖动
      let top = 0 // 0 => top, 1 => middle, 2 => bottom, -1 => 点击的位置不能被拖动
      if (startX < difference && startX > 0) { // 点击的位置为矩形左侧0 ~ 6px
        left = 0
      } else if (startX > width / 2 - difference && startX < width / 2 + difference) { // 点击的位置为矩形中间 width/2 - 6px ~ width/2 + 6px
        left = 1
      } else if (startX < width && startX > width - difference){ // 点击的位置为矩形右侧 width - 6px ~ width
        left = 2
      } else {
        left = -1
      }

      if (startY < difference && startY > 0) { // 点击的位置为矩形上侧0 ~ 6px
        top = 0
      } else if (startY > height / 2 - difference && startY < height / 2 + difference) { // 点击的位置为矩形中间 height/2 - 6px ~ height/2 + 6px
        top = 1
      } else if (startY < height && startY > height - difference){ // 点击的位置为矩形下侧 height - 6px ~ height
        top = 2
      } else {
        top = -1
      }

3.4、实现拖动和拉伸的方法详解 

 拖动还是拉伸?

当mousedownHandle返回的是[-1, -1]时,那就说明是拖动,拖动的话,只需要改变矩形框的left,top定位即可。

        const flag = mousedownHandle(e)
        let left = e.clientX
        let top = e.clientY
        const width = rect.offsetWidth
        const height = rect.offsetHeight
        const [dragX, dragY] = flag
        // 拖动
        if (dragX === -1 && dragY === -1) {
          left -= rect.offsetLeft // 要保持之前矩形框的坐标值
          top -= rect.offsetTop
        }
        document.onmousemove = e => {
          // 取消浏览器因回流导致的默认事件及冒泡事件
          e.preventDefault()
          if (e.stopPropagation) {
            e.stopPropagation()
          } else {
            e.cancelable = true
          }
          if (dragX === -1 && dragY === -1) {
            const rightArea = dom.offsetWidth - rect.offsetWidth - (childBorder * 2) // 右边界
            const bottomArea = dom.offsetHeight - rect.offsetHeight - (childBorder * 2) // 下边界
            const leftArea = 0 // 左边界
            const topArea = 0 // 上边界
            const moveLeft = e.clientX - left > rightArea ? rightArea : (e.clientX - left< leftArea ? leftArea : e.clientX - left)
            const moveTop = e.clientY - top > bottomArea ? bottomArea : (e.clientY - top < topArea ? topArea : e.clientY - top)
            rect.style.left = moveLeft + 'px'
            rect.style.top = moveTop + 'px'
          }
        }

 当mousedownHandle返回的不是[-1, -1]时,例如[2, 2],那就说明是向右下角拉伸(目前实现了向右下角拉伸,其余拉伸童鞋们可以自己思考喔,同理可参考我的来写哟~)

    document.onmousemove = e => {
          // 取消浏览器因回流导致的默认事件及冒泡事件
          e.preventDefault()
          if (e.stopPropagation) {
            e.stopPropagation()
          } else {
            e.cancelable = true
          }
          if (dragX === 2 && dragY === 2) { // 右下角拉伸
            rect.style.width = (e.clientX - left + width > dom.offsetWidth - rect.offsetLeft - (parentBorder * 2 + childBorder * 2) ? dom.offsetWidth - rect.offsetLeft - (parentBorder * 2 + childBorder * 2) : e.clientX - left + width) + 'px'
            rect.style.height = (e.clientY- top + height > dom.offsetHeight - rect.offsetTop - (parentBorder * 2 + childBorder * 2) ? dom.offsetHeight - rect.offsetTop - (parentBorder * 2 + childBorder * 2) : e.clientY- top + height) + 'px'
          }
    }

4、源码展示

可直接运行展示

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>drawRectangle</title>
  <style>
    *{
      margin: 0;
      padding: 0;
    }
    .container{
      width: 1000px;
      height: 700px;
      margin: 10% auto;
    }
    .control{
      margin-bottom: 10px;
    }
    #out-box{
      width: 100%;
      height: 600px;
      border: 2px solid #000;
      position: relative;
      overflow: hidden;
    }
    .rect{
      position: absolute;
      box-shadow: 0 0 0 1999px rgba(0, 0, 0, .4);
      left: -9999px;
      top: 0;
      width: 0;
      height: 0;
      border: 2px solid orange;
      cursor: move;
    }
    .rect::after{
      content: '';
      position: absolute;
      right: -6px;
      bottom: -6px;
      width: 6px;
      height: 6px;
      border-radius: 50%;
      border: 2px solid orange;
      background-color: #fff;
      cursor: nwse-resize;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="control">
      <button id="clear">清屏</button>
      <button id="start-paint">开始绘制</button>
    </div>
    <div id="out-box">
      <div id="rect" class="rect"></div>
    </div>
  </div>
  
  <script>
    const dom = document.getElementById('out-box')
    const rect  = document.getElementById('rect')
    const origin = dom.getBoundingClientRect()
    const parentBorder = Number(getComputedStyle(dom, null).borderWidth.split('px')[0]) // 父元素边框 如果你明确知道边框宽度,就不需要这行,直接赋值就行
    const childBorder = Number(getComputedStyle(rect, null).borderWidth.split('px')[0]) // 子元素边框 如果你明确知道边框宽度,就不需要这行,直接赋值就行
    /**
     * 开始绘制
     */
    const startMouse = () => {
      dom.style.cursor = 'crosshair'
      dom.onmousedown = e => {
        if (e.target !== dom) return
        const left = e.clientX - origin.x
        const top = e.clientY - origin.y
        rect.style.left = left + 'px'
        rect.style.top = top + 'px'
        document.onmousemove = e => {
          // 取消浏览器因回流导致的默认事件及冒泡事件
          e.preventDefault()
          if (e.stopPropagation) {
            e.stopPropagation()
          } else {
            e.cancelable = true
          }
          // 宽高边界限制
          const widthArea = e.clientX - origin.x > dom.offsetWidth - (parentBorder * 2 + childBorder * 2) ? dom.offsetWidth - (parentBorder * 2 + childBorder * 2) : e.clientX - origin.x
          const heightArea = e.clientY - origin.y > dom.offsetHeight - (parentBorder * 2 + childBorder * 2) ? dom.offsetHeight - (parentBorder * 2 + childBorder * 2) : e.clientY - origin.y
          rect.style.width = widthArea - left + 'px'
          rect.style.height = heightArea - top + 'px'
        }
        document.onmouseup = e => {
          dom.onmousedown = null
          document.onmousemove = null
          document.onmouseup = null
          dom.style.cursor = ''
          editMouse()
        }
      }
    }
    const editMouse = () => {
      rect.onmousedown = e => {
        if (e.target !== rect) return
        const flag = mousedownHandle(e)
        let left = e.clientX
        let top = e.clientY
        const width = rect.offsetWidth
        const height = rect.offsetHeight
        const [dragX, dragY] = flag
        // 拖动
        if (dragX === -1 && dragY === -1) {
          left -= rect.offsetLeft // 要保持之前矩形框的坐标值
          top -= rect.offsetTop
        }
        document.onmousemove = e => {
          // 取消浏览器因回流导致的默认事件及冒泡事件
          e.preventDefault()
          if (e.stopPropagation) {
            e.stopPropagation()
          } else {
            e.cancelable = true
          }
          if (dragX === -1 && dragY === -1) {
            const rightArea = dom.offsetWidth - rect.offsetWidth - (childBorder * 2) // 右边界
            const bottomArea = dom.offsetHeight - rect.offsetHeight - (childBorder * 2) // 下边界
            const leftArea = 0 // 左边界
            const topArea = 0 // 上边界
            const moveLeft = e.clientX - left > rightArea ? rightArea : (e.clientX - left< leftArea ? leftArea : e.clientX - left)
            const moveTop = e.clientY - top > bottomArea ? bottomArea : (e.clientY - top < topArea ? topArea : e.clientY - top)
            rect.style.left = moveLeft + 'px'
            rect.style.top = moveTop + 'px'
          } else if (dragX === 2 && dragY === 2) { // 右下角拉伸
            rect.style.width = (e.clientX - left + width > dom.offsetWidth - rect.offsetLeft - (parentBorder * 2 + childBorder * 2) ? dom.offsetWidth - rect.offsetLeft - (parentBorder * 2 + childBorder * 2) : e.clientX - left + width) + 'px'
            rect.style.height = (e.clientY- top + height > dom.offsetHeight - rect.offsetTop - (parentBorder * 2 + childBorder * 2) ? dom.offsetHeight - rect.offsetTop - (parentBorder * 2 + childBorder * 2) : e.clientY- top + height) + 'px'
          }
        }
        document.onmouseup = e => {
          document.onmousemove = null
          document.onmouseup = null
        }
      }
    }
    /**
     * mousedown逻辑处理
     */
    const mousedownHandle = (e) => {
      const startX = e.offsetX
      const startY = e.offsetY
      const width = e.target.offsetWidth
      const height = e.target.offsetHeight
      const difference = 10 // 点击四边角10 px范围为拉伸,其他为拖动,这个值可以根据你需要的来调整
      let left = 0 // 0 => left, 1 => middle, 2 => right, -1 => 点击的位置不能被拖动
      let top = 0 // 0 => top, 1 => middle, 2 => bottom, -1 => 点击的位置不能被拖动
      if (startX < difference && startX > 0) { // 点击的位置为矩形左侧0 ~ 6px
        left = 0
      } else if (startX > width / 2 - difference && startX < width / 2 + difference) { // 点击的位置为矩形中间 width/2 - 6px ~ width/2 + 6px
        left = 1
      } else if (startX < width && startX > width - difference){ // 点击的位置为矩形右侧 width - 6px ~ width
        left = 2
      } else {
        left = -1
      }

      if (startY < difference && startY > 0) { // 点击的位置为矩形上侧0 ~ 6px
        top = 0
      } else if (startY > height / 2 - difference && startY < height / 2 + difference) { // 点击的位置为矩形中间 height/2 - 6px ~ height/2 + 6px
        top = 1
      } else if (startY < height && startY > height - difference){ // 点击的位置为矩形下侧 height - 6px ~ height
        top = 2
      } else {
        top = -1
      }
      if (left === -1 || top === -1 || (left === 1 && top === 1)) {
        return [-1, -1]
      }
      return [left, top] // 只会有八个位置能被准确返回,其余都是返回[-1, -1]
    }

    const clear = document.querySelector('#clear') // 清屏
    const startPaint = document.querySelector('#start-paint') // 开始绘制
    clear.onclick = e => {
      rect.style.left = '-9999px'
      rect.style.top = 0
      rect.style.width = 0
      rect.style.height = 0
    }
    startPaint.onclick = e => {
      startMouse()
    }
  </script>
</body>
</html>

5、问题答疑?

1、在onmousedown里为啥要加上 if (e.target !== dom) return 这行代码呢?

dom.onmousedown = e => {
        if (e.target !== dom) return
}

因为我在多次写的时候发现呀,很多时候矩形框的下面就会有类似截图软件下的涂鸦功能,当你点击涂鸦按钮时,其实这个时候你也是点击dom的(可理解为事件穿透),但是我们写逻辑的时候不想要涂鸦按钮和dom一起绑定住想区分开,所以这个时候判断onmousedown的对象和dom是否一致,不一致的话,就不执行后续操作。

2、在onmousemove里为啥要加 e.preventDefault() ... 这段代码呢?

    document.onmousemove = e => {
          e.preventDefault()
          if (e.stopPropagation) {
            e.stopPropagation()
          } else {
            e.cancelable = true
          }
    } 

注意哦,只在绑定对象为document才加这一段代码,其他的不加~

加上这段代码是因为在mousemove来回移动到当前矩形框时,会出现浏览器的黑色拒绝符号并会卡顿,导致操作不流畅,所以加上这段代码可以取消浏览器因回流导致的默认事件及冒泡事件

3、 矩形框周围的黑色半透明蒙层是如何实现的?

box-shadow: 0 0 0 1999px rgba(0, 0, 0, .4);

是通过这行样式实现的喔,其中1999px基本满足大部分屏幕的要求,当然也可以根据你的需求来设置哦,但是一定要切记,外层盒子要设置overflow,不然矩形框的阴影将会溢出去

overflow: hidden;

4、绘制矩形框时的边界范围限制?

其实可以看到,绘制时,矩形框的left和top都是已经确定好的,只是在mousemove时候改变宽高,但是宽高不能超过外层盒子的范围呀,所以就是在你mousemove时,将计算出来的宽高与父级offsetWidth,offsetHeight进行比较(记住为了更好看,我这里是将边框宽度也一起计算进来的喔,如果你不想计算的话,影响也不大~)(内部变量找不到的可以到上面源码里查看全部喔~)

          // 宽高边界限制
          const widthArea = e.clientX - origin.x > dom.offsetWidth - (parentBorder * 2 + childBorder * 2) ? dom.offsetWidth - (parentBorder * 2 + childBorder * 2) : e.clientX - origin.x
          const heightArea = e.clientY - origin.y > dom.offsetHeight - (parentBorder * 2 + childBorder * 2) ? dom.offsetHeight - (parentBorder * 2 + childBorder * 2) : e.clientY - origin.y
          rect.style.width = widthArea - left + 'px'
          rect.style.height = heightArea - top + 'px'

5、拖动矩形框时的边界范围限制?

这里给出了上下左右四个边界范围限制,当移动left,top超过这个范围时,都将给予处理,使矩形框不会超过外层盒子的边界范围(内部变量找不到的可以到上面源码里查看全部喔~)

            const rightArea = dom.offsetWidth - rect.offsetWidth - (childBorder * 2) // 右边界
            const bottomArea = dom.offsetHeight - rect.offsetHeight - (childBorder * 2) // 下边界
            const leftArea = 0 // 左边界
            const topArea = 0 // 上边界
            const moveLeft = e.clientX - left > rightArea ? rightArea : (e.clientX - left< leftArea ? leftArea : e.clientX - left)
            const moveTop = e.clientY - top > bottomArea ? bottomArea : (e.clientY - top < topArea ? topArea : e.clientY - top)
            rect.style.left = moveLeft + 'px'
            rect.style.top = moveTop + 'px'

6、拉伸矩形框时的边界范围限制?

拉伸的时候,其实矩形框的left,top,width和height都可能需要改变,不过具体要看你拉伸的是哪个边角,下面我代码里是拉伸的右下角,所以只需要改变矩形框宽高即可。当宽高的长度等于或超过外层盒子的offsetWidth,offsetHeight减去矩形框的offsetLeft,offsetTop时,就说明已经到范围边界了,这个长度不能再被增加了。(内部变量找不到的可以到上面源码里查看全部喔~)

            rect.style.width = (e.clientX - left + width > dom.offsetWidth - rect.offsetLeft - (parentBorder * 2 + childBorder * 2) ? dom.offsetWidth - rect.offsetLeft - (parentBorder * 2 + childBorder * 2) : e.clientX - left + width) + 'px'
            rect.style.height = (e.clientY- top + height > dom.offsetHeight - rect.offsetTop - (parentBorder * 2 + childBorder * 2) ? dom.offsetHeight - rect.offsetTop - (parentBorder * 2 + childBorder * 2) : e.clientY- top + height) + 'px'

---不了解的可以评论哟,林大大哟原创---

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

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

相关文章

7个实用有效的shopify运营策略,跨境电商卖家必知

关键词&#xff1a;shopify运营、跨境电商卖家 您的Shopify 在线商店是使用当今最好的平台之一构建的。2022 年第二季度&#xff0c;Shopify 在美国电子商务平台中占据最大市场份额&#xff0c;约占美国所有在线业务的 32%。 这也意味着电子商务品牌之间的竞争比以往任何时候都…

【图像融合】基于matlab DSIFT多聚焦图像融合【含Matlab源码 2224期】

⛄一、SIFT配准简介 1 算法概述 在实时系统中&#xff0c;算法的输入为相机数据流&#xff0c;当前输入的图像与上一张相似度很高时应不参与融合&#xff0c;由于在体视显微镜下序列图像存在较大程度的偏移&#xff0c;所以融合前还需要进行图像配准&#xff0c;配准完成后再进…

安杰思提交注册:预计2022年度收入不低于3.5亿元,同比增长15%

11月16日&#xff0c;杭州安杰思医学科技股份有限公司&#xff08;下称“安杰思”&#xff09;在上海证券交易所科创板提交招股书&#xff08;注册稿&#xff09;。据贝多财经了解&#xff0c;安杰思于2022年6月24日在科创板递交上市申请材料&#xff0c;2022年11月7日获得上市…

面试--线程池的执行流程和拒绝策略有哪些?

一. 执行流程 聊到线程池就一定会聊到线程池的执行流程, 也就是当有一个任务进入线程池之后, 线程池是如何执行的? 想要真正的了解线程池的执行流程&#xff0c;就得先从线程池的执行方法 execute() 说起, execute() 实现源码如下: public void execute(Runnable command)…

2.10.2版本的青龙升级2.10.13及2.11.3版本的教程

重要提醒&#xff1a; 这个教程仅限使用我下面这个命令搭建的青龙面板使用 docker run -dit \--name QL \--hostname QL \--restart always \-p 5700:5700 \-v $PWD/QL/config:/ql/config \-v $PWD/QL/log:/ql/log \-v $PWD/QL/db:/ql/db \-v $PWD/QL/scripts:/ql/scripts \-…

【消息队列笔记】chp3-如何确保消息不丢失

一、检测消息是否丢失 我们要保证消息的可靠交付&#xff0c;首先就要知道消息是否丢失了。如何做到这一点呢&#xff1f; 对于IT基础设施比较完善的公司&#xff0c;可以使用分布式链路追踪系统来追踪每一条消息。如果没有这样的系统&#xff0c;可以使用消息的有序性来验证…

圆角矩形不是圆:圆角的画法和二阶连续性

本文中的所有重要图片都会给出基于Matplotlib的Python绘制代码以供参考 引言 如果在百度搜索圆角矩形的画法&#xff0c;那么多数结果都会告诉你&#xff0c;就是把一个普通矩形的拐角换成相切的 14\frac{1}{4}41​ 圆弧&#xff0c;就像 引文1 和 引文2 说的那样。然而&#x…

网络规划设计与综合布线技术详解

一、网络工程概述 1、计算机网络及其组成 计算机网络是现代通信技术与计算机技术相结合的产物。 随着计算机网络本身的发展,人们认为:计算机网络是把地理位置不同、功能独立自治的计算机系统及数据设备通过通信设备和线路连接起来,在功能完善的网络软件运行支持下,以实现…

springboot+vue实现excel的导出

首先是springboot对数据的处理 依赖的导入 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency>RequestMapping("/exportExcel") public R exportR…

【SpringBoot项目】SpringBoot项目-瑞吉外卖【day01】

文章目录前言软件开发整体介绍软件开发流程瑞吉外卖项目介绍项目介绍产品原型展示技术选型功能架构角色开发环境搭建数据库环境搭建maven项目搭建设置静态资源映射后台登录需求分析代码开发功能测试后台退出需求分析代码开发功能测试&#x1f315;博客x主页&#xff1a;己不由心…

JVS低代码如何实现复杂物料编码?

日常业务过程中&#xff0c;存在大量的编码&#xff0c;例如订单的流水号&#xff0c;复杂的物料编码&#xff0c;学生证号等等场景&#xff0c;那么通过JVS如何去实现各种编码&#xff1f; 为了让使用者使用尽量简单&#xff0c;我们编码分为简单配置的编码和复杂配置的编码。…

[附源码]java毕业设计家校通信息管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

docker stats查询容器状态显示异常有模线

docker stats 命令用来显示容器使用的系统资源。 默认情况下&#xff0c;stats 命令会每隔 1 秒钟刷新一次输出的内容直到你按下 ctrl c。 输出详情介绍&#xff1a; CONTAINER ID 与 NAME: 容器 ID 与名称。 CPU % 与 MEM %: 容器使用的 CPU 和内存的百分比。 MEM USAGE…

Java基础之《netty(1)—netty介绍》

一、介绍 1、netty是由JBOSS提供的一个java开源框架&#xff0c;现为github上的独立项目。 2、netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;可以快速开发高性能、高可靠的网络IO程序。 3、netty主要针对在TCP协议下&#xff0c;面向clients端的高并发应用&…

【python3】4.文件管理

2022.11.16 本学习内容总结于莫烦python:4.文件管理 https://mofanpy.com/tutorials/python-basic/interactive-python/read-write-file4 文件管理 4.1 读写文件 均是用特殊字符open 4.1.1 创建文件 f open("new_file.txt", "w") # 创建并打开 f.wr…

进入数字化供应链高潮期,与IBM咨询共创无边界竞争力

供应链领域的国际专家马丁克里斯托弗在30年前就提出“未来的竞争不再是企业和企业之间的竞争&#xff0c;而是供应链之间的竞争。”近几年来&#xff0c;基于工业4.0技术的供应链4.0开始进入业界的视野&#xff0c;2020年开始的疫情让全球供应链结束了长期稳定状态而进入VUCA&a…

针对谷氨酰胺运输体的小分子抑制剂

精准癌症治疗手段 在运输体水平靶向谷氨酰胺代谢 ACST2 蛋白是谷氨酰胺进入癌细胞的主要转运蛋白。在肺癌、乳腺癌、结肠癌等癌症中&#xff0c;ACST2 蛋白水平的上调与患者存活率有关。当抑制 ACST2 基因表达时&#xff0c;会显著抑制癌细胞生长。ASCT2 水平升高与多种癌症的…

【支付】支付安全

这里写目录标题1. 加密 - 对称加密与非对称加密1.1 对称加密1.2 非对称加密1.3 对称加密与非对称加密区别2. 身份认证公钥加密&#xff0c;私钥解密&#xff08;加密信息&#xff09;私钥加密&#xff0c;公钥解密&#xff08;身份认证&#xff09;3. 摘要算法与数据完整性3.1 …

深度剖析 Vue3 在浏览器的运行原理

上一讲我们学习了 Vue 响应式的大致原理&#xff0c;响应式就是可以把普通的 JavaScript 对象包裹成响应式对象&#xff0c;这样&#xff0c;我们对对象做的修改&#xff0c;响应式都能够监听到&#xff0c;并且执行 effect 内部注册的函数来执行数据修改之后的效果 那今天我就…

公司建网站多少钱?【网站多少钱】

很多公司成立初期会选择建一个公司网站&#xff0c;那么首先就会考虑公司建网站多少钱的问题。公司建网站多少钱会受到建网站方式的影响&#xff0c;不同方式费用不同&#xff0c;那么下面就说说公司建网站多少钱。 1、公司有团队&#xff0c;自己建 公司有技术团队的情况&am…