Initial commit

This commit is contained in:
apollo79 2024-07-30 14:59:22 +02:00
commit df9c300e15
No known key found for this signature in database
11 changed files with 3096 additions and 0 deletions

28
.gitignore vendored Normal file
View file

@ -0,0 +1,28 @@
dist
.solid
.output
.vercel
.netlify
.vinxi
# Environment
.env
.env*.local
# dependencies
/node_modules
# IDEs and editors
/.idea
.project
.classpath
*.launch
.settings/
# Temp
gitignore
# System Files
.DS_Store
Thumbs.db

36
README.md Normal file
View file

@ -0,0 +1,36 @@
## Usage
Those templates dependencies are maintained via [pnpm](https://pnpm.io) via `pnpm up -Lri`.
This is the reason you see a `pnpm-lock.yaml`. That being said, any package manager will work. This file can be safely be removed once you clone a template.
```bash
$ npm install # or pnpm install or yarn install
```
### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs)
## Available Scripts
In the project directory, you can run:
### `npm run dev` or `npm start`
Runs the app in the development mode.<br>
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
The page will reload if you make edits.<br>
### `npm run build`
Builds the app for production to the `dist` folder.<br>
It correctly bundles Solid in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.<br>
Your app is ready to be deployed!
## Deployment
You can deploy the `dist` folder to any static host provider (netlify, surge, now, etc.)
## This project was created with the [Solid CLI](https://solid-cli.netlify.app)

16
index.html Normal file
View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.ico" />
<title>Solid App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="/src/index.tsx" type="module"></script>
</body>
</html>

24
package.json Normal file
View file

@ -0,0 +1,24 @@
{
"name": "vite-template-solid",
"version": "0.0.0",
"description": "",
"scripts": {
"start": "vite",
"dev": "vite",
"build": "vite build",
"serve": "vite preview"
},
"type": "module",
"license": "MIT",
"devDependencies": {
"solid-devtools": "^0.29.2",
"typescript": "^5.3.3",
"unocss": "^0.59.0",
"vite": "^5.0.11",
"vite-plugin-solid": "^2.8.2"
},
"dependencies": {
"@solid-primitives/scheduled": "^1.4.3",
"solid-js": "^1.8.11"
}
}

2754
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load diff

175
src/App.tsx Normal file
View file

@ -0,0 +1,175 @@
import { debounce } from "@solid-primitives/scheduled";
import { Component, createEffect, createMemo, createSignal } from "solid-js";
export const App: Component = () => {
const [pixelSize, setPixelSize] = createSignal(8);
const [canvasRef, setCanvasRef] = createSignal<HTMLCanvasElement>();
const dataCanvas = document.createElement("canvas");
const dataCanvasContext = dataCanvas.getContext("2d");
const [data, setData] = createSignal<string>();
const imageElement = new Image();
createEffect(() => {
const src = data();
if (src) {
imageElement.src = src;
}
});
const [imageData, setImageData] = createSignal<ImageData>();
imageElement.addEventListener("load", () => {
const { naturalWidth: width, naturalHeight: height } = imageElement;
[dataCanvas.width, dataCanvas.height] = [width, height];
dataCanvasContext?.drawImage(imageElement, 0, 0);
setImageData(dataCanvasContext?.getImageData(0, 0, width - 1, height - 1));
});
const context = () => canvasRef()?.getContext("2d");
const mosaicPixels = createMemo(() => {
const pixels = imageData();
const ctx = context();
const currentPixelSize = pixelSize();
if (currentPixelSize === 1) {
return pixels;
}
if (pixels && ctx) {
const mosaicPixelsImageData = ctx.createImageData(
pixels.width,
pixels.height
);
const lastRowHeight = pixels.height % currentPixelSize;
const rows = (pixels.height - lastRowHeight) / currentPixelSize + 1;
const lastColWidth = pixels.width % currentPixelSize;
const cols = (pixels.width - lastColWidth) / currentPixelSize + 1;
// advance the new rows
for (let row = 0; row < rows; row++) {
// advance the new cols
for (let col = 0; col < cols; col++) {
const affectedPixelStartPositions: number[] = [];
let redSum = 0,
greenSum = 0,
blueSum = 0,
alphaSum = 0;
let pixelWidth = currentPixelSize;
if (col === cols - 1) {
pixelWidth = lastColWidth;
}
let pixelHeight = currentPixelSize;
if (row === rows - 1) {
pixelHeight = lastRowHeight;
}
let divider = pixelWidth * pixelHeight;
// loop though the vertical pixels
for (let k = 0; k < pixelWidth * 4; k += 4) {
// for each vertical pixels we also get all the pixels we need below it
// each pixel consists of 4 values (r, g, b, a)
for (let l = 0; l < pixelHeight; l++) {
const pixelStartPosition =
row * currentPixelSize * (pixels.width * 4) +
col * currentPixelSize * 4 +
k +
l * (pixels.width * 4);
affectedPixelStartPositions.push(pixelStartPosition);
redSum += pixels.data[pixelStartPosition];
greenSum += pixels.data[pixelStartPosition + 1];
blueSum += pixels.data[pixelStartPosition + 2];
alphaSum += pixels.data[pixelStartPosition + 3];
}
}
const red = redSum / divider;
const green = greenSum / divider;
const blue = blueSum / divider;
const alpha = alphaSum / divider;
for (const startPosition of affectedPixelStartPositions) {
mosaicPixelsImageData.data[startPosition] = red;
mosaicPixelsImageData.data[startPosition + 1] = green;
mosaicPixelsImageData.data[startPosition + 2] = blue;
mosaicPixelsImageData.data[startPosition + 3] = alpha;
}
}
}
return mosaicPixelsImageData;
}
});
createEffect(() => {
const pixels = mosaicPixels();
const ctx = context();
if (pixels && ctx) {
canvasRef()!.width = pixels.width;
canvasRef()!.height = pixels.height;
ctx.putImageData(pixels, 0, 0);
}
});
const triggerPixelSizeChange = debounce(
(pixelSize: number) => setPixelSize(pixelSize),
250
);
return (
<>
<div class="w-screen h-screen flex flex-col">
<form class="m2">
<input
required
type="file"
accept="image/*"
onChange={(event) => {
const file = event.currentTarget.files?.[0];
if (file) {
const reader = new FileReader();
reader.addEventListener("load", (event) => {
const data = event.target!.result;
setData(data as string);
});
reader.readAsDataURL(file);
}
}}
/>
<input
type="range"
min="1"
max="20"
value={pixelSize()}
onChange={(event) => {
triggerPixelSizeChange(event.currentTarget.valueAsNumber);
}}
/>
</form>
<canvas ref={setCanvasRef} class="grow" />
</div>
</>
);
};
export default App;

4
src/index.css Normal file
View file

@ -0,0 +1,4 @@
* {
padding: 0;
margin: 0;
}

17
src/index.tsx Normal file
View file

@ -0,0 +1,17 @@
/* @refresh reload */
import { render } from "solid-js/web";
import App from "./App";
import "./index.css";
import "virtual:uno.css";
const root = document.getElementById("root");
if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
throw new Error(
"Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got misspelled?"
);
}
render(() => <App />, root!);

15
tsconfig.json Normal file
View file

@ -0,0 +1,15 @@
{
"compilerOptions": {
"strict": true,
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"jsx": "preserve",
"jsxImportSource": "solid-js",
"types": ["vite/client"],
"noEmit": true,
"isolatedModules": true,
},
}

5
uno.config.ts Normal file
View file

@ -0,0 +1,5 @@
import { defineConfig, presetUno } from "unocss";
defineConfig({
presets: [presetUno],
});

22
vite.config.ts Normal file
View file

@ -0,0 +1,22 @@
import { defineConfig } from "vite";
import solidPlugin from "vite-plugin-solid";
// import devtools from 'solid-devtools/vite';
import UnoCSS from "unocss/vite";
export default defineConfig({
plugins: [
/*
Uncomment the following line to enable solid-devtools.
For more info see https://github.com/thetarnav/solid-devtools/tree/main/packages/extension#readme
*/
// devtools(),
solidPlugin(),
UnoCSS(),
],
server: {
port: 3000,
},
build: {
target: "esnext",
},
});