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

React js原生 详解 HTML 拖放 API(鼠标拖放功能)

最近碰到了个需求,大概就是要通过可视化拖拽的方式配置一个冰柜,需要把预设好的冰柜内部架子模板一个个拖到冰箱内。一开始的想法是用鼠标事件(mousedown、mouseup等)那一套去实现,能实现但是过程过于复杂,需要控制的状态太多了。其实 Web Api 为 html 元素拖拽量身定制了一套 HTML 拖放API,用这个方法实现一些简单的拖拽功能简直不要太简单。为此写了这篇文章,下面将详细介绍 HTML 拖放 API 的核心知识点

文档

一、被拖拽元素和放置被拖拽元素的元素

通常我们所了解的拖放是按住鼠标左键不放然后移动鼠标把一个页面元素从某个位置移动到另一个位置,然后松开鼠标左键,至此完成了整个拖放过程。在这个过程中我们需要先重点关注两个东西,一个是被拖拽元素另一个是 放置被拖拽元素的元素

1.1 被拖拽元素

我们得先有个概念,页面上显示的元素默认并不都是可以被拖拽的(除了图片、被选中的文字、链接),所以如果当前元素默认不可被拖拽那么就得先把它设置为可拖拽的。ps:可拖拽元素被拖拽时会有一个半透明的快照跟着鼠标移动。

将 HTML 元素的 draggable 属性设置为 true, 元素就可以变为可拖拽元素。效果如下图。

<div id="box" draggable="true">draggable box</div>

在这里插入图片描述

1.2 可放置被拖拽元素的元素

所有的元素区域默认是不支持放置被拖拽元素的,直观的表现是,当被拖拽元素经过不可放置区域时鼠标的样式是一个禁止放置的一个图标(圆圈带一个斜杠),所以需要将目标元素设置为一个可放置区域

默认情况下是这样:

<div id="box" draggable="true">draggable box</div>
<div id="droppable">放置区域</div>

在这里插入图片描述
设置为放置区域需要给元素绑定一个事件 dragover 且要 阻止默认行为

<div id="box" draggable="true">draggable box</div>
<div id="droppable">放置区域</div>
<script>let dropDom = document.getElementById('droppable')dropDom.addEventListener('dragover', (e) => {e.preventDefault()})
</script>

React:
放置区域需要绑定onDragOver事件,且要 阻止默认行为 – 其他事件一样加on

<div draggable="true">draggable box</div>
<div onDragOver={(e) => {e.preventDefault()}}>放置区域</div>

设置为可放置区域后鼠标样式也变了不再是禁止图标,而是一个加号图标(图标可以设置,下面会讲解):
在这里插入图片描述
然而你会发现被拖放元素并没有真正的被放置到放置区域,这是必然的,放置操作需要开发者自行定义,以上的设置只是是为了向用户表明这个区域是允许放东西的,那么至于怎么放需要开发者自行决定。

二、拖拽过程触发的一些事件

这一小节将带你了解整个拖放过程的其他细节,比如拖拽过程中会触发哪些事件

2.1 被拖放目标触发的事件

给被拖放目标元素绑定三个事件 dragstart、drag、dragend。

<div id="box" draggable="true">draggable box</div>
<div id="droppable">放置区域</div>
<script>let dragDom = document.getElementById('box')dragDom.addEventListener('dragstart', (e) => {console.log('开始拖动');})dragDom.addEventListener('drag', (e) => {console.log('拖动中');})dragDom.addEventListener('dragend', (e) => {console.log('结束拖动');})
</script>

React

<div  draggable="true"onDragStart={(e) => {console.log("开始拖动", e);}}onDrag={(e) => {console.log("拖动中", e);}}onDragEnd={(e) => {console.log("结束拖动", e);}}
>
>draggable box</div>
<div onDragOver={(e) => {e.preventDefault()}}>放置区域</div>

开始拖动触发 dragstart ,拖动过程中(鼠标不松开)触发drag,松开鼠标(或者按下 Esc 键)触发 dragend
在这里插入图片描述

2.2 被拖拽元素在放置区域内会触发的事件

先给放置目标元素绑定四个事件

