国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

JavaScript+canvas實現(xiàn)一個旋轉的3D球動畫效果

這篇具有很好參考價值的文章主要介紹了JavaScript+canvas實現(xiàn)一個旋轉的3D球動畫效果。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

效果

canvas實現(xiàn)的動態(tài)3d旋轉球體,JavaScript,javascript,3d


實現(xiàn)過程

1. 獲取Canvas元素和設置初始參數(shù)

// 獲取Canvas元素
const canvas = document.querySelector('#scene');
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
const ctx = canvas.getContext('2d');

// 針對高DPI屏幕進行縮放
if (window.devicePixelRatio > 1) {
    canvas.width = canvas.clientWidth * 2;
    canvas.height = canvas.clientHeight * 2;
    ctx.scale(2, 2);
}

// Canvas的寬度和高度
let width = canvas.clientWidth;
let height = canvas.clientHeight;
// 球體旋轉的角度
let rotation = 0;
// 存儲所有點的數(shù)組
let dots = [];

這部分代碼主要是獲取Canvas元素,并根據(jù)設備的DPI進行縮放。然后,定義了一些全局變量,包括Canvas的寬度、高度、球體旋轉的角度和存儲所有點的數(shù)組。


2. 定義一些常量

// 一些常量
const DOTS_AMOUNT = 1000; // 點的數(shù)量
const DOT_RADIUS = 2; // 點的半徑
let GLOBE_RADIUS = width * 0.7; // 球半徑
let GLOBE_CENTER_Z = -GLOBE_RADIUS; // 球心的Z坐標
let PROJECTION_CENTER_X = width / 2; // 畫布HTML的X中心
let PROJECTION_CENTER_Y = height / 2; // 畫布HTML的Y中心
let FIELD_OF_VIEW = width * 0.8;

這部分代碼定義了一些常量,如點的數(shù)量、點的半徑、球半徑等。


3.定義點(Dot)類

// Dot類表示每個點的屬性
class Dot {
    constructor(x, y, z, color) {
        this.x = x;
        this.y = y;
        this.z = z;
        this.color = color; // 添加顏色屬性

        this.xProject = 0;
        this.yProject = 0;
        this.sizeProjection = 0;
    }

    // 將三維坐標映射到二維畫布上
    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(sin, cos) {
        this.project(sin, cos);
        ctx.beginPath();
        ctx.arc(this.xProject, this.yProject, DOT_RADIUS * this.sizeProjection, 0, Math.PI * 2);
        ctx.fillStyle = this.color; // 使用粒子的顏色屬性
        ctx.closePath();
        ctx.fill();
    }
}

這部分代碼定義了一個Dot類,表示球體上的每個點的屬性和方法。包括構造函數(shù)、將三維坐標映射到二維畫布上的project方法,以及在畫布上繪制點的draw方法


4.創(chuàng)建和渲染球體的函數(shù)

// 創(chuàng)建所有點的函數(shù)
function createDots() {
    // 清空粒子數(shù)組
    dots.length = 0;

    // 創(chuàng)建一半藍色粒子
    for (let i = 0; i < DOTS_AMOUNT / 2; i++) {
        const theta = Math.random() * 2 * Math.PI;
        const phi = Math.acos((Math.random() * 2) - 1);
        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, '#981898'));
    }

    // 創(chuàng)建一半紅色粒子
    for (let i = 0; i < DOTS_AMOUNT / 2; i++) {
        const theta = Math.random() * 2 * Math.PI;
        const phi = Math.acos((Math.random() * 2) - 1);
        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, '#E71751'));
    }
}

這部分代碼定義了createDots函數(shù),用于生成一定數(shù)量的點,并分別將一半標記為藍色,一半標記為紅色。這里可以根據(jù)需求改動,


// 渲染函數(shù),不斷更新球體的旋轉
function render(a) {
   ctx.clearRect(0, 0, width, height);
   rotation = a * 0.0004;
   const sineRotation = Math.sin(rotation);
   const cosineRotation = Math.cos(rotation);

   // 遍歷所有點并繪制
   for (var i = 0; i < dots.length; i++) {
       dots[i].draw(sineRotation, cosineRotation);
   }

   window.requestAnimationFrame(render);
}

這部分代碼定義了render函數(shù),用于在每一幀更新球體的旋轉角度,并循環(huán)繪制所有的點,產生連續(xù)的旋轉效果。

5.監(jiān)聽窗口大小變化事件

// 當用戶調整窗口大小時重新計算參數(shù)
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(); // 重新生成所有點
}

// 變量用于存儲用戶調整窗口大小時的超時
let resizeTimeout;

// 當用戶調整窗口大小時觸發(fā)的函數(shù)
function onResize() {
    resizeTimeout = window.clearTimeout(resizeTimeout);
    resizeTimeout = window.setTimeout(afterResize, 500);
}

