【前端】three.js

文章目录

  • 概述
  • three.js-master目录结构
  • Threejs 的基本要素
    • 场景
    • 相机
      • 透视相机
      • 正交相机
    • 网格
      • 2d
      • 3d
    • 灯光
      • AmbientLight(环境光)
      • 平行光(DirectionalLight)
      • 点光源(PointLight)
      • 聚光灯(SpotLight)
    • 渲染器
  • Threejs 的实现
    • 场景的搭建
    • 地图数据的获得
    • 生成地图几何体
    • 相机辅助视图
    • 增加交互控制器
    • 射线追踪
    • 增加tooltip
  • 来源

概述

Three.js是基于原生WebGL封装运行的三维引擎,在所有WebGL引擎中,Three.js是国内文资料最多、使用最广泛的三维引擎。

既然Threejs是一款WebGL三维引擎,那么它可以用来做什么想必你一定很关心。所以接下来内容会展示大量基于Threejs引擎或Threejs类似引擎开发的Web3D应用,以便大家了解。

three.js-master目录结构

在这里插入图片描述

three.js-master
└───build——src目录下各个代码模块打包后的结果│───three.js——开发的时候.html文件中要引入的threejs引擎库,和引入jquery一样,可以辅助浏览器调试│───three.min.js——three.js压缩后的结构文件体积更小,可以部署项目的时候在.html中引入。│
└───docs——Three.js API文档文件│───index.html——打开该文件可以实现离线查看threejs API文档│
└───editor——Three.js的可视化编辑器,可以编辑3D场景│───index.html——打开应用程序│
└───docs——Three.js API文档文件│───index.html——打开该文件可以实现离线查看threejs API文档│
└───examples——里面有大量的threejs案例,平时可以通过代码编辑全局查找某个API、方法或属性来定位到一个案例│
└───src——Three.js引擎的各个模块,可以通过阅读源码深度理解threejs引擎│───index.html——打开该文件可以实现离线查看threejs API文档│
└───utils——一些辅助工具│───\utils\exporters\blender——blender导出threejs文件的插件

html文件引入three.js引擎

在.html文件中引入three.js就像引入其它.js文件一样直接引入即可。

<!--相对地址加载-->
<script src="./three.js"></script>

我已经把three.js文件上传到了我的博客服务器, 可以通过下面的URL地址去加载

<!--http绝对地址远程加载-->
<script src="http://www.yanhuangxueyuan.com/3D/example/three.js"></script>
<!-- 压缩版本 -->
<script src="http://www.yanhuangxueyuan.com/3D/example/three.min.js"></script>

.html文件中引入threejs文件之后,可以通过浏览器控制台F12验证是否成功引入,在.html文件引入three.js后可以通过THREE访问所有的API。

// 如果返回的不是未定义,说明threejs成功引入
console.log('打印场景API',THREE.Scene);

Threejs 的基本要素

场景

「场景」:是一个三维空间,所有物品的容器,可以把场景想象成一个空房间,接下来我们会往房间里放要呈现的物体、相机、光源等。

用代码表示就是如下:

const scene = new THREE.Scene();

你就把他想象成一个房间,然后你可以往里面去添加一些物体,加一个正方体哈,加矩形,什么都可以。其实three.js 整个之间的关系是一个 「树形结构」。

相机

「相机」:Threejs必须要往场景中添加一个相机,相机用来确定位置、方向、角度,相机看到的内容就是我们最总在屏幕上看到的内容。在程序运行过程中,可以调整相机的位置、方向和角度。

three.js 中的相机分为两种一种是正交相机 和透视相机 ,接下来我给大家一一介绍,但是理解照相机的情况下,你要先理解一个概念——视椎体

透视相机

视锥体是摄像机可见的空间,看上去像截掉顶部的金字塔。视锥体由6个裁剪面围成,构成视锥体的4个侧面称为上左下右面,分别对应屏幕的四个边界。为了防止物体离摄像机过近,设置近切面,同时为了防止物体离摄像机太远而不可见,设置远切面。
在这里插入图片描述

