基于web创建逼真的3D图形 | CSS技巧
在成为一名web开发者之前,我从事于视觉设计行业,创造屡获殊荣,电影和电视节目等高端3D效果,例如 Tron, The Thing, Resident Evil,和 Vikings 。为了能够创造这些效果,我们需要使用高度复杂的动画软件,例如 Maya , 3Ds Max 或者 Houdini ,包括使用数以百计的机器 渲染机器 来做长时间的离线渲染。正因为我工作以来一直使用这些工具,以至于我对现在的web技术感到很惊讶。我们可以创造和显示高质量的3D内容在浏览器里面,实际上,就是使用webGL和Three.js。
这个项目例子 是使用这些技术创建的。在他们的网站里,你可以发现更多thress.js的项目。
使用three.js的一些项目
这些由three.js构建的网站表明,3D可视化在商业,零售,娱乐和广告领域拥有巨大的潜力。
WebGL是比较低级的JavaScript的API,它能够通过使用GPU,来创造并将3D的内容显示在浏览器里面。不幸地是,既然WebGL是比较低的API,意味着它更加困难被使用。你需要编写上百行代码来运行,即使是很简单的任务。three.js,另一方面来说,是一个开放的JavaScript库,抽象了WebGL的复杂性,同时允许你以更简单的方式,创造实时的3D内容。
在本教程中,我将介绍基础的three.js库。在介绍一个新的程序库时,先举一个简单的例子来更好地表达基本原理,但我想进一步说明这一点。同时,我还将建立一个场景,更加愉快和逼真。
我们就开始了一个简单的平面和球面但最终它会看起来像这样:
See the Pen learning-threejs-final by Engin Arslan ( @enginarslan ) on CodePen .
临摹是计算机图形学的顶峰,但是,在你的位置下,实现不一定是进程中必要的因素,而是从你的工具箱中进行智能部署。这里有一些技术,你将会在本教程中学到,它将帮助实现照片写实。
颜色,凹凸和粗糙度图。
物理材料
阴影照明
逼真的3D图像 by Ian Spriggs
您将在这里学习的基本3D原理和技术在任何其他3D内容创建环境中都是相关的,无论是混合机、Unity、玛雅还是3ds max。
这将是一个漫长的教程。如果您是一个喜欢看视频的人,或者您想了解更多的关于Three.js,您应该看看我对这个问题培训的视频。来自 Lynda.com .
要求
当使用three.js时,如果你在本地工作,它有助于通过本地服务器服务HTML文件,以便加载像外部三维几何图形、图像等应用场景。如果你在寻找一个很容易建立的服务,你可以使用python来运行简单的HTTP服务器。python在很多操作系统上都有安装。
您不必担心设置本地开发服务器来执行本教程。相反,您将依赖于数据URL来加载像图片这样的资源,以消除设置服务器的开销。使用线上代码编辑器像 CodePen ,你可以很轻松的运行你的Three.js代码场景。
本教程假设对前端JavaScript以及对前端Web开发的知识有一些了解。如果您不习惯使用JavaScript,但希望轻松上手,您可能需要查看课程/书籍。 ["Coding for Visual Learners: Learning JavaScript with p5.js"( http://www.codingforvisuallearners.com/ ). (免责声明:我是作者)
让我们开始在Web上建立3D图形!
入门
我已经准备了 prepared a Pen 你可以跟随本教程进行操作。
您将使用的HTML代码将是超级简单的。它只需要有一个div元素来承载正在显示3D图形的画布。它从CDN上加载Three.js库(版本86)。
<div id="webgl"></div> ``<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/86/three.min.js">``</script>
为了您的方便,CodeOpen隐藏了HTML结构。如果您在其它在线编辑器或本地站点上构建此场景,那么您的HTML将需要类似于下面代码的内容,其中 main.js 将是保存JavaScript代码的文件。
<!DOCTYPE html> <html> <head><title>Three.js</title><style type="text/css">html, body {margin: 0;padding: 0;overflow: hidden;}</style> </head> <body><div id="webgl"></div>``<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/86/three.min.js">``</script>``<script src="./main.js">``</script> </body> </html>
请注意html中的简单CSS声明。这就是你在CodePen里的CSS标签:
html, body {margin: 0;padding: 0;overflow: hidden; }
这是为了确保没有任何的margin和padding值,可以通过您的浏览器应用,不会出现滚动条,因此可以有图形填充整个屏幕。这就是我们开始构建3D图形需要的一切。
第一部分 - Three.js 基本场景
当我们平常用three.js和3D来工作时,这里有几个您需要掌握的对象。它们是 场景 , 相机 以及 渲染 。
首先,您需要创造一个场景。您可以把一个场景对象看作是您要处理的每一个3D对象的容器。它代表了您将要创造的3D世界。您可以像这样来创造场景对象:
var scene = new THREE.Scene();`
另外一件事就是当你使用3D工作时,你需要相机。想象相机就像眼睛一样,你会看到这个3D世界。当使用2D可视化时,相机的概念通常是不存在的。你看到什么就是什么。但是在3D的世界,你需要一个相机来定义你的观点,因为你可以从一个场景中看到很多的位置和角度。相机不仅定义了位置,而且还定义了其他的信息,如视野或纵横比。
var camera = new THREE.PerspectiveCamera(45, // field of viewwindow.innerWidth / window.innerHeight, // aspect ratio1, // near clipping plane (beyond which nothing is visible)1000 // far clipping plane (beyond which nothing is visible) );
相机捕捉场景以显示目的,但我们实际上可以看到任何东西,3D数据需要转换为2D图像。这个过程称为 正在渲染 ,同时你需要用 渲染器 在three.js的场景中来进行渲染。你可以初始化渲染像这样的:
var renderer = new THREE.WebGLRenderer();`
之后设置渲染器的大小。这将决定输出图像的大小。
renderer.setSize(window.innerWidth, window.innerHeight);`
为了能够显示你渲染的结果,你需要将渲染器的 domelement 属性追加到HTML内容里面。你会使用空的div元素,为此来创造id为 WebGL 的元素。
document.getElementById('webgl').appendChild(renderer.domElement);`
当做完这一切,你可以视在渲染器上 渲染 的这种方法,是提供场景和相机作为参数对象。
renderer.render(scene,camera );
为了让代码更简洁,在函数 init 里面进行调用和执行功能。
init();`
也许你现在什么也看不见...除了黑屏。别急,这是正常的。这个场景是正常工作的,但是你没有包含任何的对象再场景里面,你所看到的基本上是空的空间,接下来,你会使用3D对象填充这个场景。
看 the Pen learning-threejs-01 by Engin Arslan ( @enginarslan ) on CodePen .
向场景中添加对象
three.js里面的几何对象是由两部分组成的。一个几何对象决定了一个对象的形状和一个材料决定了其表面质量,一个对象的外形,两者的结合组成了three.js里面的网格,形成3D对象。
Three.js允许你创建一些简单的形状,如立方体、球体在一个简单的方式。您可以通过创建一个简单的球体的半径值。
var geo = new THREE.SphereGeometry(1);`
这里有各种材料可以在几何中使用。材料决定了一个对象对光场景的反应。我们可以用一切材料使物体反光,粗糙,透明等。默认的材料,像由 MeshBasicMaterial . MeshBasicMaterial 创造的three.js对象一点不受光场景的影响。这意味着即使你的场景中没有灯光,你的几何图形也将可见。你可以用一个颜色属性,可以为对象设置你想要的颜色 meshbasicmaterial hex值传递一个对象,您现在将使用此材料,但稍后更新它将使您的对象受到场景灯光的影响。你没有任何照明的场景,现在 meshbasicmaterial 应该是一个好的选择。
var material = new THREE.MeshBasicMaterial({color: 0x00ff00 });
你可以结合几何和材料创建一个网格,这将形成三维物体。
var mesh = new THREE.Mesh(geometry, material);`
创建一个函数来封装创建球体的代码。在本教程中,您不会创建多个球体,但保持整体整洁还是不错的。
function getSphere(radius) {var geometry = new THREE.SphereGeometry(radius);var material = new THREE.MeshBasicMaterial({color: 0x00ff00});var sphere = new THREE.Mesh(geometry, material);return sphere; }var sphere = getSphere(1);
然后,您需要将这个新创建的对象添加到场景中以使其可见。
scene.add(sphere);`
让我们再次检查这个场景,你还会看到这个黑屏。
看代码 learning-threejs-02 by Engin Arslan ( @enginarslan ) on CodePen .
无论何时你往three.js里面添加场景对象,对象被放置在场景的中心,在x、y和z的坐标为0, 0, 0,就是你什么都看不到的原因,这就意味着你目前的相机和球体处于同一位置。你应该改变他们中的任何一个的位置,以便能够开始看东西。
3D协调
让我们把照相机20个单位移到z轴上。这是通过在摄像机上设置 * 位置的属性来实现的。3D对象有 position , rotation 和 scale 属性,可以允许你在3D空间里面任意旋转它们。
camera.position.z = 20;`
你可以移动摄像机以及其他轴。
camera.position.x = 0; camera.position.y = 5; camera.position.z = 20;
相机现在位置更高了,但是球体不再在框架的中心位置了。你需要把相机指向它。为了能够做到这样,你可以调用相机的一个方法称为 lookAt 。通过相机上的 lookAt 方法确定哪些点是相机指向的。在三维空间中的点表示的是向量。所以,你可以通过一个新的 Vector3 对象,这 lookAt 方法能在0, 0, 0相机坐标看。
camera.lookAt(new THREE.Vector3(0, 0, 0));`
球对象现在看起来不是很圆。究其原因,是 spheregeometry 函数实际上接受两个额外的参数,宽度和高度细分,影响 resolution 表面。增加这些值,平滑的曲面会出现。我将此值设置为24的宽度和高度细分。
var geo = new THREE.SphereGeometry(radius, 24, 24);`
See the Pen learning-threejs-03 by Engin Arslan ( @enginarslan ) on CodePen .
现在,您将创建一个简单的平面几何的球体。 PlaneGeometry 函数要求有 width 和 height 参数。在3D中,2D对象没有默认的两个侧面,所以你需要将一个 side 属性传递给材质,使平面几何体的两边呈现。
function getPlane(w, h) {var geo = new THREE.PlaneGeometry(w, h);var material = new THREE.MeshBasicMaterial({color: 0x00ff00,side: THREE.DoubleSide,});var mesh = new THREE.Mesh(geo, material);return mesh; }
现在你可以往这个平面对象里添加场景。你会注意到,平面几何的初始旋转是平行于y轴,但你可能需要它是水平的,因为它作为一个接地平面,你需要记住一件重要的事,那就是three.js里的旋转。它们用 radians 为单位,不用 degrees 。弧度旋转90度相当于 π/ 2 数学。
var plane = getPlane(50, 50); scene.add(plane); plane.rotation.x = Math.PI/2;
当你创造一个球对象,它用它的中心点定位。如果你想把它移动到地面上,那么你可以只增加它的'位置' Y值的当前半径的数量。但这不会是一个纲领性的做事方式。如果你想让球体停留在平面上,不管它的半径值是多少,你都应该利用半径值来定位。
sphere.position.y = sphere.geometry.parameters.radius;`
看 the Pen learning-threejs-04 by Engin Arslan ( @enginarslan ) on CodePen .
动画
你几乎完成了本教程的第一部分。但在我们把它整合起来之前,我想说明一下如何用three.js来做动画。three.js动画中使用的 requestanimationframe 方法对 窗口 对象反复执行一个给定的函数。它有点像一个 setInterval 函数,但它是绘制浏览器运行性能。
创造一个 update 函数,通过渲染,场景,和相机在那里执行渲染方法,在函数内进行渲染。你将会在内部声明 requestAnimationFrame 函数,并将 更新 函数,通过对 requestanimationframe 函数递归进行回调,这样说明代码比写出来更好。
function update(renderer, scene, camera) {renderer.render(scene, camera);requestAnimationFrame(function() {update(renderer, scene, camera);}); }
在这一点上一切看起来都一样,但核心的区别是, requestanimationframe 函数是使场景渲染每秒约60帧递归调用的 更新 函数。这意味着如果你正在 update 函数里面执行语句,该语句将以每秒60次的速度执行。让我们添加一个缩放动画球对象。为了从 update 函数中选择球体对象,您可以将它作为参数传递,但我们将使用不同的技术。首先,在球对象上设置一个 name 属性,并给它取一个你喜欢的名字。
sphere.name = 'sphere';`
在update函数内部,你可以使用它的名字,并且使用 getObjectByName 方法在其父对象上,找到该对象,这个场景。
var sphere = scene.getObjectByName('sphere'); sphere.scale.x += 0.01; sphere.scale.z += 0.01;
通过这段代码,这个球的X和Z轴在缩放。尽管我们的意图不是创造一个缩放的球。我们正在设置 update 函数,以便我们以后可以使用不同的动画。现在你已经看到了它是如何工作的,你可以删除这个缩放动画。
看代码 learning-threejs-05 by Engin Arslan ( @enginarslan ) on CodePen .
第二部分 - 在场景中添加现实
目前,我们正在使用 MeshBasicMaterial ,即使在场景中没有灯光时,它也会显示出给定的颜色,这会导致一个非常扁平的外观。尽管真实世界的材料不会以这种方式进行工作。真实世界可见的表面,取决于从表面反射回我们眼睛的光有多少。three.js有几个不同的材料,提供更好的接近实际表面的行为,其中一个是 meshstandardmaterial 。 meshstandardmaterial 是一个基于物理的渲染材料,可以帮助你达到逼真的效果。这是现代游戏引擎的一种材料,如 Unreal or Unity,是游戏和视觉效果的行业标准。
让我们开始在我们对象中使用 MeshStandardMaterial ,改变其颜色变为白色。
var material = new THREE.MeshStandardMaterial({color: 0xffffff, });
你将会在这个点上再次得到黑色渲染。这是正常的。对象在场景中需要光才能显示。这对于 meshbasicmaterial 不是必须的,因为它是一个简单的材料,在所有条件下,显示给定的颜色,但其他材料需要与光的相互作用才可见。让我们创造一个 SpotLight 函数,你将会用这个函数创造两个聚光灯。
function getSpotLight(color, intensity) {var light = new THREE.SpotLight(color, intensity);return light; }var spotLight_01 = getSpotlight(0xffffff, 1); scene.add(spotLight_01);
你也许在这个点上可以看到些事情。为了更好的取景和阴影,光线和相机的位置有点不同。同时创造一个辅助光。
var spotLight_02 = getSpotlight(0xffffff, 1); scene.add(spotLight_02);camera.position.x = 0; camera.position.y = 6; camera.position.z = 6;spotLight_01.position.x = 6; spotLight_01.position.y = 8; spotLight_01.position.z = -20;spotLight_02.position.x = -12; spotLight_02.position.y = 6; spotLight_02.position.z = -10;
做完这些,你场景中将有两个光源,从两个不同的位置照射球体。灯光有助于了解场景的维度。但在这一点上,事情仍然非常不真实,因为照明缺少一个关键的组成部分:阴影!
不幸地是,在three.js中渲染阴影不是很简单。这是因为阴影计算上很费成本,我们需要在多个地方激活阴影渲染。首先,你需要告诉渲染器开始渲染阴影:
var renderer = new THREE.WebGLRenderer(); renderer.shadowMap.enabled = true;
然后,你需要告诉光线投射阴影。在 getSpotLight 函数里面进行。
light.castShadow = true;`
你应该告诉对象投射或者接收阴影。在这种情况下,你将会让球体投射阴影并且用这个平面来接收阴影。
mesh.castShadow = true; mesh.receiveShadow = true;
在设置了这些之后,我们应该开始看场景中的阴影。首先,他们可能效果不是很好。您可以通过设置光影贴图大小来提高阴影的分辨率。
light.shadow.mapSize.x = 4096; light.shadow.mapSize.y = 4096;
MeshStandardMaterial 有很多属性,例如 roughness 和 metalness 控制表面与光的相互作用。这些属性取值在0到1之间,它们控制着相应的表面行为。增加平面材料的粗糙度值到1,使表面看起来更像一个橡胶,作为反射而使其变得模糊。
// material adjustments var planeMaterial = plane.material; planeMaterial.roughness = 1;
尽管如此,在本教程中我们不会将其值设为 1 。您可以自由试验值,但可以将其设置为0.65,用于粗糙度和0.75的金属。
planeMaterial.roughness = 0.65; planeMaterial.metalness = 0.75;
尽管现在的场景看起来更有希望,但仍然很难称之为现实。事实是,在不使用纹理贴图的情况下,很难在三维中建立光致主义。
看代码 learning-threejs-06 by Engin Arslan ( @enginarslan ) on CodePen .
纹理映射
材质贴图是二维图像,可以在材质上进行映射,以提供表面细节。到目前为止,你只能在表面上得到纯色,但使用纹理贴图,你可以在一个表面上绘制任何你想要的图像。纹理贴图不仅被用来操纵表面的颜色信息,而且还可以用来操纵表面的其他特性,如反射性、亮度、粗糙度等。
纹理可以从照片来源获得,也可以从草稿中绘制。对于一个在3D环境中有用的纹理,它应该以某种方式被捕获。图像中有反射或阴影,或图像过于扭曲的图像,不会产生很好的纹理贴图。有几个专门的网站在网上寻找纹理。其中一个是 textures.com ,它有一个很好的存档。他们有一些免费的下载选项,但你需要注册才能做到这一点。另一个3D材质的网站是 Megascans ,它的高分辨率,高质量的环境扫描,高质量的产品质量。
我使用了一个名为 mb3d.co.uk 的网站上的例子。这个网站提供了无缝的、免费的纹理。无缝纹理意味着一种纹理,可以在表面上多次重复,而不会在边缘遇到任何不连续性的情况下发生. 这是链接 我用的纹理文件。我已经将图片文件的大小缩小到512px,并使用一个名为 ezgif 的在线服务将图像文件转换为数据URI,以将其作为JavaScript代码的一部分,而不是将其作为单独的资产加载。(提示:如果要使用该服务,不要将标记包含在数据中)
创建一个函数,返回我们生成的数据URI,这样我们就不必在代码的中间放置一个大的字符串。
function getTexture() {var data = 'data:image/jpeg;base64,/...'; // paste your data URI inside the quotation marks.return data }
接下来,你需要加载纹理并将其应用到平面上。为此您将使用three.js。在加载纹理之后,你会将纹理加载到所需材质的地图属性中,将其作为一种颜色地图在表面上。
var textureLoader = new THREE.TextureLoader(); var texture = textureLoader.load(getTexture()); planeMaterial.map = texture;
现在的东西看起来很难看,因为表面的纹理像素化了。这张图片拉伸得太大了,无法覆盖整个表面。你可以做的是让图像重复,而不是缩放,这样就不会像素化了。为此,您需要设置 wrapSand wrapT 属性为 THREE.RepeatWrapping 。重复包装并指定重复值。因为你也会为其他类型的地图做这个(比如凹凸或粗糙贴图),最好是为它创建一个循环:
var repetition = 6; var textures = ['map']// we will add 'bumpMap' and 'roughnessMap' textures.forEach((mapName) => {planeMaterial[mapName].wrapS = THREE.RepeatWrapping;planeMaterial[mapName].wrapT = THREE.RepeatWrapping;planeMaterial[mapName].repeat.set(repetition, repetition); });
这看起来应该更好。因为你所使用的纹理是无缝的,你不会注意到有重复发生的边缘的任何不连接。
纹理的加载实际上是一个异步操作。这意味着您的3D场景是在加载图像文件之前生成的。但是由于您一直在使用 requestAnimationFrame 不断地呈现场景,因此在本例中不会造成任何问题。如果不这样做,则需要使用回调或其他异步方法来管理加载顺序。
看代码 learning-threejs-07 by Engin Arslan ( @enginarslan ) on CodePen .
其他纹理地图
正如上一章所提到的,纹理不仅被用来定义表面的颜色,而且还用来定义它的其他性质。贴图的另一种方式是 凹凸贴图 。当被用作凹凸贴图时,纹理的亮度值会模拟一个高度的效果。
planeMaterial.bumpMap = texture;`
凹凸贴图也应该使用与颜色贴图相同的重复配置,所以在 textures 数组中包含它。
var textures = ['map', 'bumpMap'];`
使用凹凸贴图,加亮一个像素的值,相应的表面看起来会更高。但是凹凸贴图并没有改变表面,它只是在操纵光与表面的相互作用产生一种不均匀拓扑的错觉。现在的碰撞量看起来有点太大了。凹凸贴图在使用时效果很好。因此,让我们将 bumpScale 参数更改为更低的值,以获得更细微的效果。
planeMaterial.bumpScale = 0.01;`
注意,这种纹理在外观上有很大的不同。反射不再完美了,但却被完美地分割了,就像现实生活中那样。另一种可用于标准材料的 StandardMaterial 是 roughness map 。纹理贴图是一个粗糙的贴图,你可以使用给定图像的亮度值来控制反射的锐度。
planeMaterial.roughnessMap = texture; var textures = ['map', 'bumpMap', 'roughnessMap'];
根据这three.js文档,当与 environment map 一起使用时,标准材料的工作效果最好。环境图模拟了一个遥远的环境,反映了场景中的反射面。当你试图模拟物体的反射率时,这真的很有帮助。在三个环境地图。js以 立方体地图 的形式出现。多维数据集映射是一个在多维数据集内映射的场景的全景视图。一个立方体地图由6个独立的图像组成,这些图像对应一个立方体的每个面。由于在一个在线编辑器中加载6个模式图像将会有太多的工作,所以在本例中不会实际使用环境映射。但是为了使这个球面对象更加有趣,也可以添加一个粗糙度图。你会使用这个 纹理 ,但是是320px*320px数据URI。
创建一个名为 getMetalTexture 纹理的新函数。
function getMetalTexture() {var data = 'data:image/jpeg;base64,/...'; // paste your data URI inside the quotation marks.return data }
把它应用在球面上,比如 bumpMap 和 roughnessMap :
var sphereMaterial = sphere.material; var metalTexture = textureLoader.load(getMetalTexture());sphereMaterial.bumpMap = metalTexture; sphereMaterial.roughnessMap = metalTexture; sphereMaterial.bumpScale = 0.01; sphereMaterial.roughness = 0.75; sphereMaterial.metalness = 0.25;
看代码 learning-threejs-08 by Engin Arslan ( @enginarslan ) on CodePen .
封装起来
你几乎完成了!在这里,你只需要做一些小小的调整。可以看到这个场景文件的最终版本 in this Pen .
给灯光提供一种非白色的颜色。注意,如何实际使用CSS颜色值作为字符串来指定颜色:
var spotLight_01 = getSpotlight('rgb(145, 200, 255)', 1); var spotLight_02 = getSpotlight('rgb(255, 220, 180)', 1);
然后在灯光中添加一些微妙的随机动画,为场景添加一些生命。首先,将名称属性分配给灯光,这样您就可以使用 getObjectByName 方法在 update 函数中找到它们。
spotLight_01.name = 'spotLight_01'; spotLight_02.name = 'spotLight_02';
之后,在 update 函数里面,使用 Math.random() 函数创造动画,
var spotLight_01 = scene.getObjectByName('spotLight_01'); spotLight_01.intensity += (Math.random() - 0.5) * 0.15; spotLight_01.intensity = Math.abs(spotLight_01.intensity);var spotLight_02 = scene.getObjectByName('spotLight_02'); spotLight_02.intensity += (Math.random() - 0.5) * 0.05; spotLight_02.intensity = Math.abs(spotLight_02.intensity);
作为一个额外的奖励,在场景文件中,我已经包含了 OrbitControls 脚本。three.js摄像机,这意味着你可以把你的鼠标拖到场景上与摄像头互动!我也这样做了,这样场景就会随着窗口大小的变化而调整。为了方便起见,我使用外部脚本实现了这一点。
看代码 learning-threejs-final by Engin Arslan ( @enginarslan ) on CodePen .
现在,这个场景有点接近现实主义了。尽管如此,仍有许多缺失的部分。由于缺少反射和周围的光线,球体球太暗了。地面平面在看的角度看得太平了。球体的轮廓太完美了——它是CG(计算机图形)完美的。照明实际上并不像它所能的那样真实;它不会随着源的距离而衰减(失去强度)。你还应该添加粒子效果,相机动画,以及后期处理滤镜,如果你想要这样做的话。但这仍然是一个很好的例子来说明three.js的力量。以及你可以在浏览器中创建的图形质量。有关可以实现使用这个神奇的库的更多信息,你应该看看我的新课程 Lynda.com 的项目!
本文作者:佚名
来源:51CTO
相关文章:

jQuery元素内容操作的方法有多少种?
jQuery中操作元素内容的方法,主要包括html()方法、text()方法和val()方法。html()方法用于获取或设置元素的HTML内容,text()方法用于获取或设置元素的文本内容,val()方法用来获取或设置表单元素的value值。具体使用说明如表1所示。 表1 元素内…

获取SQLServer数据库中所有表
对于获取SQLSERVER数据库中所有表,首先第一步引有SQLDMO.dll 找到文件路径: C:\Program Files\Microsoft SQL Server\80\Tools\Binn\SQLDMO.dll 找到SQLDOM.DLL //在后台写方法 using System;using System.Collections.Generic;using System.Linq;using Syst…

刻意练习:LeetCode实战 -- Task24. 恢复二叉搜索树
背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法(Leetcode)刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式,即选择了五个知识点(数组、链表、字符串、树、贪心算法),每个知识点选择了…

Solaris下ftp配置(初稿-待补充)
1.自带ftp版本 Version wu-2.6.2 2.ftp启动与停止 启动并启用ftp: svcadm enable network/ftp 停止并禁用ftp: svcadm disable network/ftp 3.使某个系统用户无法使用ftp或者恢复使用ftp vi /etc/ftpd/ftpusers 向其中添加要禁止使用ftp的…

女生参加web前端培训可以吗
近几年,web前端被视为互联网行业最热门编程语言技术之一,越来越多的人开始想要学习web前端技术,其中不乏有一些女性学习,那么很多人就要问了,女生参加web前端培训可以吗?我们来看看下面的详细介绍吧。 女生参…

春节期间停止更新
非常抱歉地跟各位说一下,因为老家并没有拉宽带,所以春节期间无法进行更新。虽然说我可以背着笔记本回家,然后再到朋友处蹭一下网络。但想到一年365天,能回家的就那么几天,只是想好好陪陪父母,伴伴自己的老婆…

刻意练习:LeetCode实战 -- Task26.判断子序列
背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法(Leetcode)刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式,即选择了五个知识点(数组、链表、字符串、树、贪心算法),每个知识点选择了…

spring @component的作用
转自:https://www.cnblogs.com/lyjing/p/8427832.html1、controller 控制器(注入服务) 2、service 服务(注入dao) 3、repository dao(实现dao访问) 4、component (把普通pojo实例化到…

使用JavaScript变量需要注意哪些语法细节?
使用JavaScript变量需要注意哪些语法细节?JavaScript在很多地方经常会涉及到,尤其是JavaScript变量这方面,在使用变量时,还有一些值得注意的语法细节,下面进行详细讲解。 使用JavaScript变量需要注意哪些语法细节? 1. 更新变量的…
手把手教你搭建一个学习Python好看的 Jupyter 环境
又到摆脱重复工作,换个心情,然而并没有软用的时间了。这次,教大家如何搭建一个好看的jupyter环境。安装Jupyter先来展示一下我的环境python: 3.5.*macos: 10.12.4安装Jupyter的过程只需安装Anaconda即可。测试一下初始设置:jupyte…

刻意练习:LeetCode实战 -- Task27.分发饼干
背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法(Leetcode)刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式,即选择了五个知识点(数组、链表、字符串、树、贪心算法),每个知识点选择了…

祝贺《WCF邮件通信系统》在高阳市场研究汇编第五期发表
上次给公司的市场研究汇编投稿,只写了一个PPT格式的《WCF邮件通信系统》,编辑把它整理成了PDF格式的内容,感觉很好,所以我把PDF原文中的有关内容存储成了图片,发表在这里,庆贺一下。PDF原文地址:…

学软件测试有前途吗
学软件测试有前途吗?很多人都关心这个问题,最近几年,软件测试这个行业在很多企业都是非常刚需的,随着互联网的飞快发展,IT行业出现日新月异的变化,企业的大量需求,人才的严重匮乏,导致IT行业&a…

Active Directory 账号迁移配置介绍
首先介绍一下环境: 生产域环境: example.cn 测试域环境: fengdian.info 系统平台: 2K08 R2 林、域功能级别:Windows Server 2008 要求: 测试域环境“fengdian.info”同步生产域环境所有用户账号,实现测试环境和生产环境的基本统 一,方便功能测…

VIM命令快速记忆(转自杰哥)
因为自己也是个linuxer 熟练运用VIM是必须的,恰好学长杰哥对此有研究, 转来给大家分享。对此表达对杰哥的敬意。 有好东西分享给大家才能相互学习是吧。 要做个Linuxer,VIM的操作是必须就跟手指头盲打键盘那么熟练。 首先说下Vim的两种最常用…

刻意练习:LeetCode实战 -- Task28.跳跃游戏
背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法(Leetcode)刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式,即选择了五个知识点(数组、链表、字符串、树、贪心算法),每个知识点选择了…

类操作是什么意思?jQuery的类操作教程
类操作就是通过操作元素的类名进行元素样式操作,当元素样式比较复杂时,如果通过css()方法实现,需要在CSS里编写很长的代码,既不美观也不方便。而通过写一个类名,把类名加上或去掉就会显得很方便。下面通过代码演示类的…

刻意练习:LeetCode实战 -- Task29. 加油站
背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法(Leetcode)刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式,即选择了五个知识点(数组、链表、字符串、树、贪心算法),每个知识点选择了…

C#从SQL server数据库中读取l图片和存入图片
一、从图片中获得二进制值的基本方法:Image.Save 方法 (String, ImageFormat) 这会将保存 Image 写入指定的文件中指定的格式。 命名空间: System.Drawing 程序集: System.Drawing(位于 System.Drawing.dll) 语法: public void S…

linux下查看内存使用情况
在Linux下查看内存我们一般用free命令:[rootscs-2 tmp]# free total used free shared buffers cachedMem: 3266180 3250004 16176 0 110652 2668236-/ buffers/cache: 471116 2795064Swa…

现在转行学习UI设计好不好就业
UI设计是很多企业都会有需求的一个岗位,对于现在转行学习UI设计好不好就业这个问题,小编的回答是肯定的,最直接的方法就是上招聘信息,如果说招聘网站上UI设计师职位很少,那就说明UI设计行业已经差不多饱和了。 …

刻意练习:LeetCode实战 -- Task30.通配符匹配
背景 本篇图文是LSGO软件技术团队组织的 第二期基础算法(Leetcode)刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式,即选择了五个知识点(数组、链表、字符串、树、贪心算法),每个知识点选择了…

iOS 11 安全区域适配总结
2019独角兽企业重金招聘Python工程师标准>>> 导语:本文主要是对iOS 11下APP中tableView内容下移20pt或下移64pt的问题适配的一个总结。内容包括五个部分:问题的原因分析、adjustContentInset属性的计算方式、什么情况下的tableView会发生内容…

(广州)软件开发定制服务,工作流引擎 OA 库存管理系统
本人专注于工作流的研究设计同时提供软件开发定制服务,工作流引擎 OA系统 库存管理系统 如果有机会合作共事请联系:15817167503(本人在广州) QQ:1311663711 加时请注明软件定制 广州软件定制开发 转载于:https://www.cnblogs.com/…

Java类加载机制详解【java面试题】
Java类加载机制详解【java面试题】 (1)问题分析: Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允许用户…

C#获取文件的当前路径
1. System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName -获取模块的完整路径。 2.System.Environment.CurrentDirectory -获取和设置当前目录(该进程从中启动的目录)的完全限定目录。 3.System.IO.Directory.GetCurrentDirectory() &a…

c# ThreadPool 判断子线程全部执行完毕的四种方法
1、先来看看这个多线程编程多线程用于数据采集时,速度明显很快,下面是基本方法,把那个auto写成采集数据方法即可。using System;using System.Collections.Generic;using System.Text;using System.Threading;namespace ConsoleApplication1{…

腾讯精选练习 50 题(Leetcode)笔记 PDF下载!
昨天在知识星球中立了一个Flag,第一步采取的行动就是把以前刷的“腾讯精选练习 50 题”重新梳理一下,就有了今天这本170多页的小册子。 这本小册子即可以作为学习数据结构与算法课程的参考资料,也可以作为备考计算机类研究生的备考资料。希望…

Python培训:try-except语句与else子句联合使用处理可能出现的程序异常
异常处理的主要目的是防止因外部环境的变化导致程序产生无法控制的错误,而不是处理程序的设计错误。因此,将所有的代码都用try语句包含起来的做法是不推荐的,try语句应尽量只包含可能产生异常的代码。Python中try-except语句还可以与else子句…

Backup Exec 2012 备份和还原活动目录(非授权还原)
延续以上两篇,安装配置完毕后,开始进行备份操作。 环境一如上篇: DC: pdc1.fengdian.info BE2012 Svr: backup.fengdian.info 本例使用BE2012对活动目录进行备份和后续的还原操作,通过模拟误删除DC中的两个OU及其用户账号,使用先…