Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
771 changes: 771 additions & 0 deletions public/cd-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion public/vite.svg

This file was deleted.

3 changes: 1 addition & 2 deletions src/components/three-background/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import "./styles.css";
import {initCamera, initCanvas, initScene, initStage, renderer} from "./scene.ts";
import {initCamera, initScene, initStage, renderer} from "./scene.ts";
import {initBgMeshes} from "./particules.ts";
import {initPostProcess} from "./post-process.ts";
import {animate} from "./animation-loop.ts";
Expand All @@ -9,7 +9,6 @@ import {animate} from "./animation-loop.ts";
export function animatedBackground() {
initStage();
initScene();
initCanvas();
initCamera();
initBgMeshes();
initPostProcess();
Expand Down
13 changes: 3 additions & 10 deletions src/components/three-background/scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ export let renderer: THREE.WebGLRenderer,
windowWidth = window.innerWidth,
windowHeight = window.innerHeight;

let graphicCanvas,
canvasWidth = 240,
canvasHeight = 240,
mouseX = 0,
let mouseX = 0,
mouseY = 0,
windowHalfWidth: number,
windowHalfHeight: number;
Expand All @@ -31,7 +28,7 @@ export const initStage = () => {
export const initScene = () => {
scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x010102, 1, 3000);
scene.add( new THREE.AmbientLight( 0xcccccc ) );
scene.add( new THREE.AmbientLight( 0x000000 ) );


renderer = new THREE.WebGLRenderer({
Expand All @@ -56,11 +53,7 @@ export const initCamera = () => {
camera.position.z = 800;
}

export const initCanvas = () => {
graphicCanvas = document.createElement('canvas');
graphicCanvas.width = canvasWidth;
graphicCanvas.height = canvasHeight;
}


//-----------------------------------------------------------------------

Expand Down
9 changes: 9 additions & 0 deletions src/components/three-radar-chart/animation-loop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {renderWithPostProcess} from "./post-process.ts";
import {sceneAnimation} from "./scene.ts";


export const animate = () => {
requestAnimationFrame(animate);
sceneAnimation();
renderWithPostProcess();
}
17 changes: 17 additions & 0 deletions src/components/three-radar-chart/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {initCamera, initScene, initStage, renderer} from "./scene.ts";
import {animate} from "./animation-loop.ts";
import {initRadar, TechUsage} from "./radar.ts";
import {initPostProcess} from "./post-process.ts";

export function threeDataViewer(radarValues: TechUsage[]) {
initStage();
initScene();
initCamera();
initRadar(radarValues);
initPostProcess();
animate();

return renderer.domElement;
}

//-----------------------------------------------------------------------
50 changes: 50 additions & 0 deletions src/components/three-radar-chart/label.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as THREE from "three";
import {scene} from "./scene.ts";

const offset = 1.35;
const labelMeshes: THREE.Mesh[] = [];


//-----------------------------------------------------------------------

export const label = (label: string, spawnPoint: {x: number, y: number}) => {
const texture = createLabelTexture(label);
const labelMesh = createLabelPlane(texture);

labelMesh.position.set(spawnPoint.x, spawnPoint.y * offset, 0);
scene.add(labelMesh);
labelMeshes.push(labelMesh);
}

//-----------------------------------------------------------------------

const createLabelPlane = (texture: THREE.CanvasTexture) => {
const geometry = new THREE.PlaneGeometry(2, 1);
const material = new THREE.MeshBasicMaterial({
map: texture,
side: THREE.DoubleSide,
transparent: true,
});

const plane = new THREE.Mesh(geometry, material);
return plane;
}

const createLabelTexture = (label: string) => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const width = 256;
const height = 128;
canvas.width = width;
canvas.height = height;

context!.fillStyle = 'white';
context!.font = '48px Arial';
context!.textAlign = 'center';
context!.textBaseline = 'middle';
context!.fillText(label, width / 2, height / 2);

const texture = new THREE.CanvasTexture(canvas);
return texture;
}

39 changes: 39 additions & 0 deletions src/components/three-radar-chart/post-process.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {camera, canvasHeight, canvasWidth, renderer, scene} from "./scene.ts";
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';
import {Vector2} from "three";

let composer: EffectComposer;

const postProcessConfigs = {
size: Vector2,
threshold: 0.6,
strength: 0.3,
radius: 0.5,
exposure: 0
};


export const initPostProcess = () => {
const renderScene = new RenderPass( scene, camera );

const bloomPass = new UnrealBloomPass(
new Vector2( canvasWidth, canvasHeight ), // size
postProcessConfigs.strength, // strength
postProcessConfigs.radius, // radius
postProcessConfigs.threshold // threshold
);

const outputPass = new OutputPass();

composer = new EffectComposer( renderer );
composer.addPass( renderScene );
composer.addPass( bloomPass );
composer.addPass( outputPass );
}

export const renderWithPostProcess = () => {
composer.render();
}
109 changes: 109 additions & 0 deletions src/components/three-radar-chart/radar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import * as THREE from "three";
import {scene} from "./scene.ts";
import {label} from "./label.ts";

const graphicSize = 1.5;

export type TechUsage = {
technology: string,
percentage: number
}

const triangle = [
{x: -graphicSize, y: -graphicSize},
{x: 0, y: graphicSize},
{x: graphicSize, y: -graphicSize}
]

const extrudeSettings = {
steps: 1,
depth: 0,
bevelEnabled: false,
};


//-----------------------------------------------------------------------

export const initRadar = (techs: TechUsage[]) => {
const radarSize = determineRadarSize(techs.length);
if (radarSize == undefined) { return; }

const shape = drawShape(radarSize);
const mainMesh = buildMesh(shape, 0xffffff);
scene.add(mainMesh);

for (let i = 0; i < 4; i++) {
createDepthMesh(shape, i);
}

for (let i = 0; i < techs.length; i++) {
label(techs[i].technology, radarSize[i]);
}

const valueShape = determineValueShape(techs.map(tech => tech.percentage));
const valueMesh = buildMesh(valueShape, 0x3BFFC5);
scene.add(valueMesh);
}

//-----------------------------------------------------------------------

const buildMesh = (shape: THREE.Shape, shapeColor: THREE.ColorRepresentation) => {
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
const material = new THREE.MeshBasicMaterial({
color: shapeColor,
wireframe: true
});

return new THREE.Mesh(geometry, material);
}

const createDepthMesh = (depthShape: THREE.Shape, iteration: number) => {
const mesh = buildMesh(depthShape, 0x333333);
const size = iteration * 0.25;
const offset = 2.5;

mesh.scale.set(size, size, size);
mesh.position.z = iteration * 0.6 - offset;
scene.add(mesh);
}

const drawShape = (points: {x: number, y: number}[]) => {
const shape = new THREE.Shape();

if (points.length > 0) {
shape.moveTo(points[0].x, points[0].y);
for (let i = 1; i < points.length; i++) {
shape.lineTo(points[i].x, points[i].y);
}
shape.lineTo(points[0].x, points[0].y);
}

return shape;
}

const determineValueShape = (values: number[]) => {
let valueShape: {x: number, y: number}[] = [];
const score = values.map(value => ((100 - value) / 100) * graphicSize);

valueShape = [
{x: triangle[0].x + score[0], y: triangle[0].y + score[0]},
{x: triangle[1].x, y: triangle[1].y - score[1]},
{x: triangle[2].x - score[2], y: triangle[2].y + score[2]}
];

return drawShape(valueShape);
}

const determineRadarSize = (size: number) => {
if (size == 3) {
return triangle;
}
else {
console.log("Invalid number of technology. Create a new radar size or modify the number of technologies.");
return;
}
}




Loading