oc 就是照相机的位置, 近平面、和远平面图中已经标注。从图中可以看出,棱台组成的6个面之内的东西,是可以被看到的。 影响透视照相机的大小因素:

  • 摄像机视锥体垂直视野角度 也就是图中的「a」
  • 摄像机视锥体近端面 也就是图中的 「near plane」
  • 摄像机视锥体远端面 也就是图中的「far plane」
  • 摄像机视锥体长宽比 「表示输出图像的宽和高之比」

对应的three 中的照相机:

const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 );

​ 透视相机最大的特点:就是符合我们人眼观察事物的特点, 近大远小。

近大远小的背后的实现原理就是相机会有一个投影矩阵: 投影矩阵的做的事情很简单,就是把视椎体转换成一个正方体。 所以远截面的点就要缩小, 近距离的反而放大。

在这里插入图片描述

正交相机

正交相机的特点就是视椎体的是一个立方体

在这种投影模式下,无论物体距离相机距离远或者近,在最终渲染的图片中物体的大小都保持不变。

这对于渲染2D场景或者UI元素是非常有用的。如图:
在这里插入图片描述
three中代码如下:

const camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );

网格

在计算机的世界里,一条弧线是由有限个点构成的有限条线段连接得到的。当线段数量越多,长度就越短,当达到你无法察觉这是线段时,一条平滑的弧线就出现了。 计算机的三维模型也是类似的。只不过线段变成了平面,普遍用三角形组成的网格来描述。我们把这种模型称之为 Mesh 模型。

一条弧线由多条线段得到,线段的数量越多,越接近弧线。 不懂的小伙伴,可以看下我的这篇文章:面试官问我会canvas? 我可以绘制一个烟花 动画里面「贝塞尔曲线可以是用一段段小线段去拟合起来的」 。

three.js 背后所有的图形在进行渲染之前, 都会进行三角化, 然后交给webgl 去渲染。

Threejs提供了一些常见的几何形状,有三维的也有二维的,三维的比如长方体、球体等,二维的比如长方形圆形等,如果默认提供的形状不能满足需求,也可以自定义通过定义顶点和顶点之间的连线绘制自定义几何形状,更复杂的模型还可以用建模软件建模后导入。

2d

在这里插入图片描述

3d

在这里插入图片描述
有了形状,可能渲染出来的图形没有美丽的样子,这时候材质就出来了。 组成的mesh其实是有两个部分:

材质(Material)+几何体(Geometry)就是一个 mesh,Threejs提供了集中比较有代表性的材质,常用的用漫反射、镜面反射两种材质,还可以引入外部图片,贴到物体表面,成为纹理贴图。大家有兴趣可以自己去试一下。如图:

在这里插入图片描述

灯光

假如没有光,摄像机看不到任何东西,因此需要往场景添加光源,为了跟真实世界更加接近,Threejs支持模拟不同光源,展现不同光照效果,有点光源、平行光、聚光灯、环境光等。

AmbientLight(环境光)

环境光会均匀的照亮场景中的所有物体,环境光不能用来投射阴影,因为它没有方向。

const light = new THREE.AmbientLight( 0x404040 ); // soft white light

平行光(DirectionalLight)

平行光是沿着特定方向发射的光。这种光的表现像是无限远,从它发出的光线都是平行的。常常用平行光来模拟太阳光 的效果; 太阳足够远,因此我们可以认为太阳的位置是无限远,所以我们认为从太阳发出的光线也都是平行的。

const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );

点光源(PointLight)

从一个点向各个方向发射的光源。一个常见的例子是模拟一个灯泡发出的光。

const light = new THREE.PointLight( 0xff0000, 1, 100 );

聚光灯(SpotLight)

光线从一个点沿一个方向射出,随着光线照射的变远,光线圆锥体的尺寸也逐渐增大。

const spotLight = new THREE.SpotLight( 0xffffff );

还有一些其他的灯光,感兴趣的小伙伴可以自行去three.js 官网查看。

渲染器

渲染器就是去渲染你场景中灯光、相机、网格哇。

