migrated to sveltekit including skeleton
This commit is contained in:
		
							parent
							
								
									6b0f1726e2
								
							
						
					
					
						commit
						400e27c8f9
					
				
							
								
								
									
										13
									
								
								.eslintignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.eslintignore
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					node_modules
 | 
				
			||||||
 | 
					/build
 | 
				
			||||||
 | 
					/.svelte-kit
 | 
				
			||||||
 | 
					/package
 | 
				
			||||||
 | 
					.env
 | 
				
			||||||
 | 
					.env.*
 | 
				
			||||||
 | 
					!.env.example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Ignore files for PNPM, NPM and YARN
 | 
				
			||||||
 | 
					pnpm-lock.yaml
 | 
				
			||||||
 | 
					package-lock.json
 | 
				
			||||||
 | 
					yarn.lock
 | 
				
			||||||
							
								
								
									
										30
									
								
								.eslintrc.cjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								.eslintrc.cjs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						root: true,
 | 
				
			||||||
 | 
						extends: [
 | 
				
			||||||
 | 
							'eslint:recommended',
 | 
				
			||||||
 | 
							'plugin:@typescript-eslint/recommended',
 | 
				
			||||||
 | 
							'plugin:svelte/recommended',
 | 
				
			||||||
 | 
							'prettier'
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						parser: '@typescript-eslint/parser',
 | 
				
			||||||
 | 
						plugins: ['@typescript-eslint'],
 | 
				
			||||||
 | 
						parserOptions: {
 | 
				
			||||||
 | 
							sourceType: 'module',
 | 
				
			||||||
 | 
							ecmaVersion: 2020,
 | 
				
			||||||
 | 
							extraFileExtensions: ['.svelte']
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						env: {
 | 
				
			||||||
 | 
							browser: true,
 | 
				
			||||||
 | 
							es2017: true,
 | 
				
			||||||
 | 
							node: true
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						overrides: [
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								files: ['*.svelte'],
 | 
				
			||||||
 | 
								parser: 'svelte-eslint-parser',
 | 
				
			||||||
 | 
								parserOptions: {
 | 
				
			||||||
 | 
									parser: '@typescript-eslint/parser'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						]
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										3336
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3336
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										12
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								package.json
									
									
									
									
									
								
							@ -8,16 +8,26 @@
 | 
				
			|||||||
		"preview": "vite preview",
 | 
							"preview": "vite preview",
 | 
				
			||||||
		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
 | 
							"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
 | 
				
			||||||
		"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
 | 
							"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
 | 
				
			||||||
		"lint": "prettier --plugin-search-dir . --check .",
 | 
							"lint": "prettier --plugin-search-dir . --check . && eslint .",
 | 
				
			||||||
		"format": "prettier --plugin-search-dir . --write ."
 | 
							"format": "prettier --plugin-search-dir . --write ."
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"devDependencies": {
 | 
						"devDependencies": {
 | 
				
			||||||
 | 
							"@floating-ui/dom": "^1.2.7",
 | 
				
			||||||
 | 
							"@skeletonlabs/skeleton": "^1.5.1",
 | 
				
			||||||
		"@sveltejs/adapter-static": "^2.0.2",
 | 
							"@sveltejs/adapter-static": "^2.0.2",
 | 
				
			||||||
		"@sveltejs/kit": "^1.5.0",
 | 
							"@sveltejs/kit": "^1.5.0",
 | 
				
			||||||
 | 
							"@typescript-eslint/eslint-plugin": "^5.45.0",
 | 
				
			||||||
 | 
							"@typescript-eslint/parser": "^5.45.0",
 | 
				
			||||||
 | 
							"autoprefixer": "^10.4.14",
 | 
				
			||||||
 | 
							"eslint": "^8.28.0",
 | 
				
			||||||
 | 
							"eslint-config-prettier": "^8.5.0",
 | 
				
			||||||
 | 
							"eslint-plugin-svelte": "^2.26.0",
 | 
				
			||||||
 | 
							"postcss": "^8.4.23",
 | 
				
			||||||
		"prettier": "^2.8.0",
 | 
							"prettier": "^2.8.0",
 | 
				
			||||||
		"prettier-plugin-svelte": "^2.8.1",
 | 
							"prettier-plugin-svelte": "^2.8.1",
 | 
				
			||||||
		"svelte": "^3.54.0",
 | 
							"svelte": "^3.54.0",
 | 
				
			||||||
		"svelte-check": "^3.0.1",
 | 
							"svelte-check": "^3.0.1",
 | 
				
			||||||
 | 
							"tailwindcss": "^3.3.2",
 | 
				
			||||||
		"tslib": "^2.4.1",
 | 
							"tslib": "^2.4.1",
 | 
				
			||||||
		"typescript": "^5.0.0",
 | 
							"typescript": "^5.0.0",
 | 
				
			||||||
		"vite": "^4.2.0"
 | 
							"vite": "^4.2.0"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										6
									
								
								postcss.config.cjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								postcss.config.cjs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						plugins: {
 | 
				
			||||||
 | 
							tailwindcss: {},
 | 
				
			||||||
 | 
							autoprefixer: {},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										65
									
								
								src/app.html
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								src/app.html
									
									
									
									
									
								
							@ -1,71 +1,12 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					<!DOCTYPE html>
 | 
				
			||||||
<html lang="en">
 | 
					<html lang="en" class="light">
 | 
				
			||||||
	<head>
 | 
						<head>
 | 
				
			||||||
		<meta charset="utf-8" />
 | 
							<meta charset="utf-8" />
 | 
				
			||||||
		<link rel="icon" href="%sveltekit.assets%/favicon.png" />
 | 
							<link rel="icon" href="%sveltekit.assets%/favicon.png" />
 | 
				
			||||||
		<meta name="viewport" content="width=device-width" />
 | 
							<meta name="viewport" content="width=device-width" />
 | 
				
			||||||
		%sveltekit.head%
 | 
							%sveltekit.head%
 | 
				
			||||||
		<style>
 | 
					 | 
				
			||||||
			.myPreview {
 | 
					 | 
				
			||||||
				overflow: hidden;
 | 
					 | 
				
			||||||
				width: 300px;
 | 
					 | 
				
			||||||
				height: 300px;
 | 
					 | 
				
			||||||
				background: lightgray;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
			.myPreview__image {
 | 
					 | 
				
			||||||
				width: 300px;
 | 
					 | 
				
			||||||
				height: 300px;
 | 
					 | 
				
			||||||
				transform-origin: 0 0;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		</style>
 | 
					 | 
				
			||||||
	</head>
 | 
						</head>
 | 
				
			||||||
	<body data-sveltekit-preload-data="hover">
 | 
						<body data-sveltekit-preload-data="hover" data-theme="rocket">
 | 
				
			||||||
		<div style="display: contents">%sveltekit.body%</div>
 | 
							<div style="display: contents" class="h-full overflow-hidden">%sveltekit.body%</div>
 | 
				
			||||||
		<div style="display: flex; flex-flow: row">
 | 
					 | 
				
			||||||
			<svg width="300" height="300">
 | 
					 | 
				
			||||||
				<path d="" fill="none" stroke="red" />
 | 
					 | 
				
			||||||
				<circle cx="211" cy="41" r="5" />
 | 
					 | 
				
			||||||
				<circle cx="130" cy="50" r="5" />
 | 
					 | 
				
			||||||
				<circle cx="85" cy="247" r="5" />
 | 
					 | 
				
			||||||
				<circle cx="173" cy="261" r="5" />
 | 
					 | 
				
			||||||
			</svg>
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
			<div class="myPreview" style="display: none">
 | 
					 | 
				
			||||||
				<img class="myPreview__image" src="images/sample.jpg" alt="sample" />
 | 
					 | 
				
			||||||
			</div>
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
			<canvas width="300" height="300" class="myCanvas"></canvas>
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
			<canvas width="300" height="300" id="resultCanvas"></canvas>
 | 
					 | 
				
			||||||
		</div>
 | 
					 | 
				
			||||||
		<script src="https://unpkg.com/perspective-transform@1.1.3/dist/perspective-transform.js"></script>
 | 
					 | 
				
			||||||
		<script src="js/editor.js"></script>
 | 
					 | 
				
			||||||
		<script src="js/preview.js"></script>
 | 
					 | 
				
			||||||
		<script src="js/webgl.js"></script>
 | 
					 | 
				
			||||||
		<script>
 | 
					 | 
				
			||||||
			var download = function(){
 | 
					 | 
				
			||||||
				var link = document.createElement('a');
 | 
					 | 
				
			||||||
				link.download = 'filename.png';
 | 
					 | 
				
			||||||
				link.href = document.getElementById("resultCanvas").toDataURL();
 | 
					 | 
				
			||||||
				link.click();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
			const resultCanvas = document.getElementById("resultCanvas");
 | 
					 | 
				
			||||||
			const rctx = resultCanvas.getContext("2d");
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
			make_base();
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
			function make_base() {
 | 
					 | 
				
			||||||
				srcCtx = document.querySelector(".myCanvas");
 | 
					 | 
				
			||||||
				rctx.drawImage(srcCtx, 0, 0);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
				base_image = new Image();
 | 
					 | 
				
			||||||
				base_image.src = "images/mockup-test.png";
 | 
					 | 
				
			||||||
				base_image.onload = function() {
 | 
					 | 
				
			||||||
				rctx.drawImage(base_image, 0, 0);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		</script>
 | 
					 | 
				
			||||||
	</body>
 | 
						</body>
 | 
				
			||||||
</html>
 | 
					</html>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								src/app.postcss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								src/app.postcss
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					/*place global styles here */
 | 
				
			||||||
 | 
					html, body { @apply h-full overflow-hidden; }
 | 
				
			||||||
							
								
								
									
										46
									
								
								src/routes/+layout.svelte
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/routes/+layout.svelte
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					<script lang='ts'>
 | 
				
			||||||
 | 
						import '@skeletonlabs/skeleton/themes/theme-skeleton.css';
 | 
				
			||||||
 | 
						import '@skeletonlabs/skeleton/styles/skeleton.css';
 | 
				
			||||||
 | 
						import '../app.postcss';
 | 
				
			||||||
 | 
						import { AppShell, AppBar } from '@skeletonlabs/skeleton';
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- App Shell -->
 | 
				
			||||||
 | 
					<AppShell>
 | 
				
			||||||
 | 
						<svelte:fragment slot="header">
 | 
				
			||||||
 | 
							<!-- App Bar -->
 | 
				
			||||||
 | 
							<AppBar>
 | 
				
			||||||
 | 
								<svelte:fragment slot="lead">
 | 
				
			||||||
 | 
									<strong class="text-xl">mockup-generator.com</strong>
 | 
				
			||||||
 | 
								</svelte:fragment>
 | 
				
			||||||
 | 
								<svelte:fragment slot="trail">
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class="btn btn-sm"
 | 
				
			||||||
 | 
										href="#"
 | 
				
			||||||
 | 
										target="_blank"
 | 
				
			||||||
 | 
										rel="noreferrer"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										Devices
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class="btn btn-sm"
 | 
				
			||||||
 | 
										href="#"
 | 
				
			||||||
 | 
										target="_blank"
 | 
				
			||||||
 | 
										rel="noreferrer"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										Print
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
									<a
 | 
				
			||||||
 | 
										class="btn btn-sm"
 | 
				
			||||||
 | 
										href="#"
 | 
				
			||||||
 | 
										target="_blank"
 | 
				
			||||||
 | 
										rel="noreferrer"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										Social Media
 | 
				
			||||||
 | 
									</a>
 | 
				
			||||||
 | 
								</svelte:fragment>
 | 
				
			||||||
 | 
							</AppBar>
 | 
				
			||||||
 | 
						</svelte:fragment>
 | 
				
			||||||
 | 
						<!-- Page Route Content -->
 | 
				
			||||||
 | 
						<slot />
 | 
				
			||||||
 | 
					</AppShell>
 | 
				
			||||||
@ -0,0 +1,290 @@
 | 
				
			|||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import { onMount } from "svelte";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						onMount(async () => {
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// webgl.js
 | 
				
			||||||
 | 
							const canvas = document.querySelector(".myCanvas");
 | 
				
			||||||
 | 
							const image = document.querySelector(".myPreview__image");
 | 
				
			||||||
 | 
							const gl = canvas.getContext("webgl", {
 | 
				
			||||||
 | 
								preserveDrawingBuffer: true
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const plane = createPlane(gl);
 | 
				
			||||||
 | 
							const texture = createTexture(gl);
 | 
				
			||||||
 | 
							const shader = createImageShader(gl);
 | 
				
			||||||
 | 
							let matrix = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							function update() {
 | 
				
			||||||
 | 
								gl.clearColor(0.0, 0.0, 0.0, 0.0);
 | 
				
			||||||
 | 
								gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								shader.use().setProjection(matrix).setTexture(texture);
 | 
				
			||||||
 | 
								plane.draw(shader);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							function loadTexture() {
 | 
				
			||||||
 | 
								drawToTexure(gl, texture, image);
 | 
				
			||||||
 | 
								update();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							function toMatrix(t) {
 | 
				
			||||||
 | 
								// prettier-ignore
 | 
				
			||||||
 | 
								return [
 | 
				
			||||||
 | 
								t[0], t[1], 0, t[2],
 | 
				
			||||||
 | 
								t[3], t[4], 0, t[5],
 | 
				
			||||||
 | 
								0,    0,    1,    0,
 | 
				
			||||||
 | 
								t[6], t[7], 0, t[8]
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (image.naturalWidth && image.naturalHeight) {
 | 
				
			||||||
 | 
								loadTexture();
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								image.addEventListener("load", () => {
 | 
				
			||||||
 | 
								loadTexture();
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * Event handlers
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							document.addEventListener("myPointsChanged", (event) => {
 | 
				
			||||||
 | 
								const points = event.detail.reduce(
 | 
				
			||||||
 | 
								(result, { x, y }) => [...result, x / 150 - 1, 1 - y / 150],
 | 
				
			||||||
 | 
								[]
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const transform = new PerspT([1, -1, -1, -1, -1, 1, 1, 1], points);
 | 
				
			||||||
 | 
								matrix = toMatrix(transform.coeffs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								update();
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * Primitives
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							function createPlane(gl) {
 | 
				
			||||||
 | 
								const positionBuffer = createBuffer(
 | 
				
			||||||
 | 
								gl,
 | 
				
			||||||
 | 
								[1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0]
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
								draw(shader) {
 | 
				
			||||||
 | 
									shader.bindPositionBuffer(positionBuffer);
 | 
				
			||||||
 | 
									gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							function createImageShader(gl) {
 | 
				
			||||||
 | 
								const vertexSource = `
 | 
				
			||||||
 | 
								attribute vec4 aPosition;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								uniform mat4 uProjection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								varying highp vec2 vTextureCoord;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								void main() {
 | 
				
			||||||
 | 
									vTextureCoord = vec2((aPosition.x - 1.0) * 0.5, (aPosition.y - 1.0) * 0.5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									gl_Position = vec4(aPosition.x, aPosition.y, 0.0, 1.0) * uProjection;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const fragmentSource = `
 | 
				
			||||||
 | 
								varying highp vec2 vTextureCoord;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								uniform sampler2D uSampler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								void main() {
 | 
				
			||||||
 | 
									gl_FragColor = texture2D(uSampler, vTextureCoord);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const program = createProgram(
 | 
				
			||||||
 | 
								gl,
 | 
				
			||||||
 | 
								createShader(gl, vertexSource, gl.VERTEX_SHADER),
 | 
				
			||||||
 | 
								createShader(gl, fragmentSource, gl.FRAGMENT_SHADER)
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const positionAttribute = gl.getAttribLocation(program, "aPosition");
 | 
				
			||||||
 | 
								const projectionLocation = gl.getUniformLocation(program, "uProjection");
 | 
				
			||||||
 | 
								const samplerLocation = gl.getUniformLocation(program, "uSampler");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const instance = {
 | 
				
			||||||
 | 
								use() {
 | 
				
			||||||
 | 
									gl.useProgram(program);
 | 
				
			||||||
 | 
									gl.enableVertexAttribArray(positionAttribute);
 | 
				
			||||||
 | 
									return instance;
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								bindPositionBuffer(buffer) {
 | 
				
			||||||
 | 
									gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
 | 
				
			||||||
 | 
									gl.vertexAttribPointer(positionAttribute, 2, gl.FLOAT, false, 0, 0);
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								setProjection(value) {
 | 
				
			||||||
 | 
									gl.uniformMatrix4fv(projectionLocation, false, value);
 | 
				
			||||||
 | 
									return instance;
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								setTexture(value) {
 | 
				
			||||||
 | 
									gl.activeTexture(gl.TEXTURE0);
 | 
				
			||||||
 | 
									gl.bindTexture(gl.TEXTURE_2D, value);
 | 
				
			||||||
 | 
									gl.uniform1i(samplerLocation, 0);
 | 
				
			||||||
 | 
									return instance;
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return instance;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * WebGL helpers
 | 
				
			||||||
 | 
							 * https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							function createBuffer(gl, positions) {
 | 
				
			||||||
 | 
								const positionBuffer = gl.createBuffer();
 | 
				
			||||||
 | 
								gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
 | 
				
			||||||
 | 
								gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return positionBuffer;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							function createProgram(gl, vertexShader, fragmentShader) {
 | 
				
			||||||
 | 
								const program = gl.createProgram();
 | 
				
			||||||
 | 
								gl.attachShader(program, vertexShader);
 | 
				
			||||||
 | 
								gl.attachShader(program, fragmentShader);
 | 
				
			||||||
 | 
								gl.linkProgram(program);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
 | 
				
			||||||
 | 
								const info = gl.getProgramInfoLog(program);
 | 
				
			||||||
 | 
								throw `Could not compile WebGL program. \n\n${info}`;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return program;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							function createShader(gl, source, type) {
 | 
				
			||||||
 | 
								const shader = gl.createShader(type);
 | 
				
			||||||
 | 
								gl.shaderSource(shader, source);
 | 
				
			||||||
 | 
								gl.compileShader(shader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
 | 
				
			||||||
 | 
								const info = gl.getShaderInfoLog(shader);
 | 
				
			||||||
 | 
								throw `Could not compile WebGL program. \n\n${info}`;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return shader;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							function createTexture(gl) {
 | 
				
			||||||
 | 
								const texture = gl.createTexture();
 | 
				
			||||||
 | 
								const pixel = new Uint8Array([0, 0, 255, 255]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								gl.bindTexture(gl.TEXTURE_2D, texture);
 | 
				
			||||||
 | 
								gl.texImage2D(
 | 
				
			||||||
 | 
								gl.TEXTURE_2D,
 | 
				
			||||||
 | 
								0,
 | 
				
			||||||
 | 
								gl.RGBA,
 | 
				
			||||||
 | 
								1,
 | 
				
			||||||
 | 
								1,
 | 
				
			||||||
 | 
								0,
 | 
				
			||||||
 | 
								gl.RGBA,
 | 
				
			||||||
 | 
								gl.UNSIGNED_BYTE,
 | 
				
			||||||
 | 
								pixel
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return texture;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							function drawToTexure(gl, texture, source) {
 | 
				
			||||||
 | 
								gl.bindTexture(gl.TEXTURE_2D, texture);
 | 
				
			||||||
 | 
								gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (isPowerOf2(source.naturalWidth) && isPowerOf2(source.naturalHeight)) {
 | 
				
			||||||
 | 
								gl.generateMipmap(gl.TEXTURE_2D);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
								gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
 | 
				
			||||||
 | 
								gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
 | 
				
			||||||
 | 
								gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							function isPowerOf2(value) {
 | 
				
			||||||
 | 
								return (value & (value - 1)) === 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// var download = function(){
 | 
				
			||||||
 | 
							//   var link = document.createElement('a');
 | 
				
			||||||
 | 
							//   link.download = 'filename.png';
 | 
				
			||||||
 | 
							//   link.href = document.getElementById("resultCanvas").toDataURL();
 | 
				
			||||||
 | 
							//   link.click();
 | 
				
			||||||
 | 
							// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const points = [
 | 
				
			||||||
 | 
								{ x: 211, y: 41 },
 | 
				
			||||||
 | 
								{ x: 130, y: 50 },
 | 
				
			||||||
 | 
								{ x: 85, y: 247 },
 | 
				
			||||||
 | 
								{ x: 173, y: 261 }
 | 
				
			||||||
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const event = new CustomEvent("myPointsChanged", { detail: points });
 | 
				
			||||||
 | 
							document.dispatchEvent(event);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// draw result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const resultCanvas = document.getElementById("resultCanvas");
 | 
				
			||||||
 | 
							const rctx = resultCanvas.getContext("2d");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// draw background
 | 
				
			||||||
 | 
							let srcCtx = document.querySelector(".myCanvas");
 | 
				
			||||||
 | 
							rctx.drawImage(srcCtx, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// draw foreground
 | 
				
			||||||
 | 
							let base_image = new Image();
 | 
				
			||||||
 | 
							base_image.src = "/images/mockup-test.png";
 | 
				
			||||||
 | 
							base_image.onload = function() {
 | 
				
			||||||
 | 
								rctx.drawImage(base_image, 0, 0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<svelte:head>
 | 
				
			||||||
 | 
						<script src="https://unpkg.com/perspective-transform@1.1.3/dist/perspective-transform.js"></script>
 | 
				
			||||||
 | 
					</svelte:head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="container h-full mx-auto flex justify-center items-center">
 | 
				
			||||||
 | 
						<div style="display: flex; flex-flow: row">
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
							<div class="myPreview" style="display: none">
 | 
				
			||||||
 | 
								<img class="myPreview__image" src="/images/sample.jpg" alt="sample" />
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								<canvas width="300" height="300" class="myCanvas"></canvas>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
							<canvas width="300" height="300" id="resultCanvas"></canvas>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="postcss">
 | 
				
			||||||
 | 
						/* .myPreview {
 | 
				
			||||||
 | 
							overflow: hidden;
 | 
				
			||||||
 | 
							width: 300px;
 | 
				
			||||||
 | 
							height: 300px;
 | 
				
			||||||
 | 
							background: lightgray;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.myPreview__image {
 | 
				
			||||||
 | 
							width: 300px;
 | 
				
			||||||
 | 
							height: 300px;
 | 
				
			||||||
 | 
							transform-origin: 0 0;
 | 
				
			||||||
 | 
						} */
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -1,73 +0,0 @@
 | 
				
			|||||||
(function () {
 | 
					 | 
				
			||||||
	const svg = document.querySelector("svg");
 | 
					 | 
				
			||||||
	const path = svg.querySelector("path");
 | 
					 | 
				
			||||||
	const circles = toArray(svg.querySelectorAll("circle"));
 | 
					 | 
				
			||||||
	let draggedCircle = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function update() {
 | 
					 | 
				
			||||||
		const points = circles.map((circle) => ({
 | 
					 | 
				
			||||||
			x: parseFloat(circle.getAttribute("cx")),
 | 
					 | 
				
			||||||
			y: parseFloat(circle.getAttribute("cy")),
 | 
					 | 
				
			||||||
		}));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		path.setAttribute("d", toSvgPath(points));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		const event = new CustomEvent("myPointsChanged", { detail: points });
 | 
					 | 
				
			||||||
		document.dispatchEvent(event);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		make_base();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Event handlers
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	svg.addEventListener("mousedown", (event) => {
 | 
					 | 
				
			||||||
		if (circles.includes(event.target)) {
 | 
					 | 
				
			||||||
			draggedCircle = event.target;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	document.addEventListener("mousemove", (event) => {
 | 
					 | 
				
			||||||
		if (draggedCircle) {
 | 
					 | 
				
			||||||
			const { height, left, top, width } = svg.getBoundingClientRect();
 | 
					 | 
				
			||||||
			const x = clamp(event.clientX - left, 0, width);
 | 
					 | 
				
			||||||
			const y = clamp(event.clientY - top, 0, height);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			draggedCircle.setAttribute("cx", x);
 | 
					 | 
				
			||||||
			draggedCircle.setAttribute("cy", y);
 | 
					 | 
				
			||||||
			update();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	document.addEventListener("mouseup", () => {
 | 
					 | 
				
			||||||
		draggedCircle = null;
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	document.addEventListener("DOMContentLoaded", () => {
 | 
					 | 
				
			||||||
		update();
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Helpers
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function clamp(value, min, max) {
 | 
					 | 
				
			||||||
		return Math.max(min, Math.min(value, max));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function toArray(value) {
 | 
					 | 
				
			||||||
		return Array.prototype.slice.call(value);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function toSvgOperation(operation, { x, y }) {
 | 
					 | 
				
			||||||
		return `${operation} ${x} ${y}`;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function toSvgPath(points) {
 | 
					 | 
				
			||||||
		return [
 | 
					 | 
				
			||||||
			toSvgOperation("M", points[points.length - 1]),
 | 
					 | 
				
			||||||
			...points.map((point) => toSvgOperation("L", point)),
 | 
					 | 
				
			||||||
		].join(" ");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@ -1,31 +0,0 @@
 | 
				
			|||||||
(function () {
 | 
					 | 
				
			||||||
	const image = document.querySelector(".myPreview__image");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function toCssMatrix(transform) {
 | 
					 | 
				
			||||||
		return `matrix3d(${toMatrix(transform.coeffs).join(",")})`;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function toMatrix(t) {
 | 
					 | 
				
			||||||
	// prettier-ignore
 | 
					 | 
				
			||||||
	return [
 | 
					 | 
				
			||||||
		t[0], t[3], 0, t[6],
 | 
					 | 
				
			||||||
		t[1], t[4], 0, t[7],
 | 
					 | 
				
			||||||
		0,    0,    1,    0,
 | 
					 | 
				
			||||||
		t[2], t[5], 0, t[8]
 | 
					 | 
				
			||||||
	];
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Event handlers
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	document.addEventListener("myPointsChanged", (event) => {
 | 
					 | 
				
			||||||
	const points = event.detail.reduce(
 | 
					 | 
				
			||||||
		(result, { x, y }) => [...result, x, y],
 | 
					 | 
				
			||||||
		[]
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const transform = new PerspT([300, 0, 0, 0, 0, 300, 300, 300], points);
 | 
					 | 
				
			||||||
	image.style.transform = toCssMatrix(transform);
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
@ -1,214 +0,0 @@
 | 
				
			|||||||
(function () {
 | 
					 | 
				
			||||||
	const canvas = document.querySelector(".myCanvas");
 | 
					 | 
				
			||||||
	const image = document.querySelector(".myPreview__image");
 | 
					 | 
				
			||||||
	const gl = canvas.getContext("webgl", {
 | 
					 | 
				
			||||||
		preserveDrawingBuffer: true
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const plane = createPlane(gl);
 | 
					 | 
				
			||||||
	const texture = createTexture(gl);
 | 
					 | 
				
			||||||
	const shader = createImageShader(gl);
 | 
					 | 
				
			||||||
	let matrix = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function update() {
 | 
					 | 
				
			||||||
		gl.clearColor(255.0, 255.0, 255.0, 1.0);
 | 
					 | 
				
			||||||
		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		shader.use().setProjection(matrix).setTexture(texture);
 | 
					 | 
				
			||||||
		plane.draw(shader);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function loadTexture() {
 | 
					 | 
				
			||||||
		drawToTexure(gl, texture, image);
 | 
					 | 
				
			||||||
		update();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function toMatrix(t) {
 | 
					 | 
				
			||||||
		// prettier-ignore
 | 
					 | 
				
			||||||
		return [
 | 
					 | 
				
			||||||
			t[0], t[1], 0, t[2],
 | 
					 | 
				
			||||||
			t[3], t[4], 0, t[5],
 | 
					 | 
				
			||||||
			0,    0,    1,    0,
 | 
					 | 
				
			||||||
			t[6], t[7], 0, t[8]
 | 
					 | 
				
			||||||
		];
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (image.naturalWidth && image.naturalHeight) {
 | 
					 | 
				
			||||||
		loadTexture();
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		image.addEventListener("load", () => {
 | 
					 | 
				
			||||||
			loadTexture();
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Event handlers
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	document.addEventListener("myPointsChanged", (event) => {
 | 
					 | 
				
			||||||
		const points = event.detail.reduce(
 | 
					 | 
				
			||||||
			(result, { x, y }) => [...result, x / 150 - 1, 1 - y / 150],
 | 
					 | 
				
			||||||
			[]
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		const transform = new PerspT([1, -1, -1, -1, -1, 1, 1, 1], points);
 | 
					 | 
				
			||||||
		matrix = toMatrix(transform.coeffs);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		update();
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Primitives
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function createPlane(gl) {
 | 
					 | 
				
			||||||
		const positionBuffer = createBuffer(
 | 
					 | 
				
			||||||
			gl,
 | 
					 | 
				
			||||||
			[1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0]
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return {
 | 
					 | 
				
			||||||
			draw(shader) {
 | 
					 | 
				
			||||||
			shader.bindPositionBuffer(positionBuffer);
 | 
					 | 
				
			||||||
			gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function createImageShader(gl) {
 | 
					 | 
				
			||||||
		const vertexSource = `
 | 
					 | 
				
			||||||
			attribute vec4 aPosition;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
			uniform mat4 uProjection;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
			varying highp vec2 vTextureCoord;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
			void main() {
 | 
					 | 
				
			||||||
			vTextureCoord = vec2((aPosition.x - 1.0) * 0.5, (aPosition.y - 1.0) * 0.5);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
			gl_Position = vec4(aPosition.x, aPosition.y, 0.0, 1.0) * uProjection;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		`;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		const fragmentSource = `
 | 
					 | 
				
			||||||
			varying highp vec2 vTextureCoord;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
			uniform sampler2D uSampler;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
			void main() {
 | 
					 | 
				
			||||||
			gl_FragColor = texture2D(uSampler, vTextureCoord);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		`;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		const program = createProgram(
 | 
					 | 
				
			||||||
			gl,
 | 
					 | 
				
			||||||
			createShader(gl, vertexSource, gl.VERTEX_SHADER),
 | 
					 | 
				
			||||||
			createShader(gl, fragmentSource, gl.FRAGMENT_SHADER)
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		const positionAttribute = gl.getAttribLocation(program, "aPosition");
 | 
					 | 
				
			||||||
		const projectionLocation = gl.getUniformLocation(program, "uProjection");
 | 
					 | 
				
			||||||
		const samplerLocation = gl.getUniformLocation(program, "uSampler");
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		const instance = {
 | 
					 | 
				
			||||||
			use() {
 | 
					 | 
				
			||||||
			gl.useProgram(program);
 | 
					 | 
				
			||||||
			gl.enableVertexAttribArray(positionAttribute);
 | 
					 | 
				
			||||||
			return instance;
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			bindPositionBuffer(buffer) {
 | 
					 | 
				
			||||||
			gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
 | 
					 | 
				
			||||||
			gl.vertexAttribPointer(positionAttribute, 2, gl.FLOAT, false, 0, 0);
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			setProjection(value) {
 | 
					 | 
				
			||||||
			gl.uniformMatrix4fv(projectionLocation, false, value);
 | 
					 | 
				
			||||||
			return instance;
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			setTexture(value) {
 | 
					 | 
				
			||||||
			gl.activeTexture(gl.TEXTURE0);
 | 
					 | 
				
			||||||
			gl.bindTexture(gl.TEXTURE_2D, value);
 | 
					 | 
				
			||||||
			gl.uniform1i(samplerLocation, 0);
 | 
					 | 
				
			||||||
			return instance;
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		return instance;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * WebGL helpers
 | 
					 | 
				
			||||||
	 * https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function createBuffer(gl, positions) {
 | 
					 | 
				
			||||||
		const positionBuffer = gl.createBuffer();
 | 
					 | 
				
			||||||
		gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
 | 
					 | 
				
			||||||
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		return positionBuffer;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function createProgram(gl, vertexShader, fragmentShader) {
 | 
					 | 
				
			||||||
		const program = gl.createProgram();
 | 
					 | 
				
			||||||
		gl.attachShader(program, vertexShader);
 | 
					 | 
				
			||||||
		gl.attachShader(program, fragmentShader);
 | 
					 | 
				
			||||||
		gl.linkProgram(program);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
 | 
					 | 
				
			||||||
			const info = gl.getProgramInfoLog(program);
 | 
					 | 
				
			||||||
			throw `Could not compile WebGL program. \n\n${info}`;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		return program;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function createShader(gl, source, type) {
 | 
					 | 
				
			||||||
		const shader = gl.createShader(type);
 | 
					 | 
				
			||||||
		gl.shaderSource(shader, source);
 | 
					 | 
				
			||||||
		gl.compileShader(shader);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
 | 
					 | 
				
			||||||
			const info = gl.getShaderInfoLog(shader);
 | 
					 | 
				
			||||||
			throw `Could not compile WebGL program. \n\n${info}`;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		return shader;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function createTexture(gl) {
 | 
					 | 
				
			||||||
		const texture = gl.createTexture();
 | 
					 | 
				
			||||||
		const pixel = new Uint8Array([0, 0, 255, 255]);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		gl.bindTexture(gl.TEXTURE_2D, texture);
 | 
					 | 
				
			||||||
		gl.texImage2D(
 | 
					 | 
				
			||||||
			gl.TEXTURE_2D,
 | 
					 | 
				
			||||||
			0,
 | 
					 | 
				
			||||||
			gl.RGBA,
 | 
					 | 
				
			||||||
			1,
 | 
					 | 
				
			||||||
			1,
 | 
					 | 
				
			||||||
			0,
 | 
					 | 
				
			||||||
			gl.RGBA,
 | 
					 | 
				
			||||||
			gl.UNSIGNED_BYTE,
 | 
					 | 
				
			||||||
			pixel
 | 
					 | 
				
			||||||
		);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		return texture;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function drawToTexure(gl, texture, source) {
 | 
					 | 
				
			||||||
		gl.bindTexture(gl.TEXTURE_2D, texture);
 | 
					 | 
				
			||||||
		gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
		if (isPowerOf2(source.naturalWidth) && isPowerOf2(source.naturalHeight)) {
 | 
					 | 
				
			||||||
			gl.generateMipmap(gl.TEXTURE_2D);
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
 | 
					 | 
				
			||||||
			gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
 | 
					 | 
				
			||||||
			gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	function isPowerOf2(value) {
 | 
					 | 
				
			||||||
		return (value & (value - 1)) === 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
})();
 | 
					 | 
				
			||||||
							
								
								
									
										9
									
								
								tailwind.config.cjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								tailwind.config.cjs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					/** @type {import('tailwindcss').Config} */
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						darkMode: 'class',
 | 
				
			||||||
 | 
						content: ['./src/**/*.{html,js,svelte,ts}', require('path').join(require.resolve('@skeletonlabs/skeleton'), '../**/*.{html,js,svelte,ts}')],
 | 
				
			||||||
 | 
						theme: {
 | 
				
			||||||
 | 
							extend: {},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						plugins: [...require('@skeletonlabs/skeleton/tailwind/skeleton.cjs')()],
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user