<div id="box" draggable="true">draggable box</div>
<div id="droppable">放置区域</div>
<script>let dropDom = document.getElementById('droppable')dropDom.addEventListener('dragenter', (e) => {console.log('进入到了放置区域~');})dropDom.addEventListener('dragover', (e) => {e.preventDefault()console.log('在放置区域内拖拽中~');})dropDom.addEventListener('dragleave', (e) => {console.log('离开了放置区域~');})dropDom.addEventListener('drop', (e) => {console.log('在放置区域内,放下了被拖拽元素~')})
</script>

拖拽元素进入放置区域内时触发 dragenter 事件,在放置区域内移动被拖放(鼠标不松开)元素触发 dragover 事件,被拖放元素离开放置区域触发 dragleave 事件,在放置区域内松开鼠标触发 drop 事件。
在这里插入图片描述

三、实现真正意义上的元素拖放

通过上面触发的事件我们可以知道,用户真正在放置区域释放鼠标的时候只有 drop 事件能够监听到。所以开发者需要在这个事件里做真正的放置操作,放置什么由开发者决定,可以是被拖拽元素,也可以是自定义的一些内容。

放置被拖拽元素:

<div id="box" draggable="true">draggable box</div>
<div id="droppable">放置区域</div>
<script>let dropDom = document.getElementById('droppable')dropDom.addEventListener('dragover', (e) => {e.preventDefault()console.log('在放置区域内拖拽中~');})dropDom.addEventListener('drop', (e) => {console.log('在放置区域内,放下了被拖拽元素~')e.target.appendChild(document.getElementById('box'))})
</script>

在这里插入图片描述
放置自定义内容

dropDom.addEventListener('drop', (e) => {console.log('在放置区域内,放下了被拖拽元素~')let customCOntent = '<p>自定义内容</p>'e.target.innerHTML = e.target.innerHTML + customCOntent
})

在这里插入图片描述

四、dataTransfer 对象

4.1 从被拖放元素向可放置元素传递数据

dataTransfer 对象提供了一个setData()方法,它接受两个参数,第一个参数是传递数据的类型(一般是标准的MIME类型),第二个数据是数据值。dataTransfer 还提供了 getData() 的方法用于获取传递的数据,它接受一个参数,参数值为 setData 对应的第一个参数。

传递一个简单的字符串数据

<div id="box" draggable="true">draggable box</div>
<div id="droppable">放置区域</div>
<script>let dropDom = document.getElementById('droppable')let dragDom = document.getElementById('box')dragDom.addEventListener('dragstart', (e) => {e.dataTransfer.setData('text/plain', '自定义数据')})dropDom.addEventListener('dragover', (e) => {e.preventDefault()})dropDom.addEventListener('drop', (e) => {let data = e.dataTransfer.getData('text/plain')console.log('你传递的数据为:', data);})
</script>

在这里插入图片描述
⚡注意:只能在 dragstart 事件中设置数据,在其他地方设置无效。且只能在 drop 事件中获取设置的数据,其他事件中获取不到。
案例:根据传递的数据放置不同的内容。

<div id="box" draggable="true">draggable box</div>
<div id="droppable">放置区域</div>
<script>let dropDom = document.getElementById('droppable')let dragDom = document.getElementById('box')dropDom.addEventListener('dragover', (e) => {e.preventDefault()})dropDom.addEventListener('drop', (e) => {let num = e.dataTransfer.getData('num')console.log(num);if(num > 5)e.target.innerHTML = e.target.innerHTML + '<p>传递的数字大于5</p>'else if(num == 5) e.target.innerHTML = e.target.innerHTML + '<p>传递的数字等于5</p>'elsee.target.innerHTML = e.target.innerHTML + '<p>传递的数字小于5</p>'})dragDom.addEventListener('dragstart', (e) => {let num = Math.floor(Math.random() * 10) + 1;e.dataTransfer.setData('num', num)})
</script>

在这里插入图片描述

4.2 自定义拖拽过程中跟随鼠标移动的内容

默认情况下元素被拖拽时会有一个半透明的元素快照跟随着鼠标移动。通过 dataTransfer 提供的 setDragImage(elemnt, xOffset, yOffset) 方法是可以自定义跟随内容。接受三个参数 elemnt 可以是 dom 节点或者一个图片对象,xOffset, yOffset 是相对于鼠标的偏移量。

语法

dataTransfer.setDragImage(img, xOffset, yOffset);

img | Element
用于拖曳反馈图像的图像 Element 元素。

