├── README.md ├── style.css ├── index.html └── script.js /README.md: -------------------------------------------------------------------------------- 1 | # City-3d-using-three-js 2 | 3 | city animation using three js library 4 | 5 | # Technologies used 6 | 7 | * HTML 8 | * CSS 9 | * JavaScript 10 | * Three js 11 | 12 | # Live website can be viewed here 13 | 14 | https://peter-kimanzi.github.io/City-3d-using-three-js/ 15 | 16 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: white; 3 | margin: 0; 4 | text-align: center; 5 | background-color: black; 6 | cursor: crosshair; 7 | } 8 | canvas { 9 | display: block; 10 | width: 100%; 11 | height: 100%; 12 | } 13 | p { 14 | color: rgba(255,255,255, 0.5) 15 | } 16 | .header { 17 | top: 42%; 18 | } 19 | .header-content { 20 | padding: 50px; 21 | background-color: rgba(0,0,0,0.3); 22 | border-radius: 10px; 23 | } 24 | .footer { 25 | bottom:3%; 26 | } 27 | .description { 28 | color: gray; 29 | padding-top: 50px; 30 | } 31 | a, a:hover, a:visited { 32 | color: white; 33 | text-decoration: none; 34 | } 35 | .disable-selection { 36 | -moz-user-select: none; /* Firefox */ 37 | -ms-user-select: none; /* Internet Explorer */ 38 | -khtml-user-select: none; /* KHTML browsers (e.g. Konqueror) */ 39 | -webkit-user-select: none; /* Chrome, Safari, and Opera */ 40 | -webkit-touch-callout: none; /* Disable Android and iOS callouts*/ 41 | } 42 | h1::after { 43 | content: ' Three JS'; 44 | font-size: 12px; 45 | position:absolute; 46 | top: 3px; 47 | padding-left: 5px; 48 | font-weight: 400; 49 | } 50 | h2::after { 51 | content: '2'; 52 | font-size: 12px; 53 | position:absolute; 54 | top: 14px; 55 | padding-left: 5px; 56 | } 57 | 58 | .btn { 59 | border-radius: 100px; 60 | padding: 10px 25px; 61 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | City 3D 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 |
16 |
17 |

City 3D

18 |

– Back to the red –

