Новогодняя ёлка на канвасе
Новогодняя ёлка на канвасе с помощью three.js
HTML
<div id="canvas"></div>
SCSS
body {
margin: 0;
padding: 0;
overflow: hidden;
background: #101011;
box-sizing: border-box;
width: 100vw;
height: 100vh;
}
#canvas {
position: absolute;
width: 100vw;
height: 100vh;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
button {
position: absolute;
bottom: -0.8rem;
left: 50%;
transform: translate(-50%, -50%);
margin: .5em;
border: solid .375em transparent;
padding: calc(.375em + 2px);
width: 13vh;
min-width: 2.5em;
height: 13vh;
min-height: 2.5em;
border-radius: 50%;
box-shadow: inset 0 0 0 2.75px #a961b8;
background: purple;
color: white;
background:
linear-gradient(#523535, #211b20) padding-box,
linear-gradient(#211b20, #523535) border-box;
transition: .75s;
cursor: pointer;
opacity: 0.0;
outline: solid 0 transparent;
}
button:hover {
outline: solid 0 transparent;
filter: saturate(120%) brightness(180%);
}
button:active {
outline: solid 0 transparent;
border-width: calc(.375em + 4px) .375em calc(.375em - 4px);
}
@media(max-width: 768px) {
button {
width: 5em;
height: 5em;
}
}
JS
Необходимо подключить three.jshttps://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js
https://s3-us-west-2.amazonaws.com/s.cdpn.io/264161/OrbitControls.js
скрипт/*--------------------
Settings
--------------------*/
let container, camera, scene, artwork, renderer
let windowHalfX = window.innerWidth / 2
let windowHalfY = window.innerHeight / 2
/*--------------------
Map
--------------------*/
const map = (value, x1, y1, x2, y2) => (value - x1) * (y2 - x2) / (y1 - x1) + x2;
/*--------------------
Resize
--------------------*/
const onWindowResize = () => {
camera.aspect = container.clientWidth / container.clientHeight
camera.updateProjectionMatrix()
renderer.setSize( container.clientWidth, container.clientHeight )
}
/*--------------------
Init
--------------------*/
init = () => {
container = document.querySelector( "#canvas" )
scene = new THREE.Scene()
createCamera()
createControls()
createLights()
createMeshes()
createRenderer()
document.addEventListener( "mousemove", mouseMove, false )
window.addEventListener( "resize", onWindowResize )
renderer.setAnimationLoop(() => {
render()
})
}
/*--------------------
Camera
--------------------*/
createCamera = () => {
camera = new THREE.PerspectiveCamera(
40,
window.innerWidth / window.innerHeight,
0.1,
10000,
)
camera.position.set( -25, 5, 20 )
}
/*--------------------
Controls
--------------------*/
function createControls() {
controls = new THREE.OrbitControls( camera, container )
controls.enabled = false
}
/*--------------------
Lights
--------------------*/
const createLights = () => {
const ambientLight = new THREE.HemisphereLight( 0xddeeff, 0x202020, 5 )
scene.add( ambientLight )
}
/*--------------------
Geometry
--------------------*/
const extraGeometry = () => {
let geometry = new THREE.Geometry();
const particlesLength = 2000
for ( var i = 0; i < particlesLength; i++ ) {
var vertex = new THREE.Vector3()
var color = new THREE.Vector3()
const d = map(i, 0, particlesLength, 0, Math.PI * 20)
vertex.x = i * 0.003 * Math.sin(d)
vertex.y = - i * 0.008 + (Math.sin(i * 3+ i * 0.5) * 0.2 )
vertex.z = i * 0.003 * Math.cos(d)
geometry.vertices.push( vertex )
geometry.colors.push(
new THREE.Color( '#952300' ),
new THREE.Color( '#dc1c27' ),
new THREE.Color( '#135c13' ),
new THREE.Color( '#fca12e' ),
)
}
let particles = new THREE.Points( geometry, new THREE.PointsMaterial({ vertexColors: THREE.VertexColors, size: 0.1 }))
let extraGroup = new THREE.Group()
extraGroup.add( particles )
return extraGroup
}
/*--------------------
Mesh
--------------------*/
const createMeshes = () => {
const sparklyBall = extraGeometry()
artwork = new THREE.Group()
artwork.position.y = 9
artwork.add(
sparklyBall
);
scene.add( artwork )
}
/*--------------------
Animate
--------------------*/
const animate = () => {
requestAnimationFrame(animate)
}
animate()
/*--------------------
Renderer
--------------------*/
const createRenderer = () => {
renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } )
renderer.setSize( window.innerWidth, window.innerHeight )
renderer.setPixelRatio( window.devicePixelRatio )
renderer.gammaFactor = 2.2
renderer.gammaOutput = true
renderer.physicallyCorrectLights = true
container.appendChild( renderer.domElement )
}
/*--------------------
Mousemove
--------------------*/
let mouseX = mouseY = 1
const mouseMove = ( event ) => {
isMouseMoved = true;
mouseX = ( event.clientX - windowHalfX );
mouseY = ( event.clientY - windowHalfY );
}
/*--------------------
Render
--------------------*/
const render = () => {
if ( artwork ) {
artwork.rotation.y += 0.001
}
renderer.render( scene, camera )
}
init()