如果 Element 是一个 img 元素,则将拖动位图设置为该元素的图像(保持大小);否则,将拖动数位图设置为从给定元素所生成的图片

xOffset
使用 long 指示相对于图片的横向偏移量

yOffset
使用 long 指示相对于图片的纵向偏移量

解析
  • 发生拖动时,从拖动目标 (dragstart事件触发的元素) 生成半透明图像,并在拖动过程中跟随鼠标指针。这个图片是自动创建的,你不需要自己去创建它。然而,如果想要设置为自定义图像,那么 DataTransfer.setDragImage() 方法就能派上用场。
  • 图像通常是一个 <image> 元素,但也可以是<canvas> 或任何其他图像元素。该方法的 x 和 y 坐标是图像应该相对于鼠标指针出现的偏移量。
    坐标指定鼠标指针相对于图片的偏移量。例如,要使图像居中,请使用图像宽度和高度的一半。通常在 dragstart 事件处理程序中调用此方法。
实际用例

setDragImage 的第一个参数接受的是一个Element参数,这样的话,普通的html元素image元素canvas都可以传递

1、设置为一个图片:

<script>import Tag from "../../style/imgs/attributeTag/路径.png"; //已经存在的图片let dragDom = document.getElementById('box')dragDom.addEventListener('dragstart', (e) => {let img = new Image()// 创建一个图像并且使用它作为拖动图像// 请注意: 改变 "example.gif" 为一个已经存在的图片// 或者,一个还没有创建出来的图片,那么浏览器将会使用默认的拖动图片// 译者注:默认的拖动图片与拖动对象没有联系。一般是一个小型文件图标// 例如:// mg.src = Tag //或// mg.src = `data:image/png;base64,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`;img.src = 'example.gif'e.dataTransfer.setDragImage(img, 10, 10)})
</script>

在这里插入图片描述
2、以官网例子为例,把canvas作为参数传递,我首先尝试的是这种方式,发现并不能生效。(官方的例子没有运行成功)

function dragWithCustomImage(event) {var canvas = document.createElementNS("http://www.w3.org/1999/xhtml","canvas");canvas.width = canvas.height = 50;var ctx = canvas.getContext("2d");ctx.lineWidth = 4;ctx.moveTo(0, 0);ctx.lineTo(50, 50);ctx.moveTo(0, 50);ctx.lineTo(50, 0);ctx.stroke();var dt = event.dataTransfer;dt.setData('text/plain', 'Data to Drag');dt.setDragImage(canvas, 25, 25);
}

3、根据案例,我接着使用·HtmlDivElement·作为参数传递,创建了·DIV元素·,此时也·没有生效·。

export function drawDragImage(dataTransfer: DataTransfer, context: string) {
const drawItem: API.EquipmentInfo = JSON.parse(context);
const div = document.createElement(‘div’);
div.style.height = itemObj.height + ‘px’;
div.style.width = itemObj.width + ‘px’;
div.style.border = ‘1px solid #000’;
const span = document.createElement(‘span’);
span.innerText = ‘2222’;
div.appendChild(span);
dataTransfer.setDragImage(div, drawItem.width / 2, drawItem.height / 2);
}

4、然后,我改进了canvas,把canvas转化为图片,第一次拖拽的时候,因为image加载元素是异步导致了没有生效,如图1;第二以后拖拽的时候可以生效,如图二

  const imageContent = canvas.toDataURL('image/jpeg', 1);const image = new Image();image.src = imageContent;image.onload = () => {console.log('image2 load');};dataTransfer.setDragImage(image, drawItem.width / 2, drawItem.height / 2);

在这里插入图片描述

5、最后我尝试了使用官网的方法,同样因为image加载图片是异步的,而拖拽事件是同步发生的,导致了第一次执行失败

function dragstart_handler(ev) {console.log("dragStart");// 设置拖动的格式和数据。使用事件目标的 id 作为数据ev.dataTransfer.setData("text/plain", ev.target.id);// 创建一个图像并且使用它作为拖动图像// 请注意:改变 "example.gif" 为一个已经存在的图片// 或者,一个还没有创建出来的图片,那么浏览器将会使用默认的拖动图片// 译者注:默认的拖动图片与拖动对象没有联系。一般是一个小型文件图标var img = new Image();img.src = 'example.gif';ev.dataTransfer.setDragImage(img, 10, 10);
}
解决方案

