天青色等烟雨*^_^* 2021-08-30 08:42 采纳率: 40%
浏览 1389
已结题

有那个能用html+css+js源生实现soul星球特效啊

img

  • 写回答

1条回答 默认 最新

  • console.log( ) 2021-08-30 09:35
    关注

    这个一般用canvas
    我有个例子你可以参考一下,不过我的只是随机生成圆,自动旋转,和soul的功能差的很多
    你可以在此基础上自己添加鼠标移入停止旋转,鼠标拖动旋转、点击、hover功能等

    
    <!DOCTYPE html>
    <html lang="en" >
    
    <head>
    <meta charset="UTF-8">
    <title>3D Globe (Pure canvas)</title>
    
    
    
    <link rel="stylesheet" href="css/style.css">
    
    
    </head>
    
    <body>
    
    <canvas id="scene"></canvas>
    
    
    
    <script  src="js/index.js"></script>
    
    
    
    
    </body>
    
    </html>
    
    
    
    console.clear();
    
    // Get the canvas element from the DOM
    const canvas = document.querySelector('#scene');
    canvas.width = canvas.clientWidth;
    canvas.height = canvas.clientHeight;
    // Store the 2D context
    const ctx = canvas.getContext('2d');
    
    if (window.devicePixelRatio > 1) {
      canvas.width = canvas.clientWidth * 2;
      canvas.height = canvas.clientHeight * 2;
      ctx.scale(2, 2);
    }
    
    /* ====================== */
    /* ====== VARIABLES ===== */
    /* ====================== */
    let width = canvas.clientWidth; // Width of the canvas
    let height = canvas.clientHeight; // Height of the canvas
    let rotation = 0; // Rotation of the globe
    let dots = []; // Every dots in an array
    
    /* ====================== */
    /* ====== CONSTANTS ===== */
    /* ====================== */
    /* Some of those constants may change if the user resizes their screen but I still strongly believe they belong to the Constants part of the variables */
    const DOTS_AMOUNT = 1000; // Amount of dots on the screen
    const DOT_RADIUS = 4; // Radius of the dots
    let GLOBE_RADIUS = width * 0.7; // Radius of the globe
    let GLOBE_CENTER_Z = -GLOBE_RADIUS; // Z value of the globe center
    let PROJECTION_CENTER_X = width / 2; // X center of the canvas HTML
    let PROJECTION_CENTER_Y = height / 2; // Y center of the canvas HTML
    let FIELD_OF_VIEW = width * 0.8;
    
    class Dot {
      constructor(x, y, z) {
        this.x = x;
        this.y = y;
        this.z = z;
        
        this.xProject = 0;
        this.yProject = 0;
        this.sizeProjection = 0;
      }
      // Do some math to project the 3D position into the 2D canvas
      project(sin, cos) {
        const rotX = cos * this.x + sin * (this.z - GLOBE_CENTER_Z);
        const rotZ = -sin * this.x + cos * (this.z - GLOBE_CENTER_Z) + GLOBE_CENTER_Z;
        this.sizeProjection = FIELD_OF_VIEW / (FIELD_OF_VIEW - rotZ);
        this.xProject = (rotX * this.sizeProjection) + PROJECTION_CENTER_X;
        this.yProject = (this.y * this.sizeProjection) + PROJECTION_CENTER_Y;
      }
      // Draw the dot on the canvas
      draw(sin, cos) {
        this.project(sin, cos);
        // ctx.fillRect(this.xProject - DOT_RADIUS, this.yProject - DOT_RADIUS, DOT_RADIUS * 2 * this.sizeProjection, DOT_RADIUS * 2 * this.sizeProjection);
        ctx.beginPath();
        ctx.arc(this.xProject, this.yProject, DOT_RADIUS * this.sizeProjection, 0, Math.PI * 2);
        ctx.closePath();
        ctx.fill();
      }
    }
    
    function createDots() {
      // Empty the array of dots
      dots.length = 0;
      
      // Create a new dot based on the amount needed
      for (let i = 0; i < DOTS_AMOUNT; i++) {
        const theta = Math.random() * 2 * Math.PI; // Random value between [0, 2PI]
        const phi = Math.acos((Math.random() * 2) - 1); // Random value between [-1, 1]
        
        // Calculate the [x, y, z] coordinates of the dot along the globe
        const x = GLOBE_RADIUS * Math.sin(phi) * Math.cos(theta);
        const y = GLOBE_RADIUS * Math.sin(phi) * Math.sin(theta);
        const z = (GLOBE_RADIUS * Math.cos(phi)) + GLOBE_CENTER_Z;
        dots.push(new Dot(x, y, z));
      }
    }
    
    /* ====================== */
    /* ======== RENDER ====== */
    /* ====================== */
    function render(a) {
      // Clear the scene
      ctx.clearRect(0, 0, width, height);
      
      // Increase the globe rotation
      rotation = a * 0.0004;
      
      const sineRotation = Math.sin(rotation); // Sine of the rotation
      const cosineRotation = Math.cos(rotation); // Cosine of the rotation
      
      // Loop through the dots array and draw every dot
      for (var i = 0; i < dots.length; i++) {
        dots[i].draw(sineRotation, cosineRotation);
      }
      
      window.requestAnimationFrame(render);
    }
    
    
    // Function called after the user resized its screen
    function afterResize () {
      width = canvas.offsetWidth;
      height = canvas.offsetHeight;
      if (window.devicePixelRatio > 1) {
        canvas.width = canvas.clientWidth * 2;
        canvas.height = canvas.clientHeight * 2;
        ctx.scale(2, 2);
      } else {
        canvas.width = width;
        canvas.height = height;
      }
      GLOBE_RADIUS = width * 0.7;
      GLOBE_CENTER_Z = -GLOBE_RADIUS;
      PROJECTION_CENTER_X = width / 2;
      PROJECTION_CENTER_Y = height / 2;
      FIELD_OF_VIEW = width * 0.8;
      
      createDots(); // Reset all dots
    }
    
    // Variable used to store a timeout when user resized its screen
    let resizeTimeout;
    // Function called right after user resized its screen
    function onResize () {
      // Clear the timeout variable
      resizeTimeout = window.clearTimeout(resizeTimeout);
      // Store a new timeout to avoid calling afterResize for every resize event
      resizeTimeout = window.setTimeout(afterResize, 500);
    }
    window.addEventListener('resize', onResize);
    
    // Populate the dots array with random dots
    createDots();
    
    // Render the scene
    window.requestAnimationFrame(render);
    
    
    body {
      display: flex;
      margin: 0;
      align-items: center;
      justify-content: center;
      height: 100vh;
    }
    
    canvas {
      width: 98vmin;
      height: 98vmin;
    }
    
    
    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 4月6日
  • 创建了问题 8月30日