迷失在太空

迷失在太空


更多有趣示例 尽在 小红砖社区

示例

在这里插入图片描述

HTML

<div id="universe"/>

<footer>
      <a target="_blank" href="https://www.made-on-mars.com"><svg id="Calque_logo2" data-name="Calque logo2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 1306.42"><defs><style>.cls-logo2{fill:#ffffff;}</style></defs><path class="cls-logo2" d="M2043.47,2428a39,39,0,1,0,23.28,8.1c55.42,11,96.65,60.62,96.65,117.45a120,120,0,0,1-119.93,119.91,118.29,118.29,0,0,1-48.7-10.47v-359.6a38.92,38.92,0,0,0-38.87-38.87h-87.24v-32a38.92,38.92,0,0,0-38.87-38.87h-87.18v-27.75a38.92,38.92,0,0,0-38.87-38.87H1638.8a69.8,69.8,0,0,0,0,139.6,16.78,16.78,0,1,0-16.76-16.76,16.6,16.6,0,0,0,3,9.51,64.08,64.08,0,0,1,13.8-126.67,27,27,0,0,1,27,27v343.09a38.92,38.92,0,0,0,38.87,38.87h37.94V2199.38h22.23a27,27,0,0,1,27,27v276.43a38.92,38.92,0,0,0,38.87,38.87h37.94V2270.23h22.27a27,27,0,0,1,27,27v256.37A125.53,125.53,0,1,0,2043.47,2428Z" transform="translate(-1569 -2127.04)"></path><path class="cls-logo2" d="M2128.54,2873.92V3393H1609.46V2873.92h519.08m40.46-40.46H1569v600h600v-600Z" transform="translate(-1569 -2127.04)"></path><path class="cls-logo2" d="M1794.74,3133.7a44.44,44.44,0,0,1-2.74,15.88,36.33,36.33,0,0,1-7.74,12.43,34.6,34.6,0,0,1-12,8.09,43.16,43.16,0,0,1-31,0,34.73,34.73,0,0,1-12-8.09,36.33,36.33,0,0,1-7.74-12.43,47.39,47.39,0,0,1,0-31.75,36.67,36.67,0,0,1,7.74-12.47,34.69,34.69,0,0,1,12-8.13,42.72,42.72,0,0,1,31,0,34.55,34.55,0,0,1,12,8.13,36.67,36.67,0,0,1,7.74,12.47A44.48,44.48,0,0,1,1794.74,3133.7Zm-10.69,0a39.07,39.07,0,0,0-1.93-12.73,26.83,26.83,0,0,0-5.48-9.54,23.65,23.65,0,0,0-8.59-6,31.24,31.24,0,0,0-22.51,0,24,24,0,0,0-8.62,6,26.65,26.65,0,0,0-5.51,9.54,42.85,42.85,0,0,0,0,25.44,26.69,26.69,0,0,0,5.51,9.51,23.8,23.8,0,0,0,8.62,6,31.68,31.68,0,0,0,22.51,0,23.48,23.48,0,0,0,8.59-6,26.87,26.87,0,0,0,5.48-9.51A38.86,38.86,0,0,0,1784,3133.7Z" transform="translate(-1569 -2127.04)"></path><path class="cls-logo2" d="M1816.42,3095.52A5.55,5.55,0,0,1,1818,3097l44.59,58c-.1-.93-.18-1.84-.22-2.72s-.05-1.73-.05-2.55v-54.54h9.13v77h-5.27a4.52,4.52,0,0,1-2.07-.43,5.12,5.12,0,0,1-1.64-1.45l-44.54-58c.07.9.12,1.77.16,2.63s.06,1.65.06,2.36v54.86H1809v-77h5.37A4.71,4.71,0,0,1,1816.42,3095.52Z" transform="translate(-1569 -2127.04)"></path><path class="cls-logo2" d="M1759.12,3038.25c.36-1,28.53-53,28.53-53a3.1,3.1,0,0,1,1.45-1.5,6.66,6.66,0,0,1,2.15-.27h7.69v77h-9.13v-56.57c0-.76,0-1.56.05-2.42s.09-1.73.16-2.63L1763.63,3047a4.15,4.15,0,0,1-3.76,2.41h-1.51a4.14,4.14,0,0,1-3.76-2.41l-27-48.3c.11.93.19,1.85.24,2.74s.08,1.72.08,2.48v56.57h-9.13v-77h7.68a6.69,6.69,0,0,1,2.15.27,3.12,3.12,0,0,1,1.45,1.5S1758.76,3037.29,1759.12,3038.25Z" transform="translate(-1569 -2127.04)"></path><path class="cls-logo2" d="M1881,3060.5H1873a3.42,3.42,0,0,1-2.26-.7,4.16,4.16,0,0,1-1.29-1.77l-7.2-18.58h-34.55l-7.2,18.58a4.13,4.13,0,0,1-1.29,1.72,3.42,3.42,0,0,1-2.26.76h-8.06l30.79-77h10.58Zm-50.45-28.58h28.75l-12.09-31.32a59.28,59.28,0,0,1-2.31-7.25q-.59,2.2-1.15,4.06c-.37,1.23-.74,2.32-1.1,3.24Z" transform="translate(-1569 -2127.04)"></path><path class="cls-logo2" d="M1957.48,3022a43.32,43.32,0,0,1-2.74,15.74,34.84,34.84,0,0,1-7.74,12.14,34.37,34.37,0,0,1-12,7.82,41.65,41.65,0,0,1-15.48,2.77h-28.79v-77h28.79a41.65,41.65,0,0,1,15.48,2.77,34.42,34.42,0,0,1,12,7.84,35.27,35.27,0,0,1,7.74,12.17A43.36,43.36,0,0,1,1957.48,3022Zm-10.69,0a38.61,38.61,0,0,0-1.94-12.68,26.55,26.55,0,0,0-5.48-9.45,23.44,23.44,0,0,0-8.59-5.92,29.88,29.88,0,0,0-11.23-2h-18.32v60.12h18.32a29.88,29.88,0,0,0,11.23-2,23.62,23.62,0,0,0,8.59-5.89,26.36,26.36,0,0,0,5.48-9.43A38.57,38.57,0,0,0,1946.79,3022Z" transform="translate(-1569 -2127.04)"></path><path class="cls-logo2" d="M2019.11,2983.51V2992h-37v25.57h29.92v8.16h-29.92V3052h37v8.49h-47.44v-77Z" transform="translate(-1569 -2127.04)"></path><path class="cls-logo2" d="M1759.12,3260.68c.36-1,28.53-53,28.53-53a3.1,3.1,0,0,1,1.45-1.5,6.66,6.66,0,0,1,2.15-.27h7.69v77h-9.13v-56.57c0-.76,0-1.56.05-2.42s.09-1.73.16-2.63l-26.38,48.14a4.15,4.15,0,0,1-3.76,2.41h-1.51a4.14,4.14,0,0,1-3.76-2.41l-27-48.3c.11.93.19,1.85.24,2.74s.08,1.72.08,2.48v56.57h-9.13v-77h7.68a6.69,6.69,0,0,1,2.15.27,3.12,3.12,0,0,1,1.45,1.5S1758.76,3259.72,1759.12,3260.68Z" transform="translate(-1569 -2127.04)"></path><path class="cls-logo2" d="M1881,3282.93H1873a3.42,3.42,0,0,1-2.26-.7,4.16,4.16,0,0,1-1.29-1.77l-7.2-18.58h-34.55l-7.2,18.58a4.13,4.13,0,0,1-1.29,1.72,3.42,3.42,0,0,1-2.26.76h-8.06l30.79-77h10.58Zm-50.45-28.58h28.75L1847.24,3223a59.28,59.28,0,0,1-2.31-7.25q-.59,2.2-1.15,4.06c-.37,1.23-.74,2.32-1.1,3.24Z" transform="translate(-1569 -2127.04)"></path><path class="cls-logo2" d="M1902.2,3250.8v32.13h-10.37v-77h21.76a47.48,47.48,0,0,1,12.62,1.48,24,24,0,0,1,8.78,4.27,17.05,17.05,0,0,1,5.13,6.74,22.53,22.53,0,0,1,1.67,8.85,22.18,22.18,0,0,1-1.29,7.63,20.11,20.11,0,0,1-3.74,6.36,22.29,22.29,0,0,1-6,4.82,29.37,29.37,0,0,1-8,3,11,11,0,0,1,3.44,3.28l22.46,30.57h-9.24a4.55,4.55,0,0,1-4.19-2.2l-20-27.5a5.86,5.86,0,0,0-2-1.86,7.16,7.16,0,0,0-3.23-.57Zm0-7.58h10.91a26.51,26.51,0,0,0,8-1.1,16.32,16.32,0,0,0,5.8-3.12,12.87,12.87,0,0,0,3.52-4.81,15.71,15.71,0,0,0,1.18-6.18q0-6.88-4.54-10.37t-13.51-3.49H1902.2Z" transform="translate(-1569 -2127.04)"></path><path class="cls-logo2" d="M1999.39,3218a4.09,4.09,0,0,1-1,1.21,2.24,2.24,0,0,1-1.4.41,3.66,3.66,0,0,1-2.12-.92,34.71,34.71,0,0,0-3.06-2,26.49,26.49,0,0,0-4.46-2,19.19,19.19,0,0,0-6.31-.91,18.61,18.61,0,0,0-6.18.94,13.28,13.28,0,0,0-4.49,2.55,10.53,10.53,0,0,0-2.71,3.79,12,12,0,0,0-.91,4.7,8.72,8.72,0,0,0,1.58,5.35,13.52,13.52,0,0,0,4.19,3.62,31.77,31.77,0,0,0,5.91,2.61q3.31,1.1,6.77,2.28t6.77,2.67a23.9,23.9,0,0,1,5.91,3.73,17.2,17.2,0,0,1,4.19,5.54,18.43,18.43,0,0,1,1.58,8.06,25.86,25.86,0,0,1-1.72,9.48,21.77,21.77,0,0,1-5,7.71,23.68,23.68,0,0,1-8.11,5.16,30,30,0,0,1-10.93,1.88,33.27,33.27,0,0,1-13.62-2.72,31.81,31.81,0,0,1-10.5-7.34l3-4.94a3.92,3.92,0,0,1,1-1,2.41,2.41,0,0,1,1.37-.41,4.29,4.29,0,0,1,2.58,1.22,43.78,43.78,0,0,0,3.63,2.65,27.29,27.29,0,0,0,5.26,2.65,20.73,20.73,0,0,0,7.55,1.22,19.83,19.83,0,0,0,6.61-1,13.9,13.9,0,0,0,4.92-2.88,12.31,12.31,0,0,0,3.09-4.43,14.76,14.76,0,0,0,1.08-5.75,9.66,9.66,0,0,0-1.58-5.72,13.16,13.16,0,0,0-4.16-3.74,29.17,29.17,0,0,0-5.89-2.55l-6.77-2.15a69,69,0,0,1-6.77-2.55,22,22,0,0,1-5.89-3.77,17.21,17.21,0,0,1-4.16-5.77,20.51,20.51,0,0,1-1.58-8.57,20.53,20.53,0,0,1,6.18-14.66,22.3,22.3,0,0,1,7.45-4.73,27.17,27.17,0,0,1,10.18-1.77,32.54,32.54,0,0,1,11.77,2,26.92,26.92,0,0,1,9.29,5.91Z" transform="translate(-1569 -2127.04)"></path></svg></a>
    </footer>

CSS

html, body { 
  height:100%; 
  width:100%; 
  margin:0; 
  padding:0; 
  overflow:hidden; 
}
body { 
  background: linear-gradient(180deg, #373773, #235689, #2a9096, #364a7b, #4a367b, #5e3665, #2c294b, #31437a);
  background-size: 1600% 1600%;
  -webkit-animation: skygradient 180s ease infinite;
  -moz-animation: skygradient 180s ease infinite;
  -o-animation: skygradient 180s ease infinite;
  animation: skygradient 180s ease infinite;
}
@-webkit-keyframes skygradient {
  0%{background-position:50% 0%}
  50%{background-position:50% 100%}
  100%{background-position:50% 0%}
}
@-moz-keyframes skygradient {
  0%{background-position:50% 0%}
  50%{background-position:50% 100%}
  100%{background-position:50% 0%}
}
@-o-keyframes skygradient {
  0%{background-position:50% 0%}
  50%{background-position:50% 100%}
  100%{background-position:50% 0%}
}
@keyframes skygradient { 
  0%{background-position:50% 0%}
  50%{background-position:50% 100%}
  100%{background-position:50% 0%}
}
canvas { 
  width: 100%!important; height: 100%!important; 
}

footer {
  position:fixed;
  z-index:1000;
  left:0;
  bottom:0;
  display:block;
  padding:20px;
  box-sizing:border-box;
}

footer a {
  text-decoration:none;
  display:block;
  width:50px;
}

footer a svg {
  width:100%;
  max-width:50px;
  min-width:40px;
  display:inline-block;
}

JS

function getMat(color){
      // our material is a phong material, with no shininess (highlight) and a black specular
      return new THREE.MeshStandardMaterial({
        color:color,
        roughness:.9,
        transparent: true,
        opacity: 0,
        emissive:0x270000,
        shading:THREE.FlatShading
      });
    }

    var Colors = {
      red : 0xf85051,
      orange: 0xea8962,
      yellow: 0xdacf75,
      beige: 0xccc58f,
      grey: 0xbab7a1,
      blue: 0x4379a8,
      ocean: 0x4993a8,
      green: 0x24a99b
    };

    var colorsLength = Object.keys(Colors).length;

    function randomRange(min,max) {
        return Math.floor(Math.random()*(max-min+1)+min);
    }

    function getRandomColor(){
      var colIndx = Math.floor(Math.random()*colorsLength);
      var colorStr = Object.keys(Colors)[colIndx];
      return Colors[colorStr];
    }

    function shiftPosition(pos, radius){
      if(Math.abs(pos) < radius){
        if(pos >= 0){
          return pos + radius;
        } else {
          return pos - radius;
        }
      } else {
        return pos;
      }
    }

    // Default parameters
    var parameters = {
      minRadius : 30,
      maxRadius : 50,
      minSpeed:.015,
      maxSpeed:.025,
      particles:500,
      minSize:.1,
      maxSize:2
    };

    // For a THREEJS project we need at least
    // a scene
    // a renderer
    // a camera
    // a light (1 or many)
    // a mesh (an object to display)

    var scene, renderer, camera, light;
    var stars = [];
    var nbPlanetsMax = 4;
    var planets = [];
    var WIDTH = window.innerWidth,
    HEIGHT = window.innerHeight;


    // initialise the world
    function initWorld(){
      scene = new THREE.Scene();
      camera = new THREE.PerspectiveCamera(75, WIDTH/HEIGHT, .1, 2000);
      camera.position.z = 100;

      //
      // THE RENDERER
      //
      renderer = new THREE.WebGLRenderer({
        alpha: true,
        antialias: true
      });
      renderer.setSize(WIDTH, HEIGHT);
      renderer.shadowMap.enabled = true;

      container = document.getElementById('universe');
      container.appendChild(renderer.domElement);


      // Lights
      ambientLight = new THREE.AmbientLight(0x663344,2);
      scene.add(ambientLight);

      light = new THREE.DirectionalLight(0xffffff, 1.5);
      light.position.set(200,100,200);
      light.castShadow = true;
      light.shadow.camera.left = -400;
      light.shadow.camera.right = 400;
      light.shadow.camera.top = 400;
      light.shadow.camera.bottom = -400;
      light.shadow.camera.near = 1;
      light.shadow.camera.far = 1000;
      light.shadow.mapSize.width = 2048;
      light.shadow.mapSize.height = 2048;

      scene.add(light);


      //
      // HANDLE SCREEN RESIZE
      //
      window.addEventListener('resize', handleWindowResize, false);

      // Creating firts planets
      for(var i = 0; i < nbPlanetsMax; i++){
        planets.push(new Planet(-2000/nbPlanetsMax * i - 500));
      }
      addStarts();
      loop();

  }

  function animateStars(z) {

  // loop through each star
    for(var i=0; i<stars.length; i++) {

      star = stars[i];
      // if the particle is too close move it to the back
      if(star.position.z>z) star.position.z-=2000;

    }

  }

  function addStarts(){

      for ( var z= -2000; z < 0; z+=20 ) {

        var geometry   = new THREE.SphereGeometry(0.5, 32, 32)
        var material = new THREE.MeshBasicMaterial( {color: 0xffffff} );
        var sphere = new THREE.Mesh(geometry, material)

        sphere.position.x = randomRange(-1 * Math.floor(WIDTH/2),Math.floor(WIDTH/2));
        sphere.position.y = randomRange(-1 * Math.floor(HEIGHT/2),Math.floor(HEIGHT/2));

        // Then set the z position to where it is in the loop (distance of camera)
        sphere.position.z = z;

        // scale it up a bit
        sphere.scale.x = sphere.scale.y = 2;

        //add the sphere to the scene
        scene.add( sphere );

        //finally push it to the stars array
        stars.push(sphere);
      }
  }

  var Planet = function(z){
    // the geometry of the planet is a tetrahedron
    this.planetRadius = randomRange(12,30);
    var planetDetail = randomRange(2,3);
    var geomPlanet = new THREE.TetrahedronGeometry(this.planetRadius, planetDetail);

    var noise = randomRange(1,5);
    for(var i=0; i<geomPlanet.vertices.length; i++){
      var v = geomPlanet.vertices[i];
      v.x += -noise/2 + Math.random()*noise;
      v.y += -noise/2 + Math.random()*noise;
      v.z += -noise/2 + Math.random()*noise;
    }

    // create a new material for the planet
    var color = getRandomColor();
    var matPlanet = getMat(color);
    // create the mesh of the planet
    this.planet = new THREE.Mesh(geomPlanet, matPlanet);

    this.ring = new THREE.Mesh();
    this.nParticles = 0;

    // create the particles to populate the ring
    this.updateParticlesCount();

    // Create a global mesh to hold the planet and the ring
    this.mesh = new THREE.Object3D();
    this.mesh.add(this.planet);
    this.mesh.add(this.ring);

    this.planet.castShadow = true;
    this.planet.receiveShadow = true;

    // update the position of the particles => must be moved to the loop
    this.mesh.rotation.x = (Math.random()*2-1) * 2 * Math.PI;
    this.mesh.rotation.z = (Math.random()*2-1) * 2 * Math.PI;

    var posX = randomRange(-1 * Math.floor(WIDTH/4),Math.floor(WIDTH/4));
    var posY = randomRange(-1 * Math.floor(HEIGHT/4),Math.floor(HEIGHT/4));
    posX = shiftPosition(posX, this.planetRadius);
    posY = shiftPosition(posY, this.planetRadius);

    this.mesh.position.set(posX,posY,z);
    scene.add(this.mesh);
  }
  Planet.prototype.destroy = function(){
    scene.remove( this.mesh );
  }
  Planet.prototype.updateParticlesCount = function(){
    var parameters = {
      minRadius : randomRange(this.planetRadius + 10 , 60),
      maxRadius : randomRange(40,70),
      minSpeed: randomRange(0,5)*0.1 + randomRange(0,9) * 0.01,
      maxSpeed: randomRange(0,5)*0.1 + randomRange(0,9) * 0.01,
      particles: randomRange(0,1) * randomRange(20,30),
      minSize: randomRange(1,3) + randomRange(0,9) * 0.1,
      maxSize: randomRange(1,3) + randomRange(0,9) * 0.1
    };

    if (this.nParticles < parameters.particles){
      // Remove particles
      for (var i=this.nParticles; i< parameters.particles; i++){
        var p = new Particle();
        p.mesh.rotation.x = Math.random()*Math.PI;
        p.mesh.rotation.y = Math.random()*Math.PI;
        p.mesh.position.y = -2 + Math.random()*4;
        this.ring.add(p.mesh);
      }
    }else{
      // add particles
      while(this.nParticles > parameters.particles){
        var m = this.ring.children[this.nParticles-1];
        this.ring.remove(m);
        m.userData.po = null;
        this.nParticles--;
      }
    }
    this.nParticles = parameters.particles;

    // We will give a specific angle to each particle
    // to cover the whole ring we need to
    // dispatch them regularly
    this.angleStep = Math.PI*2/this.nParticles;
    this.updateParticlesDefiniton();
  }

  // Update particles definition
  Planet.prototype.updateParticlesDefiniton = function(){

    for(var i=0; i<this.nParticles; i++){
      var m = this.ring.children[i];
      var s = parameters.minSize + Math.random()*(parameters.maxSize - parameters.minSize);
      m.scale.set(s,s,s);

      // set a random distance
      m.userData.distance = parameters.minRadius +  Math.random()*(parameters.maxRadius-parameters.minRadius);

      // give a unique angle to each particle
      m.userData.angle = this.angleStep*i;
      // set a speed proportionally to the distance
      m.userData.angularSpeed = rule3(m.userData.distance,parameters.minRadius,parameters.maxRadius,parameters.minSpeed, parameters.maxSpeed);
    }
  }

  var Particle = function(){
    // Size of the particle, make it random
    var s = 1;

    // geometry of the particle, choose between different shapes
    var geom,
    random = Math.random();

    if (random<.25){
      // Cube
      geom = new THREE.BoxGeometry(s,s,s);

    }else if (random < .5){
      // Pyramid
      geom = new THREE.CylinderGeometry(0,s,s*2, 4, 1);

    }else if (random < .75){
      // potato shape
      geom = new THREE.TetrahedronGeometry(s,2);

    }else{
      // thick plane
      geom = new THREE.BoxGeometry(s/6,s,s); // thick plane
    }
    // color of the particle, make it random and get a material
    var color = getRandomColor();
    var mat = getMat(color);

    // create the mesh of the particle
    this.mesh = new THREE.Mesh(geom, mat);
    this.mesh.receiveShadow = true;
    this.mesh.castShadow = true;
    this.mesh.userData.po = this;
  }


  // Update particles position
  Planet.prototype.updateParticlesRotation = function(){

    // increase the rotation of each particle
    // and update its position

    for(var i=0; i<this.nParticles; i++){
      var m = this.ring.children[i];
      // increase the rotation angle around the planet
      m.userData.angle += m.userData.angularSpeed;

      // calculate the new position
      var posX = Math.cos(m.userData.angle)*m.userData.distance;
      var posZ = Math.sin(m.userData.angle)*m.userData.distance;
      m.position.x = posX;
      m.position.z = posZ;

      //*
      // add a local rotation to the particle
      m.rotation.x += Math.random()*.05;
      m.rotation.y += Math.random()*.05;
      m.rotation.z += Math.random()*.05;
      //*/
    }
  }

  function addPlanet(z){
    planets.push(new Planet(z));
  }

  function loop(){
    var horizon = - 2000 + camera.position.z;
    for(var i = 0; i < planets.length; i++){
      if(planets[i].mesh.position.z > camera.position.z){
        planets[i].destroy();
        planets.splice(i, 1);
      }

      // If the planet is arriving
      if(planets[i].mesh.position.z > horizon && planets[i].planet.material.opacity < 1){
        planets[i].planet.material.opacity += 0.005;
        for(var j=0; j< planets[i].mesh.children[1].children.length; j++){
          planets[i].mesh.children[1].children[j].material.opacity += 0.005;
        }
      }
    }


    // Adding stars
    animateStars(camera.position.z);

    if(planets.length < nbPlanetsMax){
      addPlanet(camera.position.z - 2000);
    }

    for(var i = 0; i < planets.length; i++){
      planets[i].planet.rotation.y-= 0.01;
      planets[i].updateParticlesRotation();
    }

    camera.position.z -= 3;

    //
    // RENDER !
    //
    renderer.render(scene, camera);

    //
    // REQUEST A NEW FRAME
    //
    requestAnimationFrame(loop);
  }

  function handleWindowResize() {
    // Recalculate Width and Height as they had changed
    HEIGHT = window.innerHeight;
    WIDTH = window.innerWidth;

    // Update the renderer and the camera
    renderer.setSize(WIDTH, HEIGHT);
    camera.aspect = WIDTH / HEIGHT;
    camera.updateProjectionMatrix();
  }



  initWorld();




  function rule3(v,vmin,vmax,tmin, tmax){
    var nv = Math.max(Math.min(v,vmax), vmin);
    var dv = vmax-vmin;
    var pc = (nv-vmin)/dv;
    var dt = tmax-tmin;
    var tv = tmin + (pc*dt);
    return tv;

  }


猜你喜欢

转载自blog.csdn.net/weixin_45544796/article/details/107225289
今日推荐