在尝试了不同方式设置拖拽反馈图像,总结了一些解决方案

  • 以html页面的元素为模版,动态生成内容,然后设置Element元素参数,可以设置DIV元素的z-index(使用z-index,必须使用position:relative | absolute)–(尝试使用过css1、position:absolute 定位出浏览器可视界面 2、 display:none无用),隐藏在实际页面之下:这样可以动态生成要拖拽的元素,并和生成的fabric的group保持一致。 完美的解决了问题 。
  • 在这里插入图片描述
    js
export function drawDragImage(dataTransfer: DataTransfer, context: string) {const drawItem: API.EquipmentInfo = JSON.parse(context);const dragElement = document.getElementById('dragItem');const idElement = dragElement?.getElementsByClassName('dragItemId')[0];const nameElement = dragElement?.getElementsByClassName('dragItemName')[0];if (idElement) {idElement.innerHTML = drawItem.id;}if (nameElement) {nameElement.innerHTML = drawItem.typeName || '';}if (dragElement) {dragElement.style.height = drawItem.height + 'px';dragElement.style.width = drawItem.width + 'px';dragElement.style.border = '1px solid #000';dragElement.style.background = '#fff';}if (dragElement) {dataTransfer.setDragImage(dragElement, drawItem.width / 2, drawItem.height / 2);}}

