当前位置: 首页 > 工具软件 > GLOBE_3D > 使用案例 >

html5+3d球体相册,3D球,纯canvas实现

夏知
2023-12-01

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);

 类似资料: