123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- /*
- * <<
- * Davinci
- * ==
- * Copyright (C) 2016 - 2017 EDP
- * ==
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * >>
- */
- import React from 'react'
- import { DEFAULT_SECONDARY_COLOR } from 'app/globalConstants'
- const styles = require('./Background.less')
- import { PerspectiveCamera } from 'three/src/cameras/PerspectiveCamera'
- import { Scene } from 'three/src/scenes/Scene'
- import { BufferAttribute } from 'three/src/core/BufferAttribute'
- import { BufferGeometry } from 'three/src/core/BufferGeometry'
- import { Color } from 'three/src/math/Color'
- import { Points } from 'three/src/objects/Points'
- import { ShaderMaterial } from 'three/src/materials/ShaderMaterial'
- import { WebGLRenderer } from 'three/src/renderers/WebGLRenderer'
- export class Canvas extends React.Component<{}, {}> {
- constructor (props) {
- super(props)
- }
- private removeListeners: () => any = null
- private container = React.createRef<HTMLDivElement>()
- public componentDidMount () {
- // TODO to verify the performance under one or multiple chunks
- this.drawBackground()
- }
- public componentWillUnmount () {
- if (this.removeListeners) {
- this.removeListeners()
- }
- }
- private drawBackground = () => {
- const SEPARATION = 100
- const AMOUNTX = 50
- const AMOUNTY = 50
- let camera
- let scene
- let renderer
- let particles
- let count = 0
- let mouseX = 0
- let mouseY = 0
- let windowHalfX = window.innerWidth / 2
- let windowHalfY = window.innerHeight / 2
- const init = () => {
- const container = this.container.current
- camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000)
- camera.position.z = 1000
- scene = new Scene()
- const numParticles = AMOUNTX * AMOUNTY
- const positions = new Float32Array(numParticles * 3)
- const scales = new Float32Array(numParticles)
- let i = 0
- let j = 0
- for (let ix = 0; ix < AMOUNTX; ix++) {
- for (let iy = 0; iy < AMOUNTY; iy++) {
- positions[i] = ix * SEPARATION - ((AMOUNTX * SEPARATION) / 2) // x
- positions[i + 1] = 0 // y
- positions[i + 2] = iy * SEPARATION - ((AMOUNTY * SEPARATION) / 2) // z
- scales[j] = 1
- i += 3
- j++
- }
- }
- const geometry = new BufferGeometry()
- geometry.addAttribute('position', new BufferAttribute(positions, 3))
- geometry.addAttribute('scale', new BufferAttribute(scales, 1))
- const material = new ShaderMaterial({
- uniforms: {
- color: {
- value: new Color(0xffffff)
- }
- },
- vertexShader: document.getElementById('vertexshader').textContent,
- fragmentShader: document.getElementById('fragmentshader').textContent
- })
- //
- particles = new Points(geometry, material)
- scene.add(particles)
- renderer = new WebGLRenderer({ antialias: true })
- renderer.setPixelRatio(window.devicePixelRatio || 1)
- renderer.setSize(window.innerWidth, window.innerHeight)
- renderer.setClearColor(parseInt(DEFAULT_SECONDARY_COLOR.substr(1), 16))
- container.appendChild(renderer.domElement)
- document.addEventListener('mousemove', onDocumentMouseMove, false)
- container.addEventListener('touchstart', onDocumentTouchStart, false)
- container.addEventListener('touchmove', onDocumentTouchMove, false)
- window.addEventListener('resize', onWindowResize, false)
- this.removeListeners = () => {
- document.removeEventListener('mousemove', onDocumentMouseMove, false)
- container.removeEventListener('touchstart', onDocumentTouchStart, false)
- container.removeEventListener('touchmove', onDocumentTouchMove, false)
- window.removeEventListener('resize', onWindowResize, false)
- }
- }
- function onWindowResize () {
- windowHalfX = window.innerWidth / 2
- windowHalfY = window.innerHeight / 2
- camera.aspect = window.innerWidth / window.innerHeight
- camera.updateProjectionMatrix()
- renderer.setSize(window.innerWidth, window.innerHeight)
- }
- function onDocumentMouseMove (event) {
- mouseX = event.clientX - windowHalfX
- mouseY = event.clientY - windowHalfY
- }
- function onDocumentTouchStart (event) {
- if (event.touches.length === 1) {
- event.preventDefault()
- mouseX = event.touches[0].pageX - windowHalfX
- mouseY = event.touches[0].pageY - windowHalfY
- }
- }
- function onDocumentTouchMove (event) {
- if (event.touches.length === 1) {
- event.preventDefault()
- mouseX = event.touches[0].pageX - windowHalfX
- mouseY = event.touches[0].pageY - windowHalfY
- }
- }
- function animate () {
- requestAnimationFrame(animate)
- render()
- }
- function render () {
- camera.position.x += (mouseX - camera.position.x) * .05
- camera.position.y += (-mouseY - camera.position.y) * .05
- camera.lookAt(scene.position)
- const positions = particles.geometry.attributes.position.array
- const scales = particles.geometry.attributes.scale.array
- let i = 0
- let j = 0
- for (let ix = 0; ix < AMOUNTX; ix++) {
- for (let iy = 0; iy < AMOUNTY; iy++) {
- positions[i + 1] = (Math.sin((ix + count) * 0.3) * 50) +
- (Math.sin((iy + count) * 0.5) * 50)
- scales[j] = (Math.sin((ix + count) * 0.3) + 1) * 8 +
- (Math.sin((iy + count) * 0.5) + 1) * 8
- i += 3
- j++
- }
- }
- particles.geometry.attributes.position.needsUpdate = true
- particles.geometry.attributes.scale.needsUpdate = true
- renderer.render(scene, camera)
- count += 0.1
- }
- init()
- animate()
- }
- public render () {
- return (
- <div ref={this.container} className={styles.background}/>
- )
- }
- }
- export default Canvas
|