<div id="myCanvas"></div>
body {
margin: 0;
background-image: radial-gradient(#800080, #000000);
}
'use strict';
/**
* default
**/
let scene = null,
camera = null,
renderer = null,
controls = null,
pumpkin = null,
moon = null,
floor = null,
cross = null,
branch = null,
coffin = null,
bat = null,
width = 0,
height = 0;
/**
* init
**/
function init() {
width = window.innerWidth,
height = window.innerHeight;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, width / height);
camera.position.set(0, 160, 1100);
renderer = new THREE.WebGLRenderer({
alpha: true
});
renderer.setPixelRatio(
window.devicePixelRatio
);
renderer.setSize(width, height);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
controls = new THREE.OrbitControls(camera, renderer.domElement);
addLights();
drawPumpkin();
drawCross();
drawBranch();
drawCoffin();
drawFloor();
drawMoon();
drawBat();
document.getElementById('myCanvas').appendChild(renderer.domElement);
window.addEventListener('resize',onResize,false);
}
/**
* lights
**/
function addLights() {
const directLight1 = new THREE.DirectionalLight(0xffffff);
directLight1.castShadow = true;
directLight1.position.set(0, 1, 1);
scene.add(directLight1);
const pointLight = new THREE.PointLight(0xffffff, 2, 1000);
scene.add(pointLight);
}
/**
* draw
**/
function drawPumpkin() {
pumpkin = new Pumpkin();
scene.add(pumpkin.group);
}
function drawCross() {
cross = new Cross();
scene.add(cross.group);
}
function drawBranch() {
branch = new Branch();
scene.add(branch.group);
}
function drawCoffin() {
coffin = new Coffin();
scene.add(coffin.group);
}
function drawFloor() {
floor = new Floor();
scene.add(floor.group);
}
function drawMoon() {
moon = new Moon();
scene.add(moon.group);
}
function drawBat() {
bat = new Bat();
scene.add(bat.group);
}
/**
* resize
**/
function onResize() {
width = window.innerWidth;
height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
}
/**
* degree
**/
function degree(degrees) {
return degrees * (Math.PI / 180);
}
/**
* animate
**/
function animate() {
requestAnimationFrame(animate);
render();
}
/**
* render
**/
function render() {
scene.rotation.y += 0.01;
pumpkin.moveBody();
bat.moveBody();
bat.moveWings();
renderer.render(scene, camera);
}
/**
* Pumpkin
**/
class Pumpkin {
constructor() {
this.group = new THREE.Group();
this.bodyangle = 0;
this.group.position.set(0, 0, 0);
this.group.rotation.set(0, 0, 0);
this.drawHead();
this.drawBody(0,0,0, 0,0,0);
this.drawBody(0,0,0, 0,degree(90),0);
this.drawBody(0,0,0, 0,degree(45),0);
this.drawBody(0,0,0, 0,degree(-45),0);
this.draweye(60,80, 20,-30,-20, -30,-20, 20, 70, 70, 190, degree(-30), degree(30), 0);
this.draweye(80,60, -20,30,-20, -30,20,-20, -70, 70, 190, degree(-30), degree(-30), degree(90));
this.drawmouth(0, 100, 0, -50, -50, -50, 0, 40, 90, -10, 210, 0, degree(20), degree(-30));
this.drawmouth_mdl(30, -10, 225, 0, 0, -.5);
this.drawmouth_mdl(-23, -10, 225, 0, 0, .5);
this.drawmouth(100, 0, -50, 0, -50, -50, 40, 0, -80, -10, 210, 0, degree(-20), degree(120));
}
drawHead() {
const head_geometry = new THREE.CylinderGeometry(10,10,40,50)
, head_material = new THREE.MeshPhongMaterial({color: 648035})
, head_box = new THREE.Mesh(head_geometry,head_material);
head_box.position.set(0, 180, 0);
head_box.rotation.set(0, 0, 0);
this.group.add(head_box);
}
drawBody(a,b,c,d,e,f) {
const pumpkin_geometry = new THREE.ParametricGeometry(
function( u, v, target ) {
u = u * Math.PI;
v = v * 2 * Math.PI;
var x = 140 * Math.sin(u) * Math.cos(v);
var y = 170 * Math.sin(u) * Math.sin(v);
var z = 220 * Math.cos(u);
target.set( x, y, z );
}, 500, 500, true
);
const pumpkin_material = new THREE.MeshPhongMaterial({color: 0xF68636});
const pumpkin_box = new THREE.Mesh(pumpkin_geometry,pumpkin_material);
pumpkin_box.position.set(a, b, c);
pumpkin_box.rotation.set(d, e, f);
this.group.add(pumpkin_box);
}
draweye(a,b,c,d,e,f,g,h,i,j,k,l,m,n){
const eye_material = new THREE.MeshBasicMaterial({color: 0xd80202})
, eye = new THREE.Shape();
eye.moveTo(a,b);
eye.bezierCurveTo(c,d,e,f,g,h);
const eye_geometry = new THREE.ShapeGeometry(eye)
, eye_box = new THREE.Mesh(eye_geometry,eye_material);
eye_box.position.set(i, j, k);
eye_box.rotation.set(l, m, n);
this.group.add(eye_box);
}
drawmouth(a,b,c,d,e,f,g,h,i,j,k,l,m,n) {
const mouth_material = new THREE.MeshBasicMaterial({color: 0xd80202})
, shape = new THREE.Shape();
shape.moveTo(a, b);
shape.lineTo(c, d);
shape.lineTo(e, f);
shape.lineTo(g, h);
const mouth_geometry = new THREE.ShapeGeometry( shape )
, mouth_box = new THREE.Mesh(mouth_geometry, mouth_material);
mouth_box.position.set(i, j, k);
mouth_box.rotation.set(l, m, n);
this.group.add( mouth_box );
}
drawmouth_mdl(a,b,c,d,e,f) {
const mouth_geometry = new THREE.BoxGeometry(80, 40, 1)
, mouth_material = new THREE.MeshBasicMaterial({color: 0xd80202})
, mouth_box = new THREE.Mesh(mouth_geometry, mouth_material);
mouth_box.position.set(a, b, c);
mouth_box.rotation.set(d, e, f);
this.group.add(mouth_box);
}
moveBody() {
this.bodyangle += 0.05;
const bodyamplitude = 30;
this.group.position.y = 30 - (Math.cos(this.bodyangle) * bodyamplitude);
}
}
/**
* Cross
**/
class Cross {
constructor() {
this.group = new THREE.Group();
this.group.position.set(-500, 50, 300);
this.wingangle = 0;
this.beside();
this.vertical();
this.crossfloor();
this.crossfloor2();
}
beside() {
const corss_beside_geometry = new THREE.BoxGeometry( 50, 350, 50 );
const corss_beside_material = new THREE.MeshPhongMaterial({color: 0x797979});
const corss_beside = new THREE.Mesh(corss_beside_geometry, corss_beside_material);
corss_beside.position.set(0, 50, 0);
this.group.add(corss_beside);
}
vertical() {
const corss_beside_geometry = new THREE.BoxGeometry( 200, 50, 50 );
const corss_beside_material = new THREE.MeshPhongMaterial({color: 0x797979});
const corss_beside = new THREE.Mesh(corss_beside_geometry, corss_beside_material);
corss_beside.position.set(0, 100, 0);
this.group.add(corss_beside);
}
crossfloor() {
const corss_beside_geometry = new THREE.BoxGeometry( 200, 100, 200);
const corss_beside_material = new THREE.MeshPhongMaterial({color: 0x363636});
const corss_beside = new THREE.Mesh(corss_beside_geometry, corss_beside_material);
corss_beside.position.set(0, -150, 0);
this.group.add(corss_beside);
}
crossfloor2() {
const corss_beside_geometry = new THREE.BoxGeometry( 300, 50, 300);
const corss_beside_material = new THREE.MeshPhongMaterial( {color: 0x363636} );
const corss_beside = new THREE.Mesh(corss_beside_geometry, corss_beside_material);
corss_beside.position.set(0, -175, 0);
this.group.add(corss_beside);
}
}
/**
* Branch
**/
class Branch {
constructor() {
this.group = new THREE.Group();
this.group.position.set(-500, 100, -200);
this.wingangle = 0;
this.vertical();
this.branch();
this.branch2();
this.branch3();
this.branch4();
}
vertical() {
const corss_beside_geometry = new THREE.CylinderGeometry( 1, 20, 600, 100);
const corss_beside_material = new THREE.MeshPhongMaterial( {color: 0x443020} );
const corss_beside = new THREE.Mesh(corss_beside_geometry, corss_beside_material);
corss_beside.position.set(0, 0, 0);
this.group.add(corss_beside);
}
branch() {
const branch_geometry = new THREE.TorusGeometry( 300, 5, 100, 100, degree(30) )
const branch_material = new THREE.MeshPhongMaterial( {color: 0x443020} );
const branch_mesh = new THREE.Mesh( branch_geometry, branch_material );
branch_mesh.position.set(0, 300, 0);
branch_mesh.rotation.set(0, 0, degree(-90));
this.group.add( branch_mesh );
}
branch2() {
const branch_geometry = new THREE.TorusGeometry( 300, 3, 100, 100, degree(30) )
const branch_material = new THREE.MeshPhongMaterial( {color: 0x443020} );
const branch_mesh = new THREE.Mesh( branch_geometry, branch_material );
branch_mesh.position.set(0, 500, 0);
branch_mesh.rotation.set(0, 0, degree(-120));
this.group.add( branch_mesh );
}
branch3() {
const branch_geometry = new THREE.TorusGeometry( 400, 5, 100, 100, degree(30) )
const branch_material = new THREE.MeshPhongMaterial( {color: 0x443020} );
const branch_mesh = new THREE.Mesh( branch_geometry, branch_material );
branch_mesh.position.set(0, 450, 0);
branch_mesh.rotation.set(0, degree(-45), degree(-120));
this.group.add( branch_mesh );
}
branch4() {
const branch_geometry = new THREE.TorusGeometry( 300, 4, 100, 100, degree(30) )
const branch_material = new THREE.MeshPhongMaterial( {color: 0x443020} );
const branch_mesh = new THREE.Mesh( branch_geometry, branch_material );
branch_mesh.position.set(0, 450, 0);
branch_mesh.rotation.set(0, degree(150), degree(-120));
this.group.add( branch_mesh );
}
}
/**
* Coffin
**/
class Coffin {
constructor() {
this.group = new THREE.Group();
this.group.position.set(-100, -50, 350);
this.drawBody();
this.drawBody2();
this.drawBody3();
this.drawBody4();
this.drawBody5();
this.drawBody6();
}
drawBody() {
const ciffin_material = new THREE.MeshPhongMaterial({color: 0x000000})
, ciffines = new THREE.Shape();
ciffines.moveTo(0, 500)
, ciffines.lineTo(200, 700)
, ciffines.lineTo(400, 500)
, ciffines.lineTo(300, -200)
, ciffines.lineTo(100, -200)
, ciffines.lineTo(0, 500)
const ciffin_geometry = new THREE.ShapeGeometry( ciffines )
, ciffines_box = new THREE.Mesh( ciffin_geometry, ciffin_material );
ciffines_box.position.set(400, 0, 0);
ciffines_box.rotation.set(degree(-90), 0, 0);
this.group.add(ciffines_box);
}
drawBody2() {
const ciffin_material = new THREE.MeshPhongMaterial({color: 0x000000})
, ciffines = new THREE.Shape();
ciffines.moveTo(0, -100)
, ciffines.lineTo(200, -100)
, ciffines.lineTo(200, 0)
, ciffines.lineTo(0, 0)
const ciffin_geometry = new THREE.ShapeGeometry( ciffines )
, ciffines_box = new THREE.Mesh( ciffin_geometry, ciffin_material );
ciffines_box.position.set(500, 0, 200);
ciffines_box.rotation.set(0, 0, 0);
this.group.add(ciffines_box);
}
drawBody3() {
const ciffin_material = new THREE.MeshPhongMaterial({color: 0x000000})
, ciffines = new THREE.Shape();
ciffines.moveTo(0, -100)
, ciffines.lineTo(-705, -100)
, ciffines.lineTo(-705, 0)
, ciffines.lineTo(0, 0)
const ciffin_geometry = new THREE.ShapeGeometry( ciffines )
, ciffines_box = new THREE.Mesh( ciffin_geometry, ciffin_material );
ciffines_box.position.set(500, 0, 200);
ciffines_box.rotation.set(0, degree(-82), 0);
this.group.add(ciffines_box);
}
drawBody4() {
const ciffin_material = new THREE.MeshPhongMaterial({color: 0x000000})
, ciffines = new THREE.Shape();
ciffines.moveTo(0, -100)
, ciffines.lineTo(705, -100)
, ciffines.lineTo(705, 0)
, ciffines.lineTo(0, 0)
const ciffin_geometry = new THREE.ShapeGeometry( ciffines )
, ciffines_box = new THREE.Mesh( ciffin_geometry, ciffin_material );
ciffines_box.position.set(700, 0, 200);
ciffines_box.rotation.set(0, degree(82), 0);
this.group.add(ciffines_box);
}
drawBody5() {
const ciffin_material = new THREE.MeshPhongMaterial({color: 0x000000})
, ciffines = new THREE.Shape();
ciffines.moveTo(0, -100)
, ciffines.lineTo(285, -100)
, ciffines.lineTo(285, 0)
, ciffines.lineTo(0, 0)
const ciffin_geometry = new THREE.ShapeGeometry( ciffines )
, ciffines_box = new THREE.Mesh( ciffin_geometry, ciffin_material );
ciffines_box.position.set(600, 0, -700);
ciffines_box.rotation.set(0, degree(-135), 0);
this.group.add(ciffines_box);
}
drawBody6() {
const ciffin_material = new THREE.MeshPhongMaterial({color: 0x000000})
, ciffines = new THREE.Shape();
ciffines.moveTo(0, -100)
, ciffines.lineTo(-285, -100)
, ciffines.lineTo(-285, 0)
, ciffines.lineTo(0, 0)
const ciffin_geometry = new THREE.ShapeGeometry( ciffines )
, ciffines_box = new THREE.Mesh( ciffin_geometry, ciffin_material );
ciffines_box.position.set(600, 0, -700);
ciffines_box.rotation.set(0, degree(135), 0);
this.group.add(ciffines_box);
}
}
/**
* Floor
**/
class Floor {
constructor() {
this.group = new THREE.Group();
this.group.position.set(0, -150, 0);
this.group.rotation.set(degree(-90), 0, 0);
this.wingangle = 0;
this.drawBody();
}
drawBody() {
const plane = new THREE.PlaneGeometry(3000, 3000, 64, 64);
const material = new THREE.MeshStandardMaterial( {color: 0x582C1D, side: THREE.DoubleSide} );
const plane_box = new THREE.Mesh( plane, material);
this.group.add(plane_box);
}
}
/**
* Moon
**/
class Moon {
constructor() {
this.group = new THREE.Group();
this.group.position.set(100, 400, 900);
this.wingangle = 0;
this.drawBody();
}
drawBody() {
const moon = new THREE.SphereBufferGeometry(50, 50, 50);
const moon_texture = new THREE.TextureLoader().load('https://threejs-plactice.vercel.app/earth/img/moon.jpg');
const moon_materials = new THREE.MeshStandardMaterial( { color: 0xffffff, map:moon_texture } );
const moon_box_mesh = new THREE.Mesh( moon, moon_materials );
this.group.add(moon_box_mesh);
}
}
/**
* Bat
**/
class Bat {
constructor() {
this.group = new THREE.Group();
this.group.position.set(300, 300, 100);
this.group.rotation.set(0, degree(-90), 0);
this.wingangle = 0;
this.bodyangle = 0;
this.drawBody();
this.drawWings();
this.drawWings_back();
}
drawear(a,b,c,d,e,f) {
let ear_material = new THREE.MeshLambertMaterial({color: 0x000000,wireframe:false});
let ear = new THREE.Mesh(new THREE.TetrahedronGeometry(20), ear_material);
ear.position.set(a, b, c);
ear.rotation.set(d, degree(e), f);
this.group.add( ear );
}
drawBody() {
/**
* bat_body
**/
const batGeometry = new THREE.ParametricGeometry(
function( u, v, target ) {
u = u * Math.PI;
v = v * 2 * Math.PI;
var x = 60 * Math.sin(u) * Math.cos(v);
var y = 25 * Math.sin(u) * Math.sin(v);
var z = 25 * Math.cos(u);
target.set( x, y, z );
}, 80, 80, true
);
const batmaterial = new THREE.MeshPhongMaterial({color: 0x000000});
const bat = new THREE.Mesh(batGeometry,batmaterial);
bat.position.set( -30, 0, 0 );
this.group.add(bat);
/**
* ear_right
**/
this.drawear(10, 5, -20, 0, 115, 0);
/**
* ear_left
**/
this.drawear(10, 5, 20, 0, -15, 0);
}
drawWings() {
const splash_material = new THREE.MeshPhongMaterial({color: 0x000000})
, shape = new THREE.Shape();
shape.moveTo(0, 0);
shape.lineTo(20, -70);
shape.lineTo(0, -150);
shape.lineTo(-80, -100);
shape.lineTo(-40, -40);
shape.lineTo(-40, 0);
const splash_geometry = new THREE.ShapeGeometry(shape),
splash_box = new THREE.Mesh(splash_geometry, splash_material);
/**
* rightwing
**/
this.rightWing = splash_box;
this.rightWing.position.set(0, 0, 20);
this.rightWing.rotation.set(0, 0, 0);
this.group.add(this.rightWing);
/**
* leftwing
**/
this.leftWing = this.rightWing.clone();
this.leftWing.position.z = -this.rightWing.position.z;
this.group.add(this.leftWing);
}
drawWings_back() {
const splash_material = new THREE.MeshPhongMaterial({color: 0x000000})
const shape_back = new THREE.Shape();
shape_back.moveTo(40, 0 );
shape_back.lineTo(40, -40 );
shape_back.lineTo(80, -100);
shape_back.lineTo(0, -150 );
shape_back.lineTo(-20, -70 );
shape_back.lineTo(0, 0 );
const splash_geometry_back = new THREE.ShapeGeometry( shape_back ),
splash_box_back = new THREE.Mesh( splash_geometry_back, splash_material );
/**
* rightwing
**/
this.rightWing_back = splash_box_back;
this.rightWing_back.position.set(0, 0, 20);
this.rightWing_back.rotation.set(0, degree(-180), 0);
this.group.add(this.rightWing_back);
/**
* leftwing
**/
this.leftWing_back = this.rightWing_back.clone();
this.leftWing_back.position.z = -this.rightWing_back.position.z;
this.group.add(this.leftWing_back);
}
moveBody() {
const bodyamplitude = 30;
this.bodyangle += 0.05;
this.group.position.y = 300 - (Math.cos(this.bodyangle) * bodyamplitude);
}
moveWings() {
this.wingangle += .5;
const wingamplitude = degree(20);
this.rightWing.rotation.x = degree(-90) - (Math.cos(this.wingangle) * wingamplitude);
this.leftWing.rotation.x = degree(90) + (Math.cos(this.wingangle) * wingamplitude);
this.rightWing_back.rotation.x = degree(-90) - (Math.cos(this.wingangle) * wingamplitude);
this.leftWing_back.rotation.x = degree(-90) + (Math.cos(this.wingangle) * wingamplitude);
}
}
init();
animate();
This Pen doesn't use any external CSS resources.