let renderer = new THREE.WebGLRenderer({antialias: true, // true/false表示是否开启反锯齿alpha: true, // true/false 表示是否可以设置背景色透明precision: 'highp', // highp/mediump/lowp 表示着色精度选择premultipliedAlpha: false, // true/false 表示是否可以设置像素深度(用来度量图像的分率)preserveDrawingBuffer: true, // true/false 表示是否保存绘图缓冲maxLights: 3, // 最大灯光数stencil: false // false/true 表示是否使用模板字体或图案

three.js大体的一些要素我都介绍过了,接下面就进入在正题了,three.js 如何实现一个可视化地图呢?

Threejs 的实现

场景的搭建

我先不管地图不地图的,地图的这些形状肯定是放置到场景中的。跟着我的脚步一步一步去搭建一个场景。场景的搭建就照相机,渲染器。我用一个map类来表示代码如下:

class chinaMap {constructor() {this.init()}init() {// 第一步新建一个场景this.scene = new THREE.Scene()this.setCamera()this.setRenderer()}// 新建透视相机setCamera() {// 第二参数就是 长度和宽度比 默认采用浏览器  返回以像素为单位的窗口的内部宽度和高度this.camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000)}// 设置渲染器setRenderer() {this.renderer = new THREE.WebGLRenderer()// 设置画布的大小this.renderer.setSize(window.innerWidth, window.innerHeight)//这里 其实就是canvas 画布  renderer.domElementdocument.body.appendChild(this.renderer.domElement)}// 设置环境光setLight() {this.ambientLight = new THREE.AmbientLight(0xffffff) // 环境光this.scene.add(ambientLight)}}

上面我做了一一的解释,现在场景有了,灯光也有了, 我们看下样子。
在这里插入图片描述
对场景黑乎乎的什么都没有, 接下来我们我随便随便加一个长方体并且调用renderer的render方法。代码如下:

init() {//第一步新建一个场景this.scene = new THREE.Scene()this.setCamera()this.setRenderer()const geometry = new THREE.BoxGeometry()const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })const cube = new THREE.Mesh(geometry, material)this.scene.add(cube)this.render()
}//render 方法 
render() {this.renderer.render(this.scene, this.camera)
}

按照上面 去做你会页面还是明明都已经加了,为什么呢?

「默认情况下,当我们调用scene.add()的时候,物体将会被添加到(0,0,0)坐标。但将使得摄像机和立方体彼此在一起。为了防止这种情况的发生,我们只需要将摄像机稍微向外移动一些即可」

所以只要将照相机的位置z轴属性调整一下就可以到图片了

// 新建透视相机setCamera() {// 第二参数就是 长度和宽度比 默认采用浏览器  返回以像素为单位的窗口的内部宽度和高度this.camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000)this.camera.position.z = 5}

图片如下:

在这里插入图片描述
这时候有同学就会问,嗯搞半天不和canvas 2d 一样嘛,有什么区别? 看不出立体的感觉?

OK 接下来我就让这个立方体动起来。 其实就是不停的去调用 我们render 函数。 我们用reqestanimationframe。尽量还是不要用setInterval,有一个很简单的优化。

「requestAnimationFrame」有很多的优点。最重要的一点或许就是当用户切换到其它的标签页时,它会暂停,因此不会浪费用户宝贵的处理器资源,也不会损耗电池的使用寿命。
我这里做的让立方体的x,y 不断的+0.1。 先看下代码:

render() {this.renderer.render(this.scene, this.camera)
}animate() {requestAnimationFrame(this.animate.bind(this))this.cube.rotation.x += 0.01this.cube.rotation.y += 0.01this.render()
}

效果图如下:
在这里插入图片描述
是不是有那个那个感觉了, 我是以最简单的立方体的旋转,带大家从头入门下three.js。 如果看到这里觉得这里,觉得对你有帮助的话,希望你能给我点个赞 哦,感谢各位老铁了!下面正式地图需求分析。

地图数据的获得

其实最重要的是获取地图数据, 大家可以了解下openStreetMap

这个是一个可供自由编辑的世界地图。OpenStreetMap允许你查看,编辑或者使用世界各地的地理数据来帮助你。

这里我自己把中国地图的数据json拷贝下来了,代码如下:

// 加载地图数据
loadMapData() {const loader = new THREE.FileLoader()loader.load('../json/china.json', (data) => {const jsondata = JSON.parse(JSON.stringify(data))})
}

其实主要的是下面有个经纬度坐标, 其实这个才是我关心的,有了点才能生成线,最后才能生成平面。 这里涉及到一个知识点, 「墨卡托投影转换」。 墨卡托投影转换可以把我们经纬度坐标转换成我们对应平面的2d坐标。

这里我直接用可视化框架——「d3」 它里面有自带的墨卡托投影转换。

// 墨卡托投影转换const projection = d3.geoMercator().center([104.0, 37.5]).scale(80).translate([0, 0])

由于中国有很多省,每个省都对应一个Object3d。

Object3d是three.js 所有的基类, 提供了一系列的属性和方法来对三维空间中的物体进行操纵。可以通过.add( object )方法来将对象进行组合,该方法将对象添加为子对象

我这里的整个中国是一个大的Object3d,每一个省是一个Object3d,省是挂在中国下的。 然后中国这个Map挂在scene这个Object3d下。 很明显,在three.js 是一个很典型的树形数据结构,我画了张图给大家看下。

在这里插入图片描述

Scence场景下挂了很多东西, 其中有一个就是Map, 整个地图, 然后每个省份, 每个省份又是由Mesh和lLine 组成的。

我们看下代码:

generateGeometry(jsondata) {
// 初始化一个地图对象
this.map = new THREE.Object3D()
// 墨卡托投影转换
const projection = d3
.geoMercator()
.center([104.0, 37.5])
.scale(80)
.translate([0, 0])

  jsondata.features.forEach((elem) => {// 定一个省份3D对象const province = new THREE.Object3D()this.map.add(province)})this.scene.add(this.map)
}

看到这里我想你可能没有什么问题,我们整体框架定下来了,接下来我们进入核心环节

生成地图几何体

这里用到了 Three.shape() 和 THREE.ExtrudeGeometry() 为什么会用到这个呢? 我给大家解释下, 「首先每一个省份轮廓组成的下标是一个 2d坐标,但是我们要生成立方体,shape() 可以定义一个二维形状平面。 它可以和ExtrudeGeometry一起使用,获取点,或者获取三角面。」

代码如下:

// 每个的 坐标 数组const coordinates = elem.geometry.coordinates// 循环坐标数组coordinates.forEach((multiPolygon) => {multiPolygon.forEach((polygon) => {const shape = new THREE.Shape()const lineMaterial = new THREE.LineBasicMaterial({color: 'white',})const lineGeometry = new THREE.Geometry()for (let i = 0; i < polygon.length; i++) {const [x, y] = projection(polygon[i])if (i === 0) {shape.moveTo(x, -y)}shape.lineTo(x, -y)lineGeometry.vertices.push(new THREE.Vector3(x, -y, 4.01))}const extrudeSettings = {depth: 10,bevelEnabled: false,}const geometry = new THREE.ExtrudeGeometry(shape,extrudeSettings)const material = new THREE.MeshBasicMaterial({color: '#2defff',transparent: true,opacity: 0.6,})const material1 = new THREE.MeshBasicMaterial({color: '#3480C4',transparent: true,opacity: 0.5,})const mesh = new THREE.Mesh(geometry, [material, material1])const line = new THREE.Line(lineGeometry, lineMaterial)province.add(mesh)province.add(line)})})

遍历第一个点的的和canvas2d画图其实是一模一样的, 移动起点, 然后后面在划线, 画出轮廓。然后我们在这里可以设置拉伸的深度, 然后接下来就是设置材质了。lineGeometry 其实 对应的是轮廓的边线。我们看下图片吧:
在这里插入图片描述

相机辅助视图

为了方便调相机位置, 我增加了辅助视图, cameraHelper。 然后你回看下屏幕会出现一个十字架,然后我们就可以不断地调整相机的位置,让我们地地图处于画面的中央:

addHelper() {const helper = new THREE.CameraHelper(this.camera)this.scene.add(helper)
}

经过辅助的视图地不断调整:
在这里插入图片描述

增加交互控制器

现在地图是已经生成了,但是用户交互感比较差,这里我们引入three的OrbitControls 可以用鼠标在画面随意转动,就可以看到立方体的每一个部分了。但是这个方法不在three 的包里面, 得单独引入一个文件代码如下:

setController() {this.controller = new THREE.OrbitControls(this.camera,document.getElementById('canvas'))
}

我们看下效果:

three.js增加交互控制器效果

射线追踪

但是对于我自己而言还是不满意, 我怎么知道的我点击的是哪一个省份呢,OK这时候就要引入我们three中非常重要的一个类了,Raycaster 。

这个类用于进行raycasting(光线投射)。 光线投射用于进行鼠标拾取(在三维空间中计算出鼠标移过了什么物体)。

我们可以对canvas监听的onmouseMove 事件,然后 我们就可以知道当前移动的鼠标是选择的哪一个mesh。但是在这之前,我们先对每一个province这个对象上增加一个属性来表示他是哪一个省份的。

// 将省份的属性 加进来

province.properties = elem.properties

Ok, 我们可以引入射线追踪了带入如下:

setRaycaster() {this.raycaster = new THREE.Raycaster()this.mouse = new THREE.Vector2()const onMouseMove = (event) => {// 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1}window.addEventListener('mousemove', onMouseMove, false)
}animate() {requestAnimationFrame(this.animate.bind(this))// 通过摄像机和鼠标位置更新射线this.raycaster.setFromCamera(this.mouse, this.camera)this.render()
}

由于我们不停地在在画布移动, 所以需要不停的的射线位置。现在有了射线, 那我们需要场景的所有东西去比较了,rayCaster 也提供了方法代码如下:

const intersects = this.raycaster.intersectObjects(this.scene.children, // 场景的true  // 若为true,则同时也会检测所有物体的后代。否则将只会检测对象本身的相交部分
)

这个intersects得到的交叉很多,但是呢我们只选择其中一个,那就是物体材质个数有两个的, 因为我们上面就是用对mesh用两个材质

 const mesh = new THREE.Mesh(geometry, [material, material1])

所以过滤代码如下

animate() {requestAnimationFrame(this.animate.bind(this))// 通过摄像机和鼠标位置更新射线this.raycaster.setFromCamera(this.mouse, this.camera)// 算出射线 与当场景相交的对象有那些const intersects = this.raycaster.intersectObjects(this.scene.children,true)const find = intersects.find((item) => item.object.material && item.object.material.length === 2)this.render()
}

我怎么知道我到底找到没,我们对找到的mesh将它的表面变成灰色,但是这样会导致一个问题,我们鼠标再一次移动的时候要把上一次的材质给他恢复过来。

代码如下:

animate() {requestAnimationFrame(this.animate.bind(this))// 通过摄像机和鼠标位置更新射线this.raycaster.setFromCamera(this.mouse, this.camera)// 算出射线 与当场景相交的对象有那些const intersects = this.raycaster.intersectObjects(this.scene.children,true)// 恢复上一次清空的if (this.lastPick) {this.lastPick.object.material[0].color.set('#2defff')this.lastPick.object.material[1].color.set('#3480C4')}this.lastPick = nullthis.lastPick = intersects.find((item) => item.object.material && item.object.material.length === 2)if (this.lastPick) {this.lastPick.object.material[0].color.set(0xff0000)this.lastPick.object.material[1].color.set(0xff0000)}this.render()}

看下效果图:

three.js射线追踪效果

增加tooltip

为了让交互更加完美,找到了同时在鼠标右下方显示个tooltip,那这个肯定是一个div默认是影藏的,然后根据鼠标的移动移动相应的位置。

第一步新建div

<div id="tooltip"></div>

第二步设置样式 默认是影藏的

#tooltip {position: absolute;z-index: 2;background: white;padding: 10px;border-radius: 2px;visibility: hidden;
}

第三步更改div的位置:

  setRaycaster() {this.raycaster = new THREE.Raycaster()this.mouse = new THREE.Vector2()this.tooltip = document.getElementById('tooltip')const onMouseMove = (event) => {this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1// 更改div位置this.tooltip.style.left = event.clientX + 2 + 'px'this.tooltip.style.top = event.clientY + 2 + 'px'}window.addEventListener('mousemove', onMouseMove, false)}

最后一步设置tooltip的名字:

showTip() {// 显示省份的信息if (this.lastPick) {const properties = this.lastPick.object.parent.propertiesthis.tooltip.textContent = properties.namethis.tooltip.style.visibility = 'visible'} else {this.tooltip.style.visibility = 'hidden'}}

到这里,整个3d可视化地球项目已经完成了, 我们一起看下效果吧。

three.js3D可视化地图效果

来源

带你入门three.js——从0到1实现一个3d可视化地图
Three.js教程

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

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

相关文章

WordPress更改文章分类插件

当WP网站内容比较多的时候&#xff0c;有时候如果涉及到批量修改文章分类&#xff0c;如果一个个的去操作的话就太费事了&#xff0c;如果使用后台批量修改分类的话是增加旧分类不会取消选择&#xff0c;就就导致我们适得其反还需要一个一个的去编辑取消&#xff0c;实在繁琐了…

Java高级技术(单元测试)

一&#xff0c;概括 二&#xff0c;junit 三&#xff0c;案例 &#xff08;1&#xff09;&#xff0c;实验类 package com.bilibili;public class Name {public static void main(String name) {if (name null){System.out.println("0");return;}System.out.print…

PC端数据列表有头像显示头像,没有头像显示名字的第一个字

PC端数据列表有头像显示头像&#xff0c;没有头像显示名字的第一个字 .charAt(0) 是 JavaScript 字符串对象的方法&#xff0c;用于获取字符串的第一个字符。 字符串中的字符位置是从 0 开始的&#xff0c;所以.charAt(0) 就表示获取字符串的第一个字符。 <el-table ref&qu…

哈希思想应用【C++】(位图,布隆过滤器,海量数据处理面试题)

目录 一&#xff0c;位图 1. 位图概念 2.实现 3. 测试题 位图的优缺点 二&#xff0c;布隆过滤器 1). 布隆过滤器提出 2). 概念 3). 布隆过滤器的查找 4). 布隆过滤器删除(了解) 5). 布隆过滤器优点 6). 布隆过滤器缺陷 三&#xff0c;海量数据面试题 1&#xff…

java开发必备的Tomcat-servlet-http和spring boot基础入门

tomcat 介绍 概念&#xff1a; Tomcat是一个开源免费的轻量级Web服务器&#xff0c;是Apache软件基金会的核心项目&#xff0c;支持Servlet/JSP少量JavaEE(JakartaEE)规范。 JavaEE&#xff1a;Java Enterprise Edition&#xff0c;Java企业版。指Java企业级开发的技术规范总和…

Testlink 1.9.20+phpstudy_pro安装遇到的问题

phpstudy_pro启动了Apache2.4.39和Mysql5.7.26,php的版本是7.3.4zai。 安装Testlink 1.9.19时没有数据库的问题&#xff0c;安装Testlink 1.9.20时遇到了数据库问题&#xff0c;如下图所示&#xff1a; 网上搜索“Failed!Mysql Database cannnot be used”&#xff0c;给出的…

STM32开发学习(地址映射)

LED灯代码&#xff1a; #define PERIPH_BASE ((unsigned int)0x40000000)#define AHB1PERIPH_BASE (PERIPH_BASE 0x00020000)#define GPIOF_BASE (AHB1PERIPH_BASE 0x1400)#define GPIOF_MODER *(unsigned int*)(GPIOF_BASE0x00) #define GPIOF_BSRR *(uns…

Linux下Docker 离线安装详细步骤,亲测成功

1.离线原因&#xff1a;公司新创不能使用开元linux&#xff0c;使用了一个变种centOS&#xff0c;致使yum被禁 2.步骤&#xff1a; 2.1 下载docker tar包&#xff0c;下载地址&#xff1a;Index of linux/https://download.docker.com/linux/ 2.2 新建自己的软件目录&am…

大数据之HBase

HBase介绍 Apache的三篇论文&#xff0c;GFS谷歌文件系统->HDFS&#xff1b;MR -> MR ; BigTable ->HBase;HBase是hadoop数据库&#xff0c;一种分布式、可扩展的大数据NoSQL数据库之一。适合对于大量数据进行随机、实时的读写操作 HBase数据模型 Bigtable是一个稀…

【傻瓜级JS-DLL-WINCC-PLC交互】8.DLL读写WINCC连接的PLC数据

思路 JS-DLL-WINCC-PLC之间进行交互&#xff0c;思路&#xff0c;先用Visual Studio创建一个C#的DLL控件&#xff0c;然后这个控件里面嵌入浏览器组件&#xff0c;实现JS与DLL通信&#xff0c;然后DLL放入到WINCC里面的图形编辑器中&#xff0c;实现DLL与WINCC的通信。然后PLC与…

Vue实现可拖拽边界布局

Vue实现可拖拽边界布局 在前端开发中&#xff0c;有时需要实现一种可拖拽边界的布局&#xff0c;通过拖动分隔线来调整不同区域大小。例如&#xff0c;下图是一个典型的可拖拽边界布局&#xff0c;它由左右两个区域组成&#xff0c;左边是一个树形菜单&#xff0c;右边是一个上…

ANN人工神经网络:从基础认知到现实理解

什么是神经网络&#xff1f; 神经网络的再认知 前面我们了解过&#xff0c;人工神经网络&#xff08;Artificial Neural Network&#xff0c;ANN&#xff09;是人类为了模仿人大脑的神经网络结构创建出来的一种计算机系统结构。但如果仔细深入到神经网络当中&#xff0c;会慢…

排序算法基本原理及实现1

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 &#x1f4d1;插入排序 &#x1f4…

JAVAEE---多线程线程安全

根本原因&#xff1a;随机调度&#xff0c;抢占式执行 多个线程同时修改同一个变量 修改操作不是原子的 内存可见性 指令重排序 上面这段代码可以正常打印出hello&#xff0c;按照我们前面所学&#xff0c;第一次加锁之后&#xff0c;第二次加锁应该有所冲突啊。这里是因为…

c++ day2

自己封装一个矩形类(Rect)&#xff0c;拥有私有属性:宽度(width)、高度(height)&#xff0c; 定义公有成员函数: 初始化函数:void init(int w, int h) 更改宽度的函数:set_w(int w) 更改高度的函数:set_h(int h) 输出该矩形的周长和面积函数:void show() #ifndef RECT_H …

量子力学应用:探索科技前沿的奇幻之旅

量子力学应用:探索科技前沿的奇幻之旅 引言 量子力学,这门探讨微观世界规律的学科,自其诞生以来就充满了神秘与奇幻。随着科学技术的不断进步,量子力学已经从纯理论研究走向了实际应用领域,为我们打开了一个全新的科技世界。在本文中,我们将深入探讨量子力学的应用方面,…

JS 绘制半径不一致的环形图进度条

HTML部分: <canvas id"mycanvas" width"100" height"100"></canvas>JS部分&#xff1a; const option {element: "mycanvas", // 元素count: 26, // 高亮数据totalCount: 129, // 总数据progressColor: #3266FB, // 进…

一文详解Python中常用数据类型

文章目录 Python 中常用的数据类型包括&#xff1a;Python 中布尔类型(bool)Python 中的数字类型概述Pyhon中的字符串概述Python 中的List概述Python 中的元组类型(tuple)Python中的字典&#xff08;Dictionary&#xff09;Python中的集合&#xff08;Set&#xff09;Python中的…

你了解vue的diff算法吗?

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Vue篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容:vue中的diff算法 目录 一、是什么 二、比较方式 三、原理分析 小结 一、是什么 diff 算法是一…

【蓝桥杯选拔赛真题69】Scratch洗牌发牌 少儿编程scratch图形化编程 蓝桥杯创意编程选拔赛真题解析

目录 scratch洗牌发牌 一、题目要求 编程实现 二、案例分析 1、角色分析