精华内容
下载资源
问答
  • 元素周期表

    千次阅读 2019-04-01 09:12:43
    每隔一个周期,宇宙的生长过程都会进行一次,这个过程的标志就是元素周期表的次序,一个宇宙和宇宙中的星体的生命过程 就是靠这些元素来标志的。。 虽然现行的元素周期表不是很齐全,但是也能够说明一些问题,...

     

            每隔一个周期,宇宙的生长过程都会进行一次,这个过程的标志就是元素周期表的次序,一个宇宙和宇宙中的星体的生命过程

            就是靠这些元素来标志的。。

     

            虽然现行的元素周期表不是很齐全,但是也能够说明一些问题,比如从氢元素成长到铁元素的过程,一岁一岁的成长,氢氦锂

            铍硼,按照元素周期表的次序来成长,从一个宇宙到一颗恒星,每隔一岁就是出现一种新元素,凭借这种元素在元素周期表中

            次序位置,来判断这颗星体或者这颗宇宙的寿命

     

           一颗恒星的真实年龄,并不是简单的看燃烧的时间长短,这里有一个隐秘的规律

           一颗太阳或者一个星体,到底是多少岁,要看这颗太阳在几岁的时候基因盘被破译,就是简单的讲,这颗太阳几岁生的孩子

           好像一个男人,长到25岁就生孩子,那么这个男人的年龄就是25岁,这个男人的最大力量也就是25岁,就算以后活到100岁

          也还是25岁,所以。。。。当老处女,是非常有价值的。。。

     

          你的身体,必须尽量维持不生孩子的状态,你的太阳就能够继续成长,直到79号元素,出现黄金星核,黄金星。。。。

          记住。。。宇宙的年龄和你的基因密码是否被破译有密切的关系,一旦你生孩子,你的基因密码就破译了,孩子的干细胞

          带完整的父母的基因密码,一旦这种基因密码被获取,你在宇宙中的恒星和小宇宙就再也无法成长了,永远定格在这个年龄

     

         晚婚晚育。。。。是一个长期的政策

    展开全文
  • 基于three.js的3D炫酷元素周期表

    千次阅读 2019-03-12 13:50:15
    最近在学习three.js在拿example中的项目练手,用了一整天的时间模仿了一个炫酷的元素周期表,在原有的基础上进行了一些改变。下面我会逐步讲解这个项目,算是加深理解,让大家提提意见。因为我未搭建个人服务器。截...
    最近在学习three.js在拿example中的项目练手,用了一整天的时间模仿了一个炫酷的元素周期表,在原有的基础上进行了一些改变。下面我会逐步讲解这个项目,算是加深理解,让大家提提意见。

    因为我未搭建个人服务器。截几张图给大家看看效果我做的效果(大部分是和原来的一样)。可能一部分人已经见过这个经典动画了。(这里是原项目地址:threejs.org/examples/cs…




    除了优化了原来的HELIX和GRID形式的的排版之外,我用另外一种方式也创建了两种自定义的排版方式。等会分享给大家。

    下面是GitHub仓库地址,文件很简单,就一个HTML文件。想自己手动实现或者拿去用的可以看一下。喜欢的给颗星星,不胜感激(请忽略代码中的注释哈哈)。

    github.com/yjhtry/proj…

    下面开始分析这个小项目

    技术栈
    1. HTML, CSS3, Javascript
    2. three.js, tween.js
    3. 三角函数
    实现原理
    1. 利用three.js提供的CSS3DRenderer渲染器,通过CSS3转换属性将分层3D转换应用于DOM元素。其实就是包装一下DOM元素,可以像操作three.js中Mesh对象一样去操作DOM元素。本质上还是利用CSS3的3D动画属性。这个项目就是操作转换后DOM元素的positionrotation的属性值来创建动画
    2. 使用轻量级动画库tween'补间'控制DOM元素positionrotation属性值的过渡。
    3. 确定不同排版的每一个DOM元素的positionrotation(部分排版需要确定rotation)的值,并将之保存在THREE.Object3D的子对象的position属性中(也可以是一组想象数组后面我会详细讲解),然后使用‘补间’将DOM元素的positionrotation像其保存的对应属性值过渡。
    话不多说,直接上代码。

    HTML结构

    <div id="container">
        	<!-- 选中菜单结构 start-->
        	<div id="menu">
        		<button id="table">TABLE</button>
        		<button id="sphere">SPHERE</button>
        		<button id="sphere2">SPHERE2</button>
        		<button id="plane">PLANE</button>
        		<button id="helix">HELIX</button>
        		<button id="grid">GRID</button>
        	</div>
        	<!-- end -->
        </div>复制代码

    HTML部分非常简单仅仅是一个包含六个控制转换的按钮的选择栏,下面看看他们的样式

            #menu {
    		position: absolute; 
    		z-index: 100;
    		width: 100%; 
    		bottom: 50px; 
    		text-align: center; 
    		font-size: 32px 
    	}
    
    	button {
    		border: none;
    		background-color: transparent; 
    		color: rgba( 127, 255, 255, 0.75 ); 
    		padding: 12px 24px; 
    		cursor: pointer; 
    		outline: 1px solid rgba( 127, 255, 255, 0.75 );
    	}
    
    	button:hover { 
    		background-color: rgba( 127, 255, 255, 0.5 ) 
    	}
    
    	button:active { 
    		background-color: rgba( 127, 255, 255, 0.75 ) 
    	}复制代码

    首先将选择栏绝对定位到窗口底部50px处,这里注意z-index: 100,将其层级设置为最高可以防止hover,click事件被其它元素拦截。然后清除button默认样式,并给它增加了:hover和:active伪类,使交互更生动。

    效果如下:


    然后是118个DOM元素的结构和样式,因为他们是在JavaScript代码中动态创建了,这里我单独写了一个元素的结构。

    <div class="element">
        <div class="number">1</div>		
        <div class="symbol">H</div>
        <div class="detail">Hydrogen<br>1.00794</div>
    </div>复制代码

    CSS样式

        .element {
    		width: 120px;
    		height: 160px;
    		cursor: default;
    		text-align: center;
    		border: 1px solid rgba( 127, 255, 255, 0.25 );
    		box-shadow: 0 0 12px rgba( 0, 255, 255, 0.5 );
    	}
    
    	.element:hover{ 
    		border: 1px solid rgba( 127, 255, 255, 0.75 ); 
    		box-shadow: 0 0 12px rgba( 0, 255, 255, 0.75 ); 
    	}
    
    	.element .number {
    		position: absolute; 
    		top: 20px; 
    		right: 20px; 
    		font-size: 12px; 
    		color: rgba( 127, 255, 255, 0.75 ); 
    	}
    
    	.element .symbol {
    		position: absolute; 
    		top: 40px; 
    		left: 0px; 
    		right: 0; 
    		font-size: 60px; 
    		font-weight: bold; 
    		color: rgba( 255, 255, 255, 0.75 ); 
    		text-shadow: 0 0 10px rgba( 0, 255, 255, 0.95 );
    	}
    
    	.element .detail {
    		position: absolute; 
    		left: 0; 
    		right: 0; 
    		bottom: 15px; 
    		font-size: 12px; 
    		color: rgba( 127, 255, 255, 0.75 ); 
    	}复制代码

    注意box-shadowtext-shadow。下面是效果图


    通过box-shadowtext-shadow使DOM元素产生了立体感。

    JavaScript部分

    首先定义了118个元素的数据储存结构,这里使用的是数组(因外数量较多,我只拿过来前二十五个,github代码中有完整数据)

        const table   = [
    			"H", "Hydrogen", "1.00794", 1, 1,
    			"He", "Helium", "4.002602", 18, 1,
    			"Li", "Lithium", "6.941", 1, 2,
    			"Be", "Beryllium", "9.012182", 2, 2,
    			"B", "Boron", "10.811", 13, 2,
    			"C", "Carbon", "12.0107", 14, 2,
    			"N", "Nitrogen", "14.0067", 15, 2,
    			"O", "Oxygen", "15.9994", 16, 2,
    			"F", "Fluorine", "18.9984032", 17, 2,
    			"Ne", "Neon", "20.1797", 18, 2,
    			"Na", "Sodium", "22.98976...", 1, 3,
    			"Mg", "Magnesium", "24.305", 2, 3,
    			"Al", "Aluminium", "26.9815386", 13, 3,
    			"Si", "Silicon", "28.0855", 14, 3,
    			"P", "Phosphorus", "30.973762", 15, 3,
    			"S", "Sulfur", "32.065", 16, 3,
    			"Cl", "Chlorine", "35.453", 17, 3,
    			"Ar", "Argon", "39.948", 18, 3,
    			"K", "Potassium", "39.948", 1, 4,
    			"Ca", "Calcium", "40.078", 2, 4,
    			"Sc", "Scandium", "44.955912", 3, 4,
    			"Ti", "Titanium", "47.867", 4, 4,
    			"V", "Vanadium", "50.9415", 5, 4,
    			"Cr", "Chromium", "51.9961", 6, 4,
    			"Mn", "Manganese", "54.938045", 7, 4
                ]复制代码

    先来分析一下这个数据结构

    "H", "Hydrogen", "1.00794", 1, 1,复制代码

    一共118个元素,每个元素在table数组定义了五条数据分别是符号(symbol),英文全称,质量(detail),元素在表格排版中所在的列(column)和行(row)这两个数据在创建表格盘版的时我会说明使用方法。

    		let scene, camera, renderer, controls;
    		const objects = [];
    		const targets = { 
    			grid: [],
    			helix: [], 
    			table: [], 
    			sphere: [] 
    		};复制代码

    这里定义了一些全局变量。scene,camera,renderer是three.js的环境对象,相机及渲染器。controls是three.js提供控制库,用于与用户交互,很简单。objects用于存储118个DOM元素。targets对象包含四个数组类型的属性值,用来保存存有不同排版目标位置的Object3D子对象。

    元素的创建以及动画的控制由init函数执行,下面主要的篇幅用于将它

    function init() {
    
        const felidView   = 40;
        const width       = window.innerWidth;
        const height      = window.innerHeight;
        const aspect      = width / height;
        const nearPlane   = 1;
        const farPlane    = 10000;
        const WebGLoutput = document.getElementById('container');
    
        scene    = new THREE.Scene();
        camera   = new THREE.PerspectiveCamera( felidView, aspect, nearPlane, farPlane );
        camera.position.z = 3000;
    			
        renderer = new THREE.CSS3DRenderer();
        renderer.setSize( width, height );
        renderer.domElement.style.position = 'absolute';
        WebGLoutput.appendChild( renderer.domElement );
    
     复制代码

    (可能我的代码缩进比较奇怪,我主要是为了趣味性哈哈)这段代码创建了three.js的三个基本组件,场景,相机(perspectiveCamera),渲染器。这里需要注意的是,这里的far-clipping-plane设置 的值比较大,自己做的话可以设置小一些,降低性能损耗。注意这里采用的是CSS3D渲染器。

    透视相机的视锥图



    平面之间的部分被称为视锥,简单点来说就是相机的拍摄区域。图上的fov(视场)是相机的第一个参数,决定了相机拍摄范围的大小,类似于人眼的横向视域(大于180deg了吧)。aspect参数控制相机投影平面的宽高比(一般是canvas的宽高比)这个主要是为了防止图片变形,因为投影平面上的图像最终会通过canvas显示。注意使用CSS3D渲染器时,显示视口是div元素。

    let i   = 0;
    let len = table.length;
    
    for ( ; i < len; i += 5 ) {
    
        const element      		  = document.createElement('div');
        element.className 		  = 'element';
        element.style.backgroundColor = `rgba( 0, 127, 127, ${ Math.random() * 0.5 + 0.25 } )`;
    			
        const number        = document.createElement('div');
        number.className    = 'number';number.textContent  = i / 5 + 1;
        element.appendChild( number );
    			
        const symbol        = document.createElement('div');
        symbol.className    = 'symbol';
        symbol.textContent  = table[ i ];
        element.appendChild( symbol );
    				
        const detail 	= document.createElement('div');
        detail.className 	= 'detail';
        detail.innerHTML 	= `${ table[ i + 1 ] }<br/>${ table[ i + 2 ] }`;
        element.appendChild( detail );
    
        const object 	= new THREE.CSS3DObject( element );
        object.position.x   = Math.random() * 4000 - 2000;
        object.position.y   = Math.random() * 4000 - 2000;
        object.position.z   = Math.random() * 4000 - 2000;
    
        scene.add( object );
        objects.push( object );
    
    		}复制代码

     这段代码创建了显示周期表元素的HTML结构,并将每一个DOM元素使用THREE.CSS3DObject类包装成3D对象。然后随机分配对象的位置在( -2000, 2000 )这个区间内。最后把对象添加场景中,并放入objects数组中保存,为在后面的动画做准备。

    上面的已经完成了118元素的创建到随机分配位置显示的部分。下面开始创建集中排版需要的数据。

    table排版

    function createTableVertices() {
    
        let i = 0;
    
        for ( ; i < len; i += 5 ) {
    
        const object      = new THREE.Object3D();
    
        // [ clumn 18 ]
        object.position.x = table[ i  + 3 ] * 140 - 1260;
        object.position.y = -table[ i + 4 ] * 180 + 1000;
        object.position.z = 0;
    
        targets.table.push( object );
    
    	}
    }复制代码

    这个排版比较简单,使用table数组中每个元素的第四个数据(column)和第五个数据(row)直接就可以的到每个元素对应的table排版的位置信息,然后将它们赋值给对应的object.position属性中保存(这个不一定非要这样,只要是THREE.Vector3类型的数据就可以)。最后将对象保存到对应的数组中,以便在动画中使用。

    shpere排版

    const objLength = objects.length;
    
    function createSphereVertices() {
    
    	let i = 0;
    	const vector  = new THREE.Vector3();
    
    	for ( ; i < objLength; ++i ) {
    
    	    let phi   = Math.acos( -1 + ( 2  * i ) / objLength );
    	    let theta = Math.sqrt( objLength * Math.PI ) * phi;
    	    const object      = new THREE.Object3D();
    
    	    object.position.x =  800 * Math.cos( theta ) * Math.sin( phi );
    	    object.position.y =  800 * Math.sin( theta ) * Math.sin( phi );
    	    object.position.z = -800 * Math.cos( phi );
    
    	    // rotation object 
    					
    	    vector.copy( object.position ).multiplyScalar( 2 );
    	    object.lookAt( vector );
    	    targets.sphere.push( object );
    	}
    
    }复制代码

    说实话这段代码理解的不是很到位总感觉原作者的算法复杂化了,代码贴出来请大佬分析一下。后面我自己用别的方法实现了一种‘圆’不是很好看,但是很好理解。我先说一下vector这个变量的作用,它用来作为'目标位置',使用object.lookAt( vector )这个方法让这个位置的对象看向vector这一点所在的方向,在three.js的内部会将object旋转以‘看向vector’。将得到旋转的值并保存在object对象的rotation属性中,在动画中将元素对象的rotation属性过渡为对应的值,使其旋转。

     helix排版

    function createHelixVertices() {
    
            let i = 0;
    	const vector = new THREE.Vector3();
    
    	for ( ; i < objLength; ++i ) {
    
    	    let phi = i * 0.213 + Math.PI;
    
    	    const object = new THREE.Object3D();
    
    	    object.position.x = 800  * Math.sin( phi );
    	    object.position.y = -( i * 8 ) + 450;
    	    object.position.z = 800  * Math.cos( phi + Math.PI );
    
    	    object.scale.set( 1.1, 1.1, 1.1 );
    
    	    vector.x = object.position.x * 2;
    	    vector.y = object.position.y;
    	    vector.z = object.position.z * 2;
    
    	    object.lookAt( vector );
    	    targets.helix.push( object );
    
    	}
    
    }复制代码

    这个排版很好理解,首先看一下Y轴采取的是在Y方向上逐个下降的算法。如果X,Z轴不做处理那就是延Y轴的排成一排。然后我讲一下这个0.213是怎么取的



    因为总共118个元素,如果想让这些元素排列成圆的用上图的的两种函数就可以,我使用的是正弦函数,有图可以看出使118个元素排成四个圆只需要给每一个元素一个对应的角度,再通过Math.sin( angle )或Math.cos( angle )计算后,得到四组周期性的值,元素就会呈圆形排列。通过计算公式4 * Math.PI * 2 / 118得出0.213,这样每一个元素在周期表中的位置(这里是从0开始。)乘以0.213,得到与其对应的角度。使用这个角度通过正玄余玄函数得到在圆中的位置。

    grid排版

    function createGridVertices() {
    
    	let i = 0;
    
    	for ( ; i < objLength; ++i ) {
    
    	    const object      = new THREE.Object3D();
    
    	    object.position.x =  360  * ( i   % 5) - 800;
    	    object.position.y = -360  * ( ( i /  5 >> 0 ) % 5 ) + 700;
    	    object.position.z = -700  * ( i   / 25 >> 0 );
    
    	    targets.grid.push( object );
    
    	}
    }复制代码

    网格布局使用的主要是分组的思想,这是个5 * 5的网格。在X轴上的布局采用求余可以使元素分为五列,在Y轴上先除以5然后取整(这里我喜欢使用>>位操作符,和Math.floor一个效果)。这样做是为元素分行,然后求余分列。当一个平面内5 * 5排满后,在Z轴上判断元素属于哪一面。

    上面四种布局是原来的经典布局,原作者使用的是将每个元素将要过低的位置保存起来。还有两种布局是我通过这种思想延伸的,比较偷懒,也很简单。先看一下是如何使用tween动画库来完成元素位置的过渡。

    const gridBtn    = document.getElementById('grid');
    const tableBtn   = document.getElementById('table');
    const helixBtn   = document.getElementById('helix');
    const sphereBtn  = document.getElementById('sphere');
    
    gridBtn.addEventListener(    'click', function() { transform( targets.grid,   2000 )},   false );
    tableBtn.addEventListener(   'click', function() { transform( targets.table,  2000 ) },  false );
    helixBtn.addEventListener(   'click', function() { transform( targets.helix,  2000 ) },  false );
    sphereBtn.addEventListener(  'click', function() { transform( targets.sphere, 2000 ) },  false );复制代码

    function transform( targets, duration ) {
    
            TWEEN.removeAll();
    
    	for ( let i = 0; i < objLength; ++i ) {
    
    	let object = objects[ i ];
    	let target = targets[ i ];
    
    	new TWEEN.Tween( object.position )
    	    .to( { x: target.position.x, y: target.position.y, z: target.position.z },
                                                    Math.random() * duration + duration )
    	    .easing( TWEEN.Easing.Exponential.InOut )
    	    .start();
    
    
    	    new TWEEN.Tween( object.rotation )
    	    .to( { x: target.rotation.x, y: target.rotation.y, z: target.rotation.z },
                                                    Math.random() * duration + duration )
    	    .easing( TWEEN.Easing.Exponential.InOut )
    	    .start();
    
    	}
    
    	// 这个补间用来在位置与旋转补间同步执行,通过onUpdate在每次更新数据后渲染scene和camera
    	new TWEEN.Tween( {} )
    	    .to( {}, duration * 2 )
    	    .onUpdate( render )
    	    .start();
    
    }复制代码

    从事件绑定的回调可以看出,触发不同的排版时,我们传入对应的数据。然后将数据取出通过tween.js过渡这些数据产生动画。这里有tween.js使用的详细介绍github.com/tweenjs/twe…

    循环之外的的这个‘补间’是用来在动画过渡期间执行渲染页面函数的。如下

    function render() {
    
            renderer.render( scene, camera );
    
    }复制代码

    onWindowResize函数用于缩放页面时更新相机参数,场景大小以及重新渲染画面

    animation通过requestAnimationFrame这个动画神器刷新‘所有补间数据’,更新trackball控制器

    function onWindowResize() {
    
    	camera.aspect = window.innerWidth / window.innerHeight
    	camera.updateProjectionMatrix();
    
    	renderer.setSize( window.innerWidth, window.innerHeight );
    	render();
    
    }
    		
    function animation() {
    
            TWEEN.update();
            controls.update();
    	requestAnimationFrame( animation );	
    }复制代码

    最后说一下我拓展的两种‘投机取巧的排版’

    const sphere2Btn = document.getElementById('sphere2');
    sphere2Btn.addEventListener( 'click', function() { transformSphere2( 2000 ) },  false );
    
    function transformSphere2(duration) {
    
            TWEEN.removeAll();
    
    	const sphereGeom = new THREE.SphereGeometry( 800, 12, 11 );
    	const vertices = sphereGeom.vertices;
    	const vector = new THREE.Vector3();
    
    	for ( let i = 0; i < objLength; ++i ) {
    
    		const target = new THREE.Object3D();
    
    		target.position.copy(vertices[i]);
    		vector.copy( target.position ).multiplyScalar( 2 );
    		target.lookAt( vector );
    
    		let object = objects[ i ];
    
    		new TWEEN.Tween( object.position )
    			.to( vertices[i],
    			Math.random() * duration + duration )
    			.easing( TWEEN.Easing.Exponential.InOut )
    			.start();
    
    		new TWEEN.Tween( object.rotation )
    			.to( { x: target.rotation.x, y: target.rotation.y, z: target.rotation.z }, Math.random() * duration + duration )
    			.easing( TWEEN.Easing.Exponential.InOut )
    			.start();
    
    	}
    
    		new TWEEN.Tween( this )
    			.to( {}, duration * 2 )
    			.onUpdate( render )
    			.start();
    
    }复制代码

    整个动画的原理: 为每个元素创建一个目标位置,这些位置组合产生的排版就是元素最终的排版,通过‘补间’过渡位置的转换。所以我直接使用three.js内置的几何体,使用它的vertices属性中的位置作为目标位置(有一点限制,vertices中顶点(位置)的数目最好接近118)。这样通过内置的几何体我们可以不进行数学计算,直接创建一些有意思的排版。

    写到这里讲的也差不多了,我是一个刚入门前端的菜鸟,欢迎大家的指点和批评!喜欢的同学可以给个赞哦!


    转载于:https://juejin.im/post/5c8650676fb9a049dc031483

    展开全文
  • TWaver版3D化学元素周期表

    千次阅读 2014-07-14 10:12:53
    很早就有人做3D网页版的化学元素周期表了,酷炫效果和新鲜技巧一度被众多粉丝奉为神明,争相研究和效仿。甚至有人放弃一切扑向这颗蜡烛,不由总是想到那个OPPO广告女主角拽拽的鄙视道:“辞职去旅游!你敢吗?” ...

    很早就有人做3D网页版的化学元素周期表了,酷炫效果和新鲜技巧一度被众多粉丝奉为神明,争相研究和效仿。甚至有人放弃一切扑向这颗蜡烛,不由总是想到那个OPPO广告女主角拽拽的鄙视道:“辞职去旅游!你敢吗?”

    俺不敢,不过用TWaver做一个也没用几个小时。所以就老在想:不就旅个游么,至于嘛?

    这个3D元素周期表做了一些改进:卡片上增加了汉字及拼音读音,原因你懂得——各位程序猿没几个敢大声读这些汉字的。还好每个字的主要部分还大都认识,多少可以小声蒙一下,加上拼音就少了许多尴尬。另外在形状布局和特效上也丰富了一点,具体可以看下方视频连接。

    技术上来说,用TWaver 3D来做的思路略有不同。最开始网上这个程序是使用HTML5、CSS3、WebGL、THREE.js、TWEEN.js等技术做的。使用TWaver就不用这么麻烦了,直接一个mono.js就差不多搞定了。技术上依旧是WebGL+js,但没有使用CSS3和其他框架。效果和效率都很好。

    实现上难度不大,大概思路如下:

    1. 用数组定义好化学元素周期表的数据。包括编号、汉字、拼音、数值、英文等等。然后在内存中动态生成每个元素对应的图片卡,并转成base64格式的内存url字符串。注意图片的格式、透明度、颜色等细节;
    2. 为每个化学元素new一个3D立方体,并把内存图片贴图到立方体正面。立方体的厚度0就行了,其他面都透明即可;
    3. 监听鼠标事件。当鼠标over每个物体时,让立方体发光;点击物体时,让立方体动画反转一圈;
    4. 计算好几个形状布局对应的空间坐标,并事先记录到每个立方体的client属性表中。例如:node.setClient(‘grid’,{x:100,y:340});
    5. 放几个按钮,每个按钮点击后,让所有的立方体到对应的形状的位置上去,同时启用动画机制;

    实际代码中,也要留意一些注意事项:

    1. 动画:当第一次动画尚未执行完毕,用户又点击其他按钮执行新动画时,需要先判断当前有无正在运行的动画,并及时让动画停止。同时还要判断是否需要把数值恢复成初始值或动画正常结束所设定的值。这里如不仔细处理,可能会导致动画将卡片的位置、角度错乱。
    2. 布局:球形、螺旋、随机等空间点其实都很好计算。尤其球形布局,开始大家可能会去寻找“在一个半径为r的球形表面均匀散布n个点,求每个点的坐标?”这样的题目。这样就把问题复杂化了。因为简单的视觉布局并不需要特别严谨的位置数值,所以大致把球进行径向和横向切片进行数值插入即可;
    3. 贴图:最开始,我们可能会觉得程序是使用了100张小图片进行贴图。但实际上,由于每个卡片的区别仅仅是文字,所以完全可以在内存动态生成。这样速度快节省了网络下载图片的时间以及维护图片的麻烦,同时文字和图片等样式也更容易控制。这也都是HTML5的canvas技术为大家带来的好处。
    4. 物体朝向:在布局过程中,每个卡片的旋转和朝向是一个要考虑的问题。例如球形,每个卡片要面向球形圆心发射线的外方向,螺旋形卡片则朝向水平外方向,等等。计算这些坐标和角度需要很多数学运算,光是求坐标系和直角坐标系转换之类的就够大家忙活一阵子了。而用TWaver就简单了:每个物体直接lookAt一个点就行了。例如球形卡片,每帧动画只要执行:node.lookAt(0,0,0)就行了,对吗?还不完全对。这样lookAt到中心点,不就“屁股”朝外了吗?用户看到的字是卡片的背面,是反的。要解决也简单,应当让它lookAt自己坐标两倍的地方,也就是圆心放射线的外面:node.lookAt(x*2, y*2, z*2),这样就对了。
    5. 发光。鼠标over每个物体,都会看到发光。而鼠标over在光晕位置,却不会触发over事件。这是怎么做到的呢?其实也是小技俩,大家可以看看程序,自己研究吧。

    生成内存图片代码片段:

    1 var url = canvas.toDataURL("image/png");
    2 node.setStyle('front.m.texture.image',url);

    球形布局坐标计算代码片段:

    1 var radius=1000;
    2 var phi = Math.acos( -1 + ( 2 * index ) / total );
    3 var theta = Math.sqrt( total * Math.PI ) * phi;
    4 var x = radius * Math.cos( theta ) * Math.sin( phi );
    5 var y = radius * Math.sin( theta ) * Math.sin( phi );
    6 var z = radius * Math.cos( phi );

    程序和源代码都已经在TWaver的MONO DESIGN产品中,感兴趣的朋友可以登录在线网址www.mono-design.cn或下载产品包。赶紧试试吧!







    展开全文
  • 问题描述:设计一个算法从顺序中删除重复的元素,并使剩余元素间的相对次序保持不变。 例如:原顺序为{4 2 8 4 2 1 2 1 3 5 2},执行该算法后,顺序为:{4 2 8 1 3 5}。 另外,顺序的初始值通过调用算法...

    问题描述:设计一个算法从顺序表中删除重复的元素,并使剩余元素间的相对次序保持不变。
    例如:原顺序表为{4 2 8 4 2 1 2 1 3 5 2},执行该算法后,顺序表为:{4 2 8 1 3 5}。
    另外,顺序表的初始值通过调用算法
    initRandomize(int *arr, int n, int min, int max)产生。

    关于rand(),srand()相关基础知识参考以下内容:
    https://blog.csdn.net/chikey/article/details/66970397
    一、rand()

    rand()函数用来产生随机数,但是,rand()的内部实现是用线性同余法实现的,是伪随机数,由于周期较长,因此在一定范围内可以看成是随机的。

    rand()会返回一个范围在0到RAND_MAX(32767)之间的伪随机数(整数)。

    在调用rand()函数之前,可以使用srand()函数设置随机数种子,如果没有设置随机数种子,rand()函数在调用时,自动设计随机数种子为1。随机种子相同,每次产生的随机数也会相同。

    rand()函数需要的头文件是:<stdlib.h>

    rand()函数原型:int rand(void);

    使用rand()函数产生1-100以内的随机整数:int number1 = rand() % 100+1;

    二、srand()

    srand()函数需要的头文件仍然是:<stdlib.h>

    srand()函数原型:void srand (usigned int seed);

    srand()用来设置rand()产生随机数时的随机数种子。参数seed是整数,通常可以利用time(0)或geypid(0)的返回值作为seed。

    使用rand()和srand()产生1-100以内的随机整数:

    srand(time(0));
    
    int number1 = rand() % 100+1;
    

    三、使用rand()和srand()产生指定范围内的随机整数的方法

    “模除+加法”的方法

    因为,对于任意数,0<=rand()%(n-m+1)<=n-m

    因此,0+m<=rand()%(n-m+1)+m<=n-m+m

    因此,如要产生[m,n]范围内的随机数num,可用:

    int num=rand()%(n-m+1)+m;

    其中的rand()%(n-m+1)+m算是一个公式,记录一下方便以后查阅。

    比如产生10~30的随机整数:

    srand(time(0));

    int a = rand() % (21)+10;


    作者:chikey
    来源:CSDN
    原文:https://blog.csdn.net/chikey/article/details/66970397

    以下为随机数生成函数:

    #include <time.h>
    void initRandomize(int *arr, int n, int min, int max)
    {
        int i = 0;
        srand(time(0));  	/*设置种子,并生成伪随机序列*/
        for (i = 0; i < n; ++i) {
            arr[i] = rand()% (max - min + 1) + min;  /*得到从[min, max]之间的随机数*/
            //printf("%d ", arr[i]);
        }
        //printf("\n\n");
    }
    

    以下是完整代码
    包含了四个自定义删除相同数的函数
    基于《数据结构》严蔚敏版

    #include <stdio.h> 
    #include <stdlib.h>
    #define OK 1
    #define ERROR 0
    #define OVERFLOW -1
    #define LIST_INIT_SIZE 100 	
    #define LISTINCREMENT  10 	
    typedef int ElemType;	
    typedef int Status; 
    
    typedef struct 
    {
       ElemType     *elem; 								
       int 			length;		  				
       int 			listsize; 		
    } SqList;
    
    // 算法2.3  初始化 
    Status InitList_Sq(SqList &L) 
    {  
      L.elem = (ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));
      if (!L.elem) exit(OVERFLOW);        // 存储分配失败
      L.length = 0;                  
      L.listsize = LIST_INIT_SIZE;   
      return OK;
    }
    
    // 算法2.4  插入 
    Status ListInsert_Sq(SqList &L, int i, ElemType e) 
    {  
      ElemType *p, *q;
      if (i < 1 || i > L.length+1) 
      {// i的合法值为1≤i≤ListLength_Sq(L)+1
      	return ERROR;  
      }
      
      if (L.length >= L.listsize) {// 当前存储空间已满,增加容量
        ElemType *newbase = (ElemType *)realloc(L.elem,
                      (L.listsize+LISTINCREMENT)*sizeof (ElemType));
        if (!newbase) return ERROR;   								
        L.elem = newbase;             							
        L.listsize += LISTINCREMENT;  							
      } 
      q = &(L.elem[i-1]);   							
      for (p = &(L.elem[L.length-1]); p>=q; --p) 
      	*(p+1) = *p;									                              											
      *q = e;      
      ++L.length;   
      return OK;
    } 
    
    //算法2.5 删除 
    Status ListDelete_Sq(SqList &L,int i, ElemType &e)
    {
    	ElemType *p,*q;
    	if(i<1||i>L.length)  return ERROR;
    	p=L.elem+i-1; //p=&(L.elem[i-1]);
    	e=*p;
    	q=L.elem+L.length-1;//最后一个元素的位置
    	for(++p;p<=q;p++)
    		*(p-1)=*p;
    	--L.length;
    }
    
    //销毁顺序表操作 
    Status DestroyList(SqList &L)
    { 
       free(L.elem);
       L.elem=NULL;
       L.length=0;
       L.listsize=0;
       return OK;
    
    }
    
    #include <time.h>
    void initRandomize(int *arr, int n, int min, int max)
    {
        int i = 0;
        srand(time(0));  			/*设置种子,并生成伪随机序列*/
        for (i = 0; i < n; ++i) {
            arr[i] = rand()% (max - min + 1) + min;  /*得到从[min, max]之间的随机数*/
            //printf("%d ", arr[i]);
        }
        //printf("\n\n");
    }
    
    void ListPrint(SqList &L)
    {
    	for(int i=1; i<= L.length; i++)
    		printf("%d ", L.elem[i-1]);
    	printf("\n");
    } 
    
    int listdelete1(SqList *L)  //用这个方法结果是错的,暂时没找到原因 
    {							//原因找到:删除完一个元素后,j++,导致更新到原来删除位置的元素没有判断 
    	int *p,*q;				//解决方法:删除完就不要j++了 ,没有进入删除的再j++ 
    	int i,j;
    	for(i=0;i<L->length;i++)
    	{
    		for(j=i+1;j<L->length;)
    		{
    		if(L->elem[i]==L->elem[j])
    		{ 		
    		     //p=L->elem+j; 
    		    p=&(L->elem[j]);  			
    			//q=L->elem+L->length-1; 
    			q=&L->elem[L->length-1] ; 
    			for(++p;p<=q;++p)
    			*(p-1)=*p;
    			--L->length;
    		}
    		else j++; 
    		}			
    	}
    	return OK;   
    }
    
    
    int listdelete2(SqList *L)  //相比与listdelete1少用了两个指针 ,思路是一样的 
    {
    	int i,j;
    	for(i=0;i<L->length;i++)
    	{
    		for(j=i+1;j<L->length;)
    		{
    		if(L->elem[i]==L->elem[j])
    		{
    			for(int m=j+1;m<L->length;m++)
    			L->elem[m-1]=L->elem[m];
    			L->length--; 
    		}
    		else j++;	
    		}			
    	}
    	return OK;   
    }
    
    void listdelete3(SqList *L)//和之前相比,减少了移动,但开辟了新的空间,也变得繁琐了 
    {
    	int i,j,k=1;
    	int a[50]={L->elem[0]};
    	for(j=1;j<L->length;j++)
    	{
    		int flag=1;
    		for(i=0;i<k;i++)
    		{
    			if(a[i]==L->elem[j])
    			{
    				flag=0;
    				break;
    			}			 
    		}
    		if(flag)
    		{
    			L->elem[k]=L->elem[j];
    			a[k++]=L->elem[j];		
    		}	
    	}
    	L->length=k;
    }
    
    void ListDelete_same(SqList *l)   //和listdelete3比不用另外分配空间 
    {								  //这四个删除算法中的最优解 
        int j=1,i=0,len=1;
        while(j<l->length)
        {
            for(i=0;i<len;++i)//和已经进入的不重复集合的元素进行比较 
            {
                if(l->elem[i]==l->elem[j])
                    break;
        	}
            if(i==len)//意味着上面的for循环是正常结束的,所有没重复,可以进入不重复集合 
                l->elem[len++]=l->elem[j++];
            else
                j++;//说明出现重复元素,j++,判断下一个元素 
        }
        l->length=len;//最后不充分数组的长度就是,进入该数组的个数 
    }
    
    const int N=200;
    int	main()
    {
    	int A[N];
    	SqList	List;	
    	InitList_Sq(List);
    	
    	initRandomize(&A[0],N,1,10); //生成50个1~10的随机数 
    	for(int i=1; i<=N; i++)
    		ListInsert_Sq(List,i,A[i-1]);
    			
    	printf("开始时元素序列为:\n");
    	ListPrint(List);
    	/* 
    	
    	listdelete1(&List);
        ListPrint(List);
    
        listdelete2(&List);
        ListPrint(List);
        
        listdelete3(&List);
        ListPrint(List);
        
        */
        ListDelete_same(&List);
    	printf("\n删除后的顺序表L为:");    
        ListPrint(List);
    	if(DestroyList(List)) 
    	printf("\n成功释放顺序表L");
    			
        getchar();
    }
    
    
    展开全文
  • 元素——答题

    万次阅读 多人点赞 2019-09-19 14:10:44
    元素——答题 微元素每日任务,答题
  • UML核心元素

    千次阅读 2014-03-10 10:04:37
    需求分析人员不能一开始就加入自己的主观判断,假设了业务在计算机里的实现方式,而没有真正去理解客户的实际业务。 因此,在初始需求阶段,请必须使用业务主角。牢记业务主角是客户实际业务里的参与者,没有...
  • IOS基本界面元素:  要在屏幕上显示内容首先要创建一个窗口承载内容,要创建一个窗口,需要一个边框(frame),含有边框信息的底层 结构就CGRect。每个能够在屏幕上显示自己的对象都有一个边框,定义了他的显示...
  • Redis源码解析——双向链表

    千次阅读 2016-12-09 00:03:38
    相对于之前介绍的字典和SDS字符串库,Redis的双向链表库则是非常标准的、教科书般简单...因为是双向链表,所以其基本元素应该有一个指向前一个节点的指针和一个指向后一个节点的指针,还有一个记录节点值的空间 t...
  • 本节将Activity的生命周期分为两部分内容,一部分是典型情况下的生命周期,另一部分是异常情况下的生命周期。所谓典型情况下的生命周期,是指在有用户参与的情况下,Activity所经过的生命周期的改变;而异常情况下的...
  • 对Vue生命周期钩子函数的理解

    千次阅读 2018-11-08 17:26:39
    对Vue生命周期钩子函数的理解 实例创建之后,初始化事件和生命周期,而后触发beforeCreate。beforeCreate,当前实例创建之前,很少操作,一般用于加载动画,比如创建一个旋转动画。created表示当前实例创建完成,...
  • 计算机常用算法对照整理

    千次阅读 2017-07-26 10:58:01
    crosstab query 交叉查询 (for database) CRTP (curiously recurring template pattern) CTS (common type system)通用类型系统 cube 多维数据集 (for database) cursor 光标 cursor 游标 (for database...
  • 简单了解软件开发的生命周期和流程、思想

    千次阅读 多人点赞 2020-05-24 16:20:42
    都已经入行软件开发了,如果不了解软件开发的生命周期和流程、思想怎么办?那岂不是被面试官猴戏吗?
  • JBPM4 常用结构及其说明

    万次阅读 热门讨论 2014-06-16 17:31:53
    首先我想说,这不一篇原创博文。这里设置成原创,主要是为了分享,因为它对于jbpm的初学者,真的值得一看。原作者的博文地址并没有查到,我是在... 本文从结构、操作时的变化以及jbpm4.4各个包的作用来介绍jbpm的。
  • Android中Activity生命周期

    千次阅读 2018-03-31 16:41:54
    正常的情况下Activity的生命周期 onCreate():从字面意思我们也能看出这是在Activity 正在被创建的时候执行的一个方法,也是Activity生命周期的第一个方法。我们一般都在这个方法中执行初始化工作...onStart():...
  • 这是我们系统级编程SSD6的大作业,问题是一个基于优先级抢占和周期调度的进程调度算法的模拟程序。虽然并不太熟悉,没有读过如Linux,Windows,等等操作系统的书籍,在不断的讨论和查阅中也简单地向操作系统底层进程...
  • Activity的生命周期和作用

    千次阅读 2015-02-04 15:15:21
    条件语句中第一个判断是检查请求是否成功,成功的话,resultCode的值为RESULT_OK,第二个判断请求是否为已知的请求,本例使用和startActivityResult同样的参数值来和requestCode做比较。如果两个条件都满足,你就可以...
  • 数据结构-顺序基本操作的实现(含全部代码)

    万次阅读 多人点赞 2018-09-13 22:14:57
    今天起开始编写数据结构中的各种数据结构及其算法的实现。 主要依据严蔚敏版数据结构教材以及王道数据结构...L,int n) 参数:顺序L,顺序长度n 功能:创建长度为的顺序 时间复杂度:O(n) InitList(SqList &...
  • 1.NSDictionary底层是哈希,下面会介绍具体是用拉链法还是开放定址法线性探测来解决冲突?由于Apple给的查询复杂度可以快至O(1),那么为什么是O(1),底层是如何通过空间换取时间的? 2.NSArray是线性连续内存,这...
  • newScheduledThreadPool 创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。 使用示例: 2. 使用ThreadPoolExecutor这个类自定义创建线程池 二.ThreadLocal 三.中断线程 1.线程执行完毕会...
  • 先附一张官网上的vue实例的生命周期图,每个Vue实例在被创建的时候都需要经过一系列的初始化过程,例如需要设置数据监听,编译模板,将实例挂载到DOM并在数据变化时更新DOM等。同时在这个过程中也会运行一些叫做生命...
  • 计算机组成原理实验2---单周期CPU

    千次阅读 2018-09-25 22:08:06
    设计一个单周期CPU,该CPU至少能实现以下指令功能操作。 必须写一段测试用的汇编程序,而且必须包含所要求的所有指令,slti指令必须检查两种情况:“小于”和“大于等于”;beq、bne:“不等”和“等”。这段汇编...
  • 论以建筑全生命周期管理建设公司大数据平台(初稿) 李万鸿 2018 一.引言大数据、云计算、物联网、人工智能、移动技术的迅猛发展,把世界带入崭新的时代,在大数据时代背景下,传统的房地产评估行业发展思路和战略...
  • 秒懂,Java 注解 (Annotation)你可以这样学

    万次阅读 多人点赞 2017-06-27 21:48:30
    上面的代码中,我们指定 TestAnnotation 可以在程序运行周期被获取到,因此它的生命周期非常的长。 @Documented 顾名思义,这个元注解肯定是和文档有关。它的作用是能够将注解中的元素包含到 Javadoc 中去。 @...
  • ASP.NET的网页代码模型及生命周期

    千次阅读 2009-11-11 23:57:00
    第4章 ASP.NET的网页代码模型及生命周期从本章开始,就进入了ASP.NET应用程序开发的世界。在了解了C#的结构,以及面向对象的概念后,就可以从面向对象的思想开发ASP.NET应用程序。在ASP.NET中,能够使用面向对象的...
  • 机器视觉表面缺陷检测综述

    万次阅读 多人点赞 2018-01-02 20:03:35
    转自:http://www.cjig.cn/html/jig/2017/12/20171202.htm#b22 机器视觉表面缺陷检测综述 《中国图像图形学报》 Tang B, Kong J Y, Wu S Q . Review of surface defect detection based on ... vision[J]....
  • Asp.net页面生命周期中的十个事件

    千次阅读 2010-10-13 18:12:00
    本文就Asp.net页面的生命周期向大家做一个初步的介绍,以期能起到指导大家更好、更灵活地操纵Asp.net的作用。 当一个获取网页的请求(可能是通过用户提交完成的,也可能是通过超链接完成的)被发送到Web服务器...
  •   为了更清楚地了解运动的形态,庞加莱对连续运动的轨迹用一个截面(叫庞加莱截面)将其横截,那么根据 轨迹在截面上穿过的情况,就可以简洁地判断运动的形态,由此所得图像叫庞加莱映像。在截面图上,轨迹下一次...
  • 指针变量在符号上对应的地址值为指针变量的地址值,而引用在符号上对应的地址值为引用对象的地址值(与实参名字不同,地址相同)。符号生成之后就不会再改,因此指针可以改变其指向的对象(指针变量中的值可以...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 70,511
精华内容 28,204
关键字:

如何判断元素周期表