@@ -0,0 +1,155 @@
import * as THREE from 'three';
import TWEEN from '@tweenjs/tween.js';
import Stats from 'libs/stats.min';

let stats;
let mouseX = 0;
let mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;

// Three Scene
let scene;
let camera;
let renderer;

const SEPARATION = 100;
const AMOUNTX = 10;
const AMOUNTY = 10;

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 initStats() {
stats = new Stats();
stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom
// document.body.appendChild(stats.dom);
}

function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(100, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 1000;

// const material = new THREE.SpriteMaterial();
const material = new THREE.SpriteMaterial({
map: new THREE.CanvasTexture(generateCanvasSprite()),
blending: THREE.AdditiveBlending,
});
for (let ix = 0; ix < AMOUNTX; ix += 1) {
for (let iz = 0; iz < AMOUNTY; iz += 1) {
const particle = new THREE.Sprite(material);
particle.scale.x = 16;
particle.scale.y = 16;

const mid = (AMOUNTX - 1) * (SEPARATION / 2);
const xd = ix * SEPARATION;
const zd = iz * SEPARATION;
const x = xd - mid;
const z = zd - mid;
particle.position.x = x;
particle.position.z = z;
const dest = {
x: x + Math.random() * 100 - 50,
y: Math.random() * 100 - 50,
};

// particle.position.y = z;
// const dest = {
// x: x + Math.random() * 100 - 50,
// z: Math.random() * 100 - 50,
// };

new TWEEN.Tween(particle.position)
.easing(TWEEN.Easing.Exponential.Out)
.to(dest, 1000)
.yoyo(true)
.repeat(Infinity)
.start();

scene.add(particle);
}
}

renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);

document.body.appendChild(renderer.domElement);
}
function animate() {
stats.update();
requestAnimationFrame(animate);
render();
}
function render() {
TWEEN.update();

camera.position.x += (mouseX - camera.position.x) * 0.05;
camera.position.y += (-mouseY - camera.position.y) * 0.05;
camera.lookAt(scene.position);

renderer.render(scene, camera);
}
function generateCanvasSprite() {
const canvas = document.createElement('canvas');
canvas.width = 16;
canvas.height = 16;

const context = canvas.getContext('2d');
const gradient = context.createRadialGradient(
canvas.width / 2,
canvas.height / 2,
0,
canvas.width / 2,
canvas.height / 2,
canvas.width / 2,
);
gradient.addColorStop(0, 'rgba(255,255,255,1)');
gradient.addColorStop(0.2, 'rgba(0,255,255,1)');
gradient.addColorStop(0.4, 'rgba(0,0,64,1)');
gradient.addColorStop(1, 'rgba(0,0,0,1)');

context.fillStyle = gradient;
context.fillRect(0, 0, canvas.width, canvas.height);

return canvas;
}

export default () => {
initStats();
init();
animate();

document.addEventListener('mousemove', onDocumentMouseMove, false);
document.addEventListener('touchstart', onDocumentTouchStart, false);
document.addEventListener('touchmove', onDocumentTouchMove, false);

window.addEventListener('resize', onWindowResize, false);
};
@@ -0,0 +1,63 @@
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
entry: {
main: './src/index.js',
three: './src/three/app.js',
},
output: {
path: path.resolve(__dirname, 'public/'),
publicPath: '/',
filename: './js/[name].[hash].bundle.js',
},
resolve: {
extensions: ['.js', '.jsx'],
alias: {
libs: path.resolve(__dirname, 'src/libs'),
},
},
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /(node_modules|public\/)/,
},
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader?url=false',
options: {
module: true,
localIdentName: '[name]__[local]--[hash:base64:5]',
},
},
],
exclude: ['node_modules'],
},
{
test: /\.(glsl|frag|vert)$/,
loader: 'raw-loader',
exclude: /node_modules/,
},
{
test: /\.(glsl|frag|vert)$/,
loader: 'glslify-loader',
exclude: /node_modules/,
},
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/template.html',
files: {
js: ['bundle.js'],
},
filename: 'index.html',
}),
],
};
@@ -1,30 +1,26 @@
const webpack = require('webpack');
const merge = require('webpack-merge');
const path = require('path');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const loaders = require('./webpack.loaders');
const common = require('./webpack.common.config.js');

module.exports = {
entry: {
main: './src/index.js',
three: './src/three/app.js',
},
output: {
path: path.resolve(__dirname, 'public/'),
publicPath: '/',
filename: './js/[name].[hash].bundle.js',
},
module: {
loaders,
},
// Dashboard
const Dashboard = require('webpack-dashboard');
const DashboardPlugin = require('webpack-dashboard/plugin');
const dashboard = new Dashboard();

module.exports = merge(common, {
plugins: [
new webpack.HotModuleReplacementPlugin(), // Enable HMR
new DashboardPlugin(dashboard.setData),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new BrowserSyncPlugin(
{
host: 'localhost',
port: 3001,
proxy: 'http://localhost:8080/',
logLevel: "silent",
files: [
{
match: ['**/*.html'],
@@ -37,23 +33,15 @@ module.exports = {
},
],
},
{
reload: false,
}
{ reload: false }
),
new HtmlWebpackPlugin({
template: './src/template.html',
files: {
js: ['bundle.js'],
},
filename: 'index.html',
}),
],
devServer: {
hot: true, // Tell the dev-server we're using HMR
hot: false, // Tell the dev-server we're using HMR
quiet: true,
contentBase: path.resolve(__dirname, 'public'),
publicPath: '/',
},
watch: true,
devtool: 'cheap-eval-source-map',
};
});

This file was deleted.

@@ -1,28 +1,17 @@
const webpack = require('webpack');
const merge = require('webpack-merge');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const loaders = require('./webpack.loaders');
const common = require('./webpack.common.config.js');

module.exports = {
entry: {
three: './src/three/app.js',
},
output: {
path: path.resolve(__dirname, 'public/'),
publicPath: '/',
filename: './js/[name].[hash].bundle.js',
},
module: {
loaders,
},
module.exports = merge(common, {
plugins: [
new webpack.NamedModulesPlugin(),
new HtmlWebpackPlugin({
template: './src/template.html',
files: {
js: ['bundle.js'],
},
filename: 'index.html',
new UglifyJSPlugin({
sourceMap: true
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
],
};
});
682 yarn.lock

Large diffs are not rendered by default.