Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React, { useEffect, useState, createRef } from 'react';
- function TagSphere() {
- const cloudSphere = createRef<any>();
- const [clicked, setClicked] = useState(false);
- const [lastX, setLastX] = useState(0);
- const [lastY, setLastY] = useState(0);
- const [looping, setLooping] = useState(false);
- const texts = [
- 'HTML5', 'Javascript', 'Scala', 'Kotlin', 'Erlang',
- 'CSS', 'Python', 'Java', 'PostgreSQL', 'MongoDB',
- 'Android', 'TensorFlow', 'Flask', 'React', 'Redis',
- 'NodeJS', 'OCaml', 'Redux', 'Rx',
- ];
- const counts = [1,2,4,5,4,2,1];
- const options:any = {
- tilt: Math.PI / 9,
- initialVelocityX: 0.09,
- initialVelocityY: 0.09,
- initialRotationX: Math.PI * 0.14,
- initialRotationZ: 0
- };
- const π = Math.PI;
- const {
- width = 500,
- height = 500,
- radius = 150,
- padding = 50,
- fontSize = 22,
- tilt = 0,
- initialVelocityX = 0,
- initialVelocityY = 0,
- initialRotationX = 0,
- initialRotationZ = 0,
- } = options;
- let vx = initialVelocityX, vy = initialVelocityY;
- let rx = initialRotationX, rz = initialRotationZ;
- function rot(x:number,y:number,t:number) {
- return [x*Math.cos(t)-y*Math.sin(t), x*Math.sin(t)+y*Math.cos(t)];
- }
- function renderSphere() {
- ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
- let ix = 0, iz = 0, i = 1;
- for (const text of texts) {
- const degZ = (π/(counts.length-1)) * iz;
- const degX = (2*π/counts[iz]) * ix;
- let x = radius * Math.sin(degZ) * Math.cos(degX);
- let y = radius * Math.sin(degZ) * Math.sin(degX);
- let z = radius * Math.cos(degZ) + 8*(ix % 2) /* randomness */;
- [y,z] = rot(y, z, tilt);
- [x,z] = rot(x, z, rz);
- [x,y] = rot(x, y, rx);
- const alpha = 0.6 + 0.4 * (x/radius);
- const size = fontSize + 2 + 5*(x/radius);
- ctx.fillStyle = `rgba(255,255,255,${alpha})`;
- ctx.font = `${size}px "Brandon Grotesque"`;
- ctx.fillText(text, y + width/2, -z + height/2);
- ix--;
- if (ix < 0) {
- iz++;
- ix = counts[iz] - 1;
- }
- i++;
- }
- }
- function rendererLoop() {
- if (looping) window.requestAnimationFrame(rendererLoop);
- renderSphere();
- if (vx > 0) vx = vx - 0.01;
- if (vy > 0) vy = vy - 0.01;
- if (vx < 0) vx = vx + 0.01;
- if (vy > 0) vy = vy + 0.01;
- if (vx === 0 && vy === 0) stopLoop();
- rz += vy * 0.01;
- rx += vx * 0.01;
- }
- function startLoop() {
- setLooping(true);
- window.requestAnimationFrame(rendererLoop);
- }
- function stopLoop() {
- setLooping(false);
- }
- function selectTarget(event:any) {
- setClicked(true);
- setLastX(event.screenX);
- setLastY(event.screenY);
- }
- function calcMouseMoveDistance(event:any) {
- console.log(clicked, looping);
- if (!clicked) return;
- setLastX(event.screenX);
- setLastY(event.screentY);
- let [dx, dy] = [event.screenX - lastX, event.screenY - lastY];
- rz += -dy * 0.01;
- rx += dx * 0.01;
- vx = dx * 0.1;
- vy = dy * 0.1;
- if (!looping) startLoop();
- }
- function resetTarget(event:any) {
- setClicked(false);
- }
- useEffect(() => {
- let ctx = cloudSphere.current.getContext('2d');
- ctx.textAlign = 'center';
- cloudSphere.current.width = width * 2;
- cloudSphere.current.height = height * 2;
- cloudSphere.current.style.width = `${width}px`;
- cloudSphere.current.style.height = `${height}px`;
- ctx.scale(2,2);
- startLoop();
- }, [])
- return (
- <div>
- <canvas onMouseDown={selectTarget} onMouseMove={calcMouseMoveDistance} onMouseLeave={resetTarget} onMouseUp={resetTarget} ref={cloudSphere} width={300} height={300}></canvas>
- </div>
- );
- }
- export default TagSphere;
Advertisement
Add Comment
Please, Sign In to add comment