add icons
improve styling improve landing bg add astro-icon dep
This commit is contained in:
@@ -1,26 +1,45 @@
|
||||
---
|
||||
import CardFeature from "@/components/Cards/CardFeature.astro";
|
||||
import Heading from "@/components/Heading.astro";
|
||||
type Feature = {
|
||||
title: string;
|
||||
iconName: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
const features: Array<Feature> = [
|
||||
{
|
||||
title: "Fast",
|
||||
iconName: "Fast",
|
||||
description:
|
||||
"Thanks to rust with multithreading and skia we're really fast!",
|
||||
},
|
||||
{
|
||||
title: "Extensible",
|
||||
iconName: "Extensible",
|
||||
description:
|
||||
"Modular structured and thanks to our dual language approach you even decide in which language you want to extend!",
|
||||
},
|
||||
{
|
||||
title: "Community driven & Free",
|
||||
iconName: "Open",
|
||||
description:
|
||||
"The project is MIT licensed and we're open to new ideas for further development. Also since this product is not profit driven we won't screw you over!",
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<div class="flex flex-row">
|
||||
{
|
||||
features.map((feature) => (
|
||||
<CardFeature
|
||||
title={feature.title}
|
||||
description={feature.description}
|
||||
/>
|
||||
))
|
||||
}
|
||||
<div>
|
||||
<Heading>Core Features & Values</Heading>
|
||||
<div class="flex flex-row gap-card">
|
||||
{
|
||||
features.map((feature) => (
|
||||
<CardFeature
|
||||
iconName={feature.iconName}
|
||||
title={feature.title}
|
||||
description={feature.description}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
---
|
||||
import Heading from "@/components/Heading.astro";
|
||||
---
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
<h2>The next generation motion design tool</h2>
|
||||
<Heading>The Next Generation Open Motion Design Tool</Heading>
|
||||
<p>
|
||||
We believe tools for expressing yourself should be accessible to
|
||||
everybody. Not constrained to proprietary operating systems or monthly
|
||||
|
||||
@@ -4,22 +4,21 @@ import Button from "@/components/Button.astro";
|
||||
|
||||
<div class="h-[80vh] relative">
|
||||
<div
|
||||
style="filter:blur(50px);"
|
||||
class="z-0 absolute top-0 flex items-center w-full h-full justify-center object-center object-contain"
|
||||
id="landing-bg-container"
|
||||
>
|
||||
<canvas
|
||||
width="1920"
|
||||
height="1080"
|
||||
style="filter:blur(100px)"
|
||||
class="w-[800px]"
|
||||
id="landing-bg"></canvas>
|
||||
<canvas width="1920" height="1080" class="w-[800px]" id="landing-bg"
|
||||
></canvas>
|
||||
</div>
|
||||
<div
|
||||
class="z-10 relative w-full h-full flex items-center flex-col justify-center"
|
||||
>
|
||||
<div class="flex flex-col justify-center items-center gap-2">
|
||||
<h1 class="text-5xl text-center font-black">tempblade Creator</h1>
|
||||
<h2 class="text-center text-xl font-normal">
|
||||
<h1 class="text-5xl dark:text-neutral text-center font-black">
|
||||
tempblade Creator
|
||||
</h1>
|
||||
<h2 class="text-center dark:text-neutral text-xl font-normal">
|
||||
Rust Based Open Source Motion Design Editor & Toolkit
|
||||
</h2>
|
||||
<Button>Explore now!</Button>
|
||||
|
||||
95
web/src/sections/bg-voronoi.ts
Normal file
95
web/src/sections/bg-voronoi.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
color: string;
|
||||
}
|
||||
|
||||
interface VoronoiCell {
|
||||
site: Point;
|
||||
vertices: Point[];
|
||||
}
|
||||
|
||||
function generateVoronoiPattern(
|
||||
canvas: HTMLCanvasElement,
|
||||
points: Array<Point>
|
||||
) {
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
if (ctx) {
|
||||
// Draw Voronoi regions
|
||||
for (let x = 0; x < canvas.width; x++) {
|
||||
for (let y = 0; y < canvas.height; y++) {
|
||||
let closestPointIndex = 0;
|
||||
let closestDistance = distance(x, y, points[0].x, points[0].y);
|
||||
|
||||
for (let i = 1; i < points.length; i++) {
|
||||
const dist = distance(x, y, points[i].x, points[i].y);
|
||||
if (dist < closestDistance) {
|
||||
closestDistance = dist;
|
||||
closestPointIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
const { x: px, y: py, color } = points[closestPointIndex];
|
||||
ctx.fillStyle = color;
|
||||
ctx.fillRect(x, y, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function distance(x1: number, y1: number, x2: number, y2: number) {
|
||||
const dx = x2 - x1;
|
||||
const dy = y2 - y1;
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
// Get canvas element and generate Voronoi pattern
|
||||
const canvas = document.getElementById("landing-bg") as HTMLCanvasElement;
|
||||
|
||||
|
||||
const initialPoints: Array<Point> = [{
|
||||
x: 200,
|
||||
y: 200,
|
||||
color: "#8AFFAD",
|
||||
},
|
||||
{
|
||||
x: 800,
|
||||
y: 500,
|
||||
color: "#326CCC",
|
||||
},
|
||||
{
|
||||
x: 1100,
|
||||
y: 300,
|
||||
color: "#95B2F5",
|
||||
},
|
||||
{
|
||||
x: 1200,
|
||||
y: 600,
|
||||
color: "#32C3E3",
|
||||
},
|
||||
{
|
||||
x: 300,
|
||||
y: 900,
|
||||
color: "purple",
|
||||
},]
|
||||
|
||||
|
||||
const draw = (time: number) => {
|
||||
const radius = 200;
|
||||
|
||||
const angle = time % 360;
|
||||
|
||||
const radian = angle * (Math.PI / 180);
|
||||
|
||||
const x = Math.cos(radian) * radius;
|
||||
const y = Math.sin(radian) * radius;
|
||||
|
||||
const points = initialPoints.map((p) => ({ ...p, x: p.x + x, y: p.y + y }));
|
||||
|
||||
generateVoronoiPattern(canvas, points);
|
||||
|
||||
//requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
requestAnimationFrame(draw);
|
||||
@@ -1,75 +1,126 @@
|
||||
interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
color: string;
|
||||
x: number;
|
||||
y: number;
|
||||
color: string;
|
||||
radius: number;
|
||||
}
|
||||
|
||||
interface VoronoiCell {
|
||||
site: Point;
|
||||
vertices: Point[];
|
||||
}
|
||||
|
||||
function generateVoronoiPattern(
|
||||
canvas: HTMLCanvasElement,
|
||||
points: Array<Point>
|
||||
) {
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
if (ctx) {
|
||||
// Draw Voronoi regions
|
||||
for (let x = 0; x < canvas.width; x++) {
|
||||
for (let y = 0; y < canvas.height; y++) {
|
||||
let closestPointIndex = 0;
|
||||
let closestDistance = distance(x, y, points[0].x, points[0].y);
|
||||
|
||||
for (let i = 1; i < points.length; i++) {
|
||||
const dist = distance(x, y, points[i].x, points[i].y);
|
||||
if (dist < closestDistance) {
|
||||
closestDistance = dist;
|
||||
closestPointIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
const { x: px, y: py, color } = points[closestPointIndex];
|
||||
ctx.fillStyle = color;
|
||||
ctx.fillRect(x, y, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function distance(x1: number, y1: number, x2: number, y2: number) {
|
||||
const dx = x2 - x1;
|
||||
const dy = y2 - y1;
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
// Get canvas element and generate Voronoi pattern
|
||||
const canvas = document.getElementById("landing-bg") as HTMLCanvasElement;
|
||||
generateVoronoiPattern(canvas, [
|
||||
{
|
||||
x: 200,
|
||||
y: 200,
|
||||
|
||||
const initialPoints: Array<Point> = [{
|
||||
x: 500,
|
||||
y: 400,
|
||||
color: "#8AFFAD",
|
||||
},
|
||||
{
|
||||
x: 800,
|
||||
radius: Math.random() * 200
|
||||
},
|
||||
{
|
||||
x: 900,
|
||||
y: 500,
|
||||
color: "#326CCC",
|
||||
},
|
||||
{
|
||||
x: 1100,
|
||||
y: 300,
|
||||
radius: Math.random() * 200
|
||||
},
|
||||
{
|
||||
x: 1600,
|
||||
y: 400,
|
||||
color: "#95B2F5",
|
||||
},
|
||||
{
|
||||
radius: Math.random() * 200
|
||||
},
|
||||
{
|
||||
x: 1200,
|
||||
y: 600,
|
||||
color: "#32C3E3",
|
||||
},
|
||||
{
|
||||
x: 300,
|
||||
y: 900,
|
||||
radius: Math.random() * 200
|
||||
|
||||
},
|
||||
{
|
||||
x: 600,
|
||||
y: 500,
|
||||
color: "#8AFFAD",
|
||||
radius: Math.random() * 200
|
||||
|
||||
},
|
||||
{
|
||||
x: 900,
|
||||
y: 300,
|
||||
color: "purple",
|
||||
},
|
||||
]);
|
||||
radius: Math.random() * 200
|
||||
|
||||
},
|
||||
]
|
||||
|
||||
export class GradientBackground {
|
||||
context: CanvasRenderingContext2D;
|
||||
|
||||
constructor(context: CanvasRenderingContext2D) {
|
||||
this.context = context;
|
||||
this.draw = this.draw.bind(this);
|
||||
|
||||
}
|
||||
|
||||
draw(time: number) {
|
||||
const { width, height } = this.context.canvas;
|
||||
|
||||
this.context.clearRect(0, 0, width, height * 2);
|
||||
|
||||
|
||||
this.context.save();
|
||||
|
||||
this.context.translate(width * 0.5, height * 0.5);
|
||||
|
||||
|
||||
const angle = (time * 0.01) % 360;
|
||||
const radian = angle * (Math.PI / 180);
|
||||
|
||||
this.context.rotate(radian);
|
||||
|
||||
this.context.translate(width * -0.5, height * -0.5);
|
||||
|
||||
|
||||
initialPoints.forEach((point, index) => {
|
||||
const { color, radius } = point;
|
||||
|
||||
|
||||
// Calculate the position/angle on a circle by the time
|
||||
const angle = time * 0.05 + index * 10 % 360;
|
||||
|
||||
// Convert the angle to radian
|
||||
const radian = angle * (Math.PI / 180);
|
||||
|
||||
// Calculate the offset based on the radius
|
||||
const offsetX = Math.cos(radian) * radius;
|
||||
const offsetY = Math.sin(radian) * radius;
|
||||
|
||||
// Calculate the position based on offset and initial position
|
||||
const x = offsetX + point.x;
|
||||
const y = offsetY + point.y;
|
||||
|
||||
// Create the gradient
|
||||
const gradient = this.context.createRadialGradient(x, y, 0, x, y, 700);
|
||||
|
||||
gradient.addColorStop(0, color);
|
||||
gradient.addColorStop(1, "rgba(0,0,0,0)");
|
||||
|
||||
this.context.fillStyle = gradient;
|
||||
this.context.globalCompositeOperation = "lighten";
|
||||
|
||||
|
||||
// Draw a rect with the gradient
|
||||
this.context.fillRect(0, 0, width, height);
|
||||
|
||||
|
||||
})
|
||||
|
||||
this.context.restore();
|
||||
|
||||
return requestAnimationFrame(this.draw);
|
||||
}
|
||||
}
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
if (ctx) {
|
||||
const bg = new GradientBackground(ctx);
|
||||
|
||||
requestAnimationFrame(bg.draw);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user