19 | 20 |
21 |
22 |
23 |
24 |
25 |
26 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | // Three JS Template 2 | //----------------------------------------------------------------- BASIC parameters 3 | var renderer = new THREE.WebGLRenderer({antialias:true}); 4 | renderer.setSize( window.innerWidth, window.innerHeight ); 5 | 6 | if (window.innerWidth > 800) { 7 | renderer.shadowMap.enabled = true; 8 | renderer.shadowMap.type = THREE.PCFSoftShadowMap; 9 | renderer.shadowMap.needsUpdate = true; 10 | //renderer.toneMapping = THREE.ReinhardToneMapping; 11 | //console.log(window.innerWidth); 12 | }; 13 | //--- 14 | 15 | document.body.appendChild( renderer.domElement ); 16 | 17 | window.addEventListener('resize', onWindowResize, false); 18 | function onWindowResize() { 19 | camera.aspect = window.innerWidth / window.innerHeight; 20 | camera.updateProjectionMatrix(); 21 | renderer.setSize( window.innerWidth, window.innerHeight ); 22 | }; 23 | 24 | var camera = new THREE.PerspectiveCamera( 20, window.innerWidth / window.innerHeight, 1, 500 ); 25 | 26 | camera.position.set(0, 2, 14); 27 | 28 | var scene = new THREE.Scene(); 29 | var city = new THREE.Object3D(); 30 | var smoke = new THREE.Object3D(); 31 | var town = new THREE.Object3D(); 32 | 33 | var createCarPos = true; 34 | var uSpeed = 0.001; 35 | 36 | //----------------------------------------------------------------- FOG background 37 | 38 | var setcolor = 0xF02050; 39 | //var setcolor = 0xF2F111; 40 | //var setcolor = 0xFF6347; 41 | 42 | scene.background = new THREE.Color(setcolor); 43 | scene.fog = new THREE.Fog(setcolor, 10, 16); 44 | //scene.fog = new THREE.FogExp2(setcolor, 0.05); 45 | //----------------------------------------------------------------- RANDOM Function 46 | function mathRandom(num = 8) { 47 | var numValue = - Math.random() * num + Math.random() * num; 48 | return numValue; 49 | }; 50 | //----------------------------------------------------------------- CHANGE bluilding colors 51 | var setTintNum = true; 52 | function setTintColor() { 53 | if (setTintNum) { 54 | setTintNum = false; 55 | var setColor = 0x000000; 56 | } else { 57 | setTintNum = true; 58 | var setColor = 0x000000; 59 | }; 60 | //setColor = 0x222222; 61 | return setColor; 62 | }; 63 | 64 | //----------------------------------------------------------------- CREATE City 65 | 66 | function init() { 67 | var segments = 2; 68 | for (var i = 1; i<100; i++) { 69 | var geometry = new THREE.CubeGeometry(1,0,0,segments,segments,segments); 70 | var material = new THREE.MeshStandardMaterial({ 71 | color:setTintColor(), 72 | wireframe:false, 73 | //opacity:0.9, 74 | //transparent:true, 75 | //roughness: 0.3, 76 | //metalness: 1, 77 | shading: THREE.SmoothShading, 78 | //shading:THREE.FlatShading, 79 | side:THREE.DoubleSide}); 80 | var wmaterial = new THREE.MeshLambertMaterial({ 81 | color:0xFFFFFF, 82 | wireframe:true, 83 | transparent:true, 84 | opacity: 0.03, 85 | side:THREE.DoubleSide/*, 86 | shading:THREE.FlatShading*/}); 87 | 88 | var cube = new THREE.Mesh(geometry, material); 89 | var wire = new THREE.Mesh(geometry, wmaterial); 90 | var floor = new THREE.Mesh(geometry, material); 91 | var wfloor = new THREE.Mesh(geometry, wmaterial); 92 | 93 | cube.add(wfloor); 94 | cube.castShadow = true; 95 | cube.receiveShadow = true; 96 | cube.rotationValue = 0.1+Math.abs(mathRandom(8)); 97 | 98 | //floor.scale.x = floor.scale.z = 1+mathRandom(0.33); 99 | floor.scale.y = 0.05;//+mathRandom(0.5); 100 | cube.scale.y = 0.1+Math.abs(mathRandom(8)); 101 | //TweenMax.to(cube.scale, 1, {y:cube.rotationValue, repeat:-1, yoyo:true, delay:i*0.005, ease:Power1.easeInOut}); 102 | /*cube.setScale = 0.1+Math.abs(mathRandom()); 103 | 104 | TweenMax.to(cube.scale, 4, {y:cube.setScale, ease:Elastic.easeInOut, delay:0.2*i, yoyo:true, repeat:-1}); 105 | TweenMax.to(cube.position, 4, {y:cube.setScale / 2, ease:Elastic.easeInOut, delay:0.2*i, yoyo:true, repeat:-1});*/ 106 | 107 | var cubeWidth = 0.9; 108 | cube.scale.x = cube.scale.z = cubeWidth+mathRandom(1-cubeWidth); 109 | //cube.position.y = cube.scale.y / 2; 110 | cube.position.x = Math.round(mathRandom()); 111 | cube.position.z = Math.round(mathRandom()); 112 | 113 | floor.position.set(cube.position.x, 0/*floor.scale.y / 2*/, cube.position.z) 114 | 115 | town.add(floor); 116 | town.add(cube); 117 | }; 118 | //----------------------------------------------------------------- Particular 119 | 120 | var gmaterial = new THREE.MeshToonMaterial({color:0xFFFF00, side:THREE.DoubleSide}); 121 | var gparticular = new THREE.CircleGeometry(0.01, 3); 122 | var aparticular = 5; 123 | 124 | for (var h = 1; h<300; h++) { 125 | var particular = new THREE.Mesh(gparticular, gmaterial); 126 | particular.position.set(mathRandom(aparticular), mathRandom(aparticular),mathRandom(aparticular)); 127 | particular.rotation.set(mathRandom(),mathRandom(),mathRandom()); 128 | smoke.add(particular); 129 | }; 130 | 131 | var pmaterial = new THREE.MeshPhongMaterial({ 132 | color:0x000000, 133 | side:THREE.DoubleSide, 134 | roughness: 10, 135 | metalness: 0.6, 136 | opacity:0.9, 137 | transparent:true}); 138 | var pgeometry = new THREE.PlaneGeometry(60,60); 139 | var pelement = new THREE.Mesh(pgeometry, pmaterial); 140 | pelement.rotation.x = -90 * Math.PI / 180; 141 | pelement.position.y = -0.001; 142 | pelement.receiveShadow = true; 143 | //pelement.material.emissive.setHex(0xFFFFFF + Math.random() * 100000); 144 | 145 | city.add(pelement); 146 | }; 147 | 148 | //----------------------------------------------------------------- MOUSE function 149 | var raycaster = new THREE.Raycaster(); 150 | var mouse = new THREE.Vector2(), INTERSECTED; 151 | var intersected; 152 | 153 | function onMouseMove(event) { 154 | event.preventDefault(); 155 | mouse.x = (event.clientX / window.innerWidth) * 2 - 1; 156 | mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; 157 | }; 158 | function onDocumentTouchStart( event ) { 159 | if ( event.touches.length == 1 ) { 160 | event.preventDefault(); 161 | mouse.x = event.touches[ 0 ].pageX - window.innerWidth / 2; 162 | mouse.y = event.touches[ 0 ].pageY - window.innerHeight / 2; 163 | }; 164 | }; 165 | function onDocumentTouchMove( event ) { 166 | if ( event.touches.length == 1 ) { 167 | event.preventDefault(); 168 | mouse.x = event.touches[ 0 ].pageX - window.innerWidth / 2; 169 | mouse.y = event.touches[ 0 ].pageY - window.innerHeight / 2; 170 | } 171 | } 172 | window.addEventListener('mousemove', onMouseMove, false); 173 | window.addEventListener('touchstart', onDocumentTouchStart, false ); 174 | window.addEventListener('touchmove', onDocumentTouchMove, false ); 175 | 176 | //----------------------------------------------------------------- Lights 177 | var ambientLight = new THREE.AmbientLight(0xFFFFFF, 4); 178 | var lightFront = new THREE.SpotLight(0xFFFFFF, 20, 10); 179 | var lightBack = new THREE.PointLight(0xFFFFFF, 0.5); 180 | 181 | var spotLightHelper = new THREE.SpotLightHelper( lightFront ); 182 | //scene.add( spotLightHelper ); 183 | 184 | lightFront.rotation.x = 45 * Math.PI / 180; 185 | lightFront.rotation.z = -45 * Math.PI / 180; 186 | lightFront.position.set(5, 5, 5); 187 | lightFront.castShadow = true; 188 | lightFront.shadow.mapSize.width = 6000; 189 | lightFront.shadow.mapSize.height = lightFront.shadow.mapSize.width; 190 | lightFront.penumbra = 0.1; 191 | lightBack.position.set(0,6,0); 192 | 193 | smoke.position.y = 2; 194 | 195 | scene.add(ambientLight); 196 | city.add(lightFront); 197 | scene.add(lightBack); 198 | scene.add(city); 199 | city.add(smoke); 200 | city.add(town); 201 | 202 | //----------------------------------------------------------------- GRID Helper 203 | var gridHelper = new THREE.GridHelper( 60, 120, 0xFF0000, 0x000000); 204 | city.add( gridHelper ); 205 | 206 | //----------------------------------------------------------------- CAR world 207 | var generateCar = function() { 208 | 209 | } 210 | //----------------------------------------------------------------- LINES world 211 | 212 | var createCars = function(cScale = 2, cPos = 20, cColor = 0xFFFF00) { 213 | var cMat = new THREE.MeshToonMaterial({color:cColor, side:THREE.DoubleSide}); 214 | var cGeo = new THREE.CubeGeometry(1, cScale/40, cScale/40); 215 | var cElem = new THREE.Mesh(cGeo, cMat); 216 | var cAmp = 3; 217 | 218 | if (createCarPos) { 219 | createCarPos = false; 220 | cElem.position.x = -cPos; 221 | cElem.position.z = (mathRandom(cAmp)); 222 | 223 | TweenMax.to(cElem.position, 3, {x:cPos, repeat:-1, yoyo:true, delay:mathRandom(3)}); 224 | } else { 225 | createCarPos = true; 226 | cElem.position.x = (mathRandom(cAmp)); 227 | cElem.position.z = -cPos; 228 | cElem.rotation.y = 90 * Math.PI / 180; 229 | 230 | TweenMax.to(cElem.position, 5, {z:cPos, repeat:-1, yoyo:true, delay:mathRandom(3), ease:Power1.easeInOut}); 231 | }; 232 | cElem.receiveShadow = true; 233 | cElem.castShadow = true; 234 | cElem.position.y = Math.abs(mathRandom(5)); 235 | city.add(cElem); 236 | }; 237 | 238 | var generateLines = function() { 239 | for (var i = 0; i<60; i++) { 240 | createCars(0.1, 20); 241 | }; 242 | }; 243 | 244 | //----------------------------------------------------------------- CAMERA position 245 | 246 | var cameraSet = function() { 247 | createCars(0.1, 20, 0xFFFFFF); 248 | //TweenMax.to(camera.position, 1, {y:1+Math.random()*4, ease:Expo.easeInOut}) 249 | }; 250 | 251 | //----------------------------------------------------------------- ANIMATE 252 | 253 | var animate = function() { 254 | var time = Date.now() * 0.00005; 255 | requestAnimationFrame(animate); 256 | 257 | city.rotation.y -= ((mouse.x * 8) - camera.rotation.y) * uSpeed; 258 | city.rotation.x -= (-(mouse.y * 2) - camera.rotation.x) * uSpeed; 259 | if (city.rotation.x < -0.05) city.rotation.x = -0.05; 260 | else if (city.rotation.x>1) city.rotation.x = 1; 261 | var cityRotation = Math.sin(Date.now() / 5000) * 13; 262 | //city.rotation.x = cityRotation * Math.PI / 180; 263 | 264 | //console.log(city.rotation.x); 265 | //camera.position.y -= (-(mouse.y * 20) - camera.rotation.y) * uSpeed;; 266 | 267 | for ( let i = 0, l = town.children.length; i < l; i ++ ) { 268 | var object = town.children[ i ]; 269 | //object.scale.y = Math.sin(time*50) * object.rotationValue; 270 | //object.rotation.y = (Math.sin((time/object.rotationValue) * Math.PI / 180) * 180); 271 | //object.rotation.z = (Math.cos((time/object.rotationValue) * Math.PI / 180) * 180); 272 | } 273 | 274 | smoke.rotation.y += 0.01; 275 | smoke.rotation.x += 0.01; 276 | 277 | camera.lookAt(city.position); 278 | renderer.render( scene, camera ); 279 | } 280 | 281 | //----------------------------------------------------------------- START functions 282 | generateLines(); 283 | init(); 284 | animate(); --------------------------------------------------------------------------------