// 監(jiān)聽窗口大小變化事件
window.addEventListener('resize', onResize);

這部分代碼用于監(jiān)聽窗口大小變化事件,并在用戶調整窗口大小時重新計算參數(shù),以保持效果的穩(wěn)定性。

最后初始化一下就好了

// 初始化點數(shù)組
createDots();

// 渲染場景
window.requestAnimationFrame(render);

完整代碼文章來源地址http://www.zghlxwxcb.cn/news/detail-801094.html

<!DOCTYPE html>
<html lang="en">

<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>3D旋轉球體</title>
   <style>
       body {
           height: 100vh;
           display: flex;
           justify-content: center;
           align-items: center;
           background: #000;
           margin: 0;
       }

       canvas {
           width: 500px;
           height: 500px;
       }
   </style>
</head>

<body>
   <canvas id="scene"></canvas>
   <script>
       // 獲取Canvas元素
       const canvas = document.querySelector('#scene');
       canvas.width = canvas.clientWidth;
       canvas.height = canvas.clientHeight;
       const ctx = canvas.getContext('2d');

       // 針對高DPI屏幕進行縮放
       if (window.devicePixelRatio > 1) {
           canvas.width = canvas.clientWidth * 2;
           canvas.height = canvas.clientHeight * 2;
           ctx.scale(2, 2);
       }

       // Canvas的寬度和高度
       let width = canvas.clientWidth;
       let height = canvas.clientHeight;
       // 球體旋轉的角度
       let rotation = 0;
       // 存儲所有點的數(shù)組
       let dots = [];

       // 一些常量
       const DOTS_AMOUNT = 1000; // 點的數(shù)量
       const DOT_RADIUS = 2; // 點的半徑
       let GLOBE_RADIUS = width * 0.7; // 球半徑
       let GLOBE_CENTER_Z = -GLOBE_RADIUS; // 球心的Z坐標
       let PROJECTION_CENTER_X = width / 2; // 畫布HTML的X中心
       let PROJECTION_CENTER_Y = height / 2; // 畫布HTML的Y中心
       let FIELD_OF_VIEW = width * 0.8;

       // Dot類表示每個點的屬性
       class Dot {
           constructor(x, y, z, color) {
               this.x = x;
               this.y = y;
               this.z = z;
               this.color = color; // 添加顏色屬性

               this.xProject = 0;
               this.yProject = 0;
               this.sizeProjection = 0;
           }

           // 將三維坐標映射到二維畫布上
           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(sin, cos) {
               this.project(sin, cos);
               ctx.beginPath();
               ctx.arc(this.xProject, this.yProject, DOT_RADIUS * this.sizeProjection, 0, Math.PI * 2);
               ctx.fillStyle = this.color; // 使用粒子的顏色屬性
               ctx.closePath();
               ctx.fill();
           }
       }

       // 創(chuàng)建所有點的函數(shù)
       function createDots() {
           // 清空粒子數(shù)組
           dots.length = 0;

           // 創(chuàng)建一半藍色粒子
           for (let i = 0; i < DOTS_AMOUNT / 2; i++) {
               const theta = Math.random() * 2 * Math.PI;
               const phi = Math.acos((Math.random() * 2) - 1);
               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, '#981898'));
           }

           // 創(chuàng)建一半紅色粒子
           for (let i = 0; i < DOTS_AMOUNT / 2; i++) {
               const theta = Math.random() * 2 * Math.PI;
               const phi = Math.acos((Math.random() * 2) - 1);
               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, '#E71751'));
           }
       }

       // 渲染函數(shù),不斷更新球體的旋轉
       function render(a) {
           ctx.clearRect(0, 0, width, height);
           rotation = a * 0.0004;
           const sineRotation = Math.sin(rotation);
           const cosineRotation = Math.cos(rotation);

           // 遍歷所有點并繪制
           for (var i = 0; i < dots.length; i++) {
               dots[i].draw(sineRotation, cosineRotation);
           }

           window.requestAnimationFrame(render);
       }

       // 當用戶調整窗口大小時重新計算參數(shù)
       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(); // 重新生成所有點
       }

       // 變量用于存儲用戶調整窗口大小時的超時
       let resizeTimeout;

       // 當用戶調整窗口大小時觸發(fā)的函數(shù)
       function onResize() {
           resizeTimeout = window.clearTimeout(resizeTimeout);
           resizeTimeout = window.setTimeout(afterResize, 500);
       }

       // 監(jiān)聽窗口大小變化事件
       window.addEventListener('resize', onResize);

       // 初始化點數(shù)組
       createDots();

       // 渲染場景
       window.requestAnimationFrame(render);
   </script>
</body>

</html>

到了這里,關于JavaScript+canvas實現(xiàn)一個旋轉的3D球動畫效果的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包