React

 import {useRef} from "react";import { Modal, Space, Input, Tree, Button, Badge } from "antd";const mouseStyle = useRef<any>(null);<divdraggable="true"onDragStart={(e) => {//mouseStyle.currente.dataTransfer.setDragImage(mouseStyle.current, 10, 10);}}>移动位置</div>//	
//absolute top-[10%] z-[1] h-10    css使用了tailwindcss
//npm install -D tailwindcss
//https://tailwindcss.com/docs/installation 文档地址<div className="absolute top-[10%] z-[1] h-10" ref={mouseStyle}><Badge count={5}><div className=" border border-[#444444] leading-6 h-6 w-15">2023.09.22初级会计资格考试</div></Badge>
</div>

在这里插入图片描述

4.3 设置放置前的反馈图标

dataTransfer 提供了一个 dropEffect属性设置放置前的反馈图标,它有四种取值 none move copy link

在 dragover 中设置 dropEffect 的值

dropDom.addEventListener('dragover', (e) => {e.preventDefault()e.dataTransfer.dropEffect = 'link' // none || move || copy || link
})
  • 值为 none 或者经过不可放置区域,显示禁止放置图标在这里插入图片描述
  • 值为 move 时
    在这里插入图片描述
  • 值为 copy 时
    在这里插入图片描述
  • 值为 link 时
    在这里插入图片描述

4.4 拖动文件上传

通过 dataTransfer 的 files 属性可以获取用户拖拽的文件信息

拖拽系统文件到放置区域,并打印拖拽的文件信息:

dropDom.addEventListener('drop', (e) => {e.preventDefault()// 上传的文件列表let fileList = e.dataTransfer.filesfor (let i = 0; i < fileList.length; i++) {const file = fileList[i];console.log('文件名:' + file.name);console.log('文件大小:' + file.size);// 后续操作 比如:调接口上传文件}
})

在这里插入图片描述

4.5 清除 setData() 的值

dataTransfer 提供了 clearData() 清除 setData 设置的值,传参数则删除指定类型的值,不传则全部清除。

dropDom.addEventListener('drop', (e) => {console.log(e.dataTransfer.getData('text/plain'));console.log(e.dataTransfer.getData('text/html'));
})dragDom.addEventListener('dragstart', (e) => {e.dataTransfer.setData('text/plain', '自定义数据')e.dataTransfer.setData('text/html', '自定义数据2')e.dataTransfer.clearData('text/html')
})

在这里插入图片描述

4.6 查看设置了哪些类型的值

dataTransfer 提供了 types 属性查看 setData 设置了哪些类型的值。

dropDom.addEventListener('drop', (e) => {console.log(e.dataTransfer.types);
})
dragDom.addEventListener('dragstart', (e) => {e.dataTransfer.setData('text/plain', '自定义数据')e.dataTransfer.setData('text/html', '自定义数据2')
})

在这里插入图片描述

4.7 effectAllowed 属性取值会影响到 dropEffect 的取值效果。

effectAllowed 用于限制 dropEffect 只能设置哪些值

effectAllowed 的取值有: + none -> 此项表示 dropEffect 设置任何值都是禁止效果 + copy -> dropEffect 可以设置为 copy + copyLink -> dropEffect 可以设置为 copy 和 link + copyMove -> dropEffect 可以设置为 copy 和 Move + link -> dropEffect 可以设置为 link + linkMove -> dropEffect 可以设置为 link 和 Move + move -> dropEffect 可以设置为 Move + all -> dropEffect 可以设置为所有合法值 + uninitialized -> 等同 all 效果

dropDom.addEventListener('dragover', (e) => {e.preventDefault()e.dataTransfer.dropEffect = 'move'
})
dragDom.addEventListener('dragstart', (e) => {e.dataTransfer.effectAllowed = 'none'
})

上面即使 dropEffect 设置为 move, 但是 effectAllowed 的值为 none,所有还是禁止放置的反馈图标。
在这里插入图片描述

五、总结

  • 实现一个拖拽功能时先定义好被拖拽元素和放置区域元素。
  • 所有的放置操作都是在 drop 事件中完成。
  • 放置前的反馈效果可以根据你传递的数据来设置 dropEffect 显示不同的效果。
  • 被拖拽元素也可以是放置区域,放置区域也可以是被拖拽元素,两者没有明确的界限。
  • 功能自定义按需求开发

相关文章:

React js原生 详解 HTML 拖放 API(鼠标拖放功能)

最近碰到了个需求&#xff0c;大概就是要通过可视化拖拽的方式配置一个冰柜&#xff0c;需要把预设好的冰柜内部架子模板一个个拖到冰箱内。一开始的想法是用鼠标事件&#xff08;mousedown、mouseup等&#xff09;那一套去实现&#xff0c;能实现但是过程过于复杂&#xff0c;…...

LiveMedia视频中间件如何与第三方系统实现事件录像关联

一、平台简介 LiveMedia视频中间件是支持部署到本地服务器或者云服务器的纯软件服务&#xff0c;也提供服务器、GPU一体机全包服务&#xff0c;提供视频设备管理、无插件、跨平台的实时视频、历史回放、语音对讲、设备控制等基础功能&#xff0c;支持视频协议有海康、大华私有协…...

机器学习-有监督算法-决策树和支持向量机

目录 决策树ID3C4.5CART 支持向量积 决策树 训练&#xff1a;构造树&#xff0c;测试&#xff1a;从模型从上往下走一遍。建树方法&#xff1a;ID3&#xff0c;C4.5&#xff0c;CART ID3 以信息论为基础&#xff0c;以信息增益为衡量标准熵越小&#xff0c;混乱程度越小&…...

luffy项目之后台项目搭建、目录调整、封装日志、全局异常、Response、数据库连接

luffy后台项目创建 在虚拟环境中创建luffy项目安装django&#xff1a;pip install django3.1.12命令创建项目django-admin startproject luffy_api也可以pycharm创建项目&#xff0c;创建项目时选则已经创建好的虚拟环境即可 luffy项目目录调整 """ ├── …...

C++标准模板(STL)- 类型支持 (数值极限,min_exponent10,max_exponent,max_exponent10)

数值极限 std::numeric_limits 定义于头文件 <limits> 定义于头文件 <limits> template< class T > class numeric_limits; numeric_limits 类模板提供查询各种算术类型属性的标准化方式&#xff08;例如 int 类型的最大可能值是 std::numeric_limits&l…...

linux 服务器类型Apache配置https访问

一&#xff1a;查看服务器类型&#xff0c;下载相应的SSL证书 命令&#xff1a;netstat -anp | grep :80 httpd是Apache超文本传输协议(HTTP)服务器的主程序&#xff0c;所以下载Apache证书 二&#xff1a;将证书解压后复制到服务器上 三个文件&#xff1a;xxx.key xxx_publ…...

langchain 加载各种格式文件读取方法

参考&#xff1a;https://python.langchain.com/docs/modules/data_connection/document_loaders/ https://github.com/thomas-yanxin/LangChain-ChatGLM-Webui/blob/master/app.py 代码 可以支持pdf、md、doc、txt等格式 from langchain.document_loaders import Unstruct…...

飞花令游戏(Python)

飞花令是古时候人们经常玩一种“行酒令”的游戏&#xff0c;是中国古代酒令之一&#xff0c;属雅令。“飞花”一词则出自唐代诗人韩翃《寒食》中 春城无处不飞花 一句。行飞花令时选用诗和词&#xff0c;也可用曲&#xff0c;但选择的句子一般不超过7个字。 在《中国诗词大会》…...

解决“413 Request Entity Too Large”错误 代表请求包太大,服务器拒绝响应

解决办法&#xff1a; 在nginx的配置文件nginx.conf中&#xff0c;添加这么一句client_max_body_size 1024m; 意思是最大请求是1024m。这个配置可以放到 http段 或者 server段 或者 location段。...

MoeCTF2023web

01http 打开题目环境 可以看到要求完成所有任务&#xff0c;这里用burp抓个包 按照要求修改可以得到flag moectf{basic_http_knowledge_HJbg427uFuznTqiJdtS1xhZNwpdsOnKU} 02 Web入门指北 直接找到结尾发现乱码&#xff0c;去解码 编码可以试试url编码和base64到16 这里用…...

C语言编写简易图书管理系统

这篇文章介绍了一个基本的图书管理系统的实现&#xff0c;它允许用户添加、插入、删除、修改、显示和查询图书的功能。该系统通过使用二进制文件将图书信息保存到磁盘&#xff0c;并且在程序启动时能够加载已保存的图书信息。 介绍 在计算机科学中&#xff0c;图书管理系统是…...

C++入门 第一篇(C++关键字, 命名空间,C++输入输出)

目录 1. C关键字 2. 命名空间 2.1 命名空间定义 2.2命名空间的使用 命名空间的使用有三种方式&#xff1a; 1.加命名空间名称及作用域限定符 2.使用using将命名空间中某个成员引入 3.使用using namespace 命名空间名称 引入 3. C输入&输出 4.缺省函数 4.1 缺省参…...

python股票波动性分析

一、简介 我们都经历过这样的情况——盯着股票图表,试图理解那些疯狂的价格上涨,或者只是想知道为什么突然平静。在这些波动中,有一个一致的因素常常脱颖而出:波动性。了解波动性为衡量任何特定点的市场情绪和情绪提供了一个视角。通过剖析波动性的细微差别,我们不仅可以更…...

53 打家劫舍

打家劫舍 题解1 DP1题解2 DP2 &#xff01;经典DP&#xff01; 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果 两间相邻的房屋在同一晚上被小偷闯入…...

CentOS 7 基于C 连接ZooKeeper 客户端

前提条件&#xff1a;CentOS 7 编译ZooKeeper 客户端&#xff0c;请参考&#xff1a;CentOS 7 编译ZooKeeper 客户端 1、Docker 安装ZooKeeper # docker 获取zookeeper 最新版本 docker pull zookeeper# docker 容器包含镜像查看 docker iamges# 准备zookeeper 镜像文件挂载对…...

2023-2024-1 for循环-1(15-38)

7-15 输出闰年 输出21世纪中截止某个年份以来的所有闰年年份。注意&#xff1a;闰年的判别条件是该年年份能被4整除但不能被100整除、或者能被400整除。 输入格式: 输入在一行中给出21世纪的某个截止年份。 输出格式: 逐行输出满足条件的所有闰年年份&#xff0c;即每个年…...

初级问题 程序中的变量是指什么?中级问题 把若干个数据沿直线排列起来的数据结构叫作什么?高级问题 栈和队列的区别是什么?

目录 1.深刻主题 2.描写复杂人物 初级问题 程序中的变量是指什么&#xff1f; 中级问题 把若干个数据沿直线排列起来的数据结构叫作什么&#xff1f; 高级问题 栈和队列的区别是什么&#xff1f; 计算机图形学&#xff08;有效边表算法&#xff09; 介绍一下计算机图形学…...

clickhouse数据库简介,列式存储

clickhouse数据库简介 1、关于列存储 所说的行式存储和列式存储&#xff0c;指的是底层的存储形式&#xff0c;数据在磁盘上的真实存储&#xff0c;至于暴漏在上层的用户的使用是没有区别的&#xff0c;看到的都是一行一行的表格。 idnameuser_id1闪光10266032轨道物流10265…...

flask 发送ajax

前端 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <script src"https://cdn.lyshark.com/javascript/jquery/3.5.1/jquery.min.js"…...

Android Gradle 命令打包AAR

平台 Android Archive (AAR) 文件是一种特定于Android的存档文件格式&#xff0c;用于将Android库和资源打包成单个可重用的单元。AAR文件通常用于共享和分发Android库&#xff0c;以便其他Android应用项目可以轻松引用和使用这些库。 AAR文件是一种便捷的方式&#xff0c;用于…...

如何导出带有材质的GLB模型?

1、为什么要使用 GLB 模型? GLB格式&#xff08;GLTF Binary&#xff09;是一种用于存储和传输3D模型及相关数据的文件格式&#xff0c;具有以下优点和作用&#xff1a; 统一性&#xff1a;GLB是一种开放标准的3D文件格式&#xff0c;由Khronos Group制定和维护。它融合了GL…...

C/C++面试常见知识点

目录 C/C语言C内存分区malloc/free与new/delete的区别联合体联合体大小的计算 结构体对齐为什么需要结构体内存对齐 结构体与联合体的区别左值引用与右值引用指针和引用的区别迭代器失效static关键字在C语言的作用进程地址空间的分布内联函数 三大特性构造函数不能是虚函数析构…...

详细介绍数据结构-堆

计算机中的堆数据结构 什么是堆 在计算机科学中&#xff0c;堆&#xff08;Heap&#xff09;是一种重要的数据结构&#xff0c;它用于在动态分配时存储和组织数据。堆是一块连续的内存区域&#xff0c;其中每个存储单元&#xff08;通常是字节&#xff09;都与另一个存储单元…...

001flutter基础学习

flutter基础学习 参考:https://book.flutterchina.club/chapter1/flutter_intro.html Flutter是谷歌的移动UI框架跨平台: Linux,Android, IOS,Fuchsia原生用户界面:它是原生的,让我们体验更好,性能更好开源免费&#xff1a;完全开源,可以进行商用Flutter与主流框架的对比 Cor…...

leetCode 1143.最长公共子序列 动态规划 + 图解

此题我的往期文章推荐&#xff1a; leetCode 1143.最长公共子序列 动态规划 滚动数组-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/133689692?spm1001.2014.3001.5501leetCode 1143.最长公共子序列 一步步思考动态规划 优化空间复杂度_呵呵哒(&#xf…...

解密人工智能:KNN | K-均值 | 降维算法 | 梯度Boosting算法 | AdaBoosting算法

文章目录 一、机器学习算法简介1.1 机器学习算法包含的两个步骤1.2 机器学习算法的分类 二、KNN三、K-均值四、降维算法五、梯度Boosting算法和AdaBoosting算法六、结语 一、机器学习算法简介 机器学习算法是一种基于数据和经验的算法&#xff0c;通过对大量数据的学习和分析&…...

Python深度学习实践

线性模型 课程 import numpy as np import matplotlib.pyplot as plt x_data[1.0,2.0,3.0] y_data[2.0,4.0,6.0] #前馈函数 def forward(x):return x*w #损失函数 def loss(x,y):y_predforward(x)return (y_pred-y)*(y_pred-y) w_list[] mse_list[] for w in np.arange(0.0,4…...

VS2017+QT+PCL环境配置

前言: 最近自己再弄一下小项目中需要用到pcl来开发点云的显示,但是却遇到很多坑,所以记录下来分析给知音人。 避雷:由于vtk和pcl之间有版本以来关系,但是安装过程是不变的。 选择对应的版本参考如下安装: pcl1.8.1依赖vtk版本7.1.1;pcl1.9.1至pcl1.12.0依赖vtk最低版本为…...

207、SpringBoot 整合 RabbitMQ 实现消息的发送 与 接收(监听器)

目录 ★ 发送消息★ 创建队列的两种方式代码演示需求1&#xff1a;发送消息1、ContentUtil 先定义常量2、RabbitMQConfig 创建队列的两种方式之一&#xff1a;配置式&#xff1a;问题&#xff1a; 3、MessageService 编写逻辑PublishController 控制器application.properties 配…...

想要精通算法和SQL的成长之路 - 滑动窗口和大小根堆

想要精通算法和SQL的成长之路 - 滑动窗口和大小根堆 前言一. 大小根堆二. 数据流的中位数1.1 初始化1.2 插入操作1.3 完整代码 三. 滑动窗口中位数3.1 在第一题的基础上改造3.2 栈的remove操作 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 大小根堆 先来说下大小根堆是什…...