├── 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 |
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();
--------------------------------------------------------------------------------