mirror of
https://github.com/DavidHDev/vue-bits.git
synced 2026-03-07 14:39:30 -07:00
Merge pull request #138 from Utkarsh-Singhal-26/feat/grainient
[ FEAT ] : 🎉 New <Grainient /> Background
This commit is contained in:
BIN
public/assets/videos/grainient.mp4
Normal file
BIN
public/assets/videos/grainient.mp4
Normal file
Binary file not shown.
BIN
public/assets/videos/grainient.webm
Normal file
BIN
public/assets/videos/grainient.webm
Normal file
Binary file not shown.
1
public/r/Grainient.json
Normal file
1
public/r/Grainient.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -19,10 +19,10 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="hero-main-content">
|
<div class="hero-main-content">
|
||||||
<router-link to="/backgrounds/pixel-snow" class="hero-new-badge-container">
|
<router-link to="/backgrounds/grainient" class="hero-new-badge-container">
|
||||||
<span class="hero-new-badge">Christmas Special 🎁</span>
|
<span class="hero-new-badge">New 🎉</span>
|
||||||
<div class="hero-new-badge-text">
|
<div class="hero-new-badge-text">
|
||||||
<span>Pixel Snow</span>
|
<span>Grainient</span>
|
||||||
<i class="pi-arrow-right pi" style="font-size: 0.8rem"></i>
|
<i class="pi-arrow-right pi" style="font-size: 0.8rem"></i>
|
||||||
</div>
|
</div>
|
||||||
</router-link>
|
</router-link>
|
||||||
@@ -83,7 +83,7 @@ const ResponsiveSplitText = defineComponent({
|
|||||||
isMobile: { type: Boolean, required: true },
|
isMobile: { type: Boolean, required: true },
|
||||||
text: { type: String, required: true },
|
text: { type: String, required: true },
|
||||||
className: { type: String, default: '' },
|
className: { type: String, default: '' },
|
||||||
splitType: { type: String as () => 'chars' | 'words' | 'lines' | 'words, chars', default: 'chars' },
|
splitType: { type: String as () => 'chars' | 'words' | 'lines', default: 'chars' },
|
||||||
delay: { type: Number, default: 100 },
|
delay: { type: Number, default: 100 },
|
||||||
duration: { type: Number, default: 0.6 },
|
duration: { type: Number, default: 0.6 },
|
||||||
ease: { type: String, default: 'power3.out' },
|
ease: { type: String, default: 'power3.out' },
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
// Highlighted sidebar items
|
// Highlighted sidebar items
|
||||||
export const NEW = [
|
export const NEW = [
|
||||||
'Antigravity',
|
|
||||||
'Color Bends',
|
'Color Bends',
|
||||||
'Floating Lines',
|
'Floating Lines',
|
||||||
'Ghost Cursor',
|
|
||||||
'Grid Scan',
|
|
||||||
'Laser Flow',
|
|
||||||
'Light Pillar',
|
'Light Pillar',
|
||||||
'Liquid Ether',
|
'Antigravity',
|
||||||
'Pixel Blast',
|
'Reflective Card',
|
||||||
'Pixel Snow',
|
'Pixel Snow',
|
||||||
|
'Grainient',
|
||||||
];
|
];
|
||||||
export const UPDATED = ['Metallic Paint'];
|
export const UPDATED = ['Metallic Paint'];
|
||||||
|
|
||||||
@@ -133,6 +130,7 @@ export const CATEGORIES = [
|
|||||||
'Floating Lines',
|
'Floating Lines',
|
||||||
'Galaxy',
|
'Galaxy',
|
||||||
'Gradient Blinds',
|
'Gradient Blinds',
|
||||||
|
'Grainient',
|
||||||
'Grid Distortion',
|
'Grid Distortion',
|
||||||
'Grid Motion',
|
'Grid Motion',
|
||||||
'Grid Scan',
|
'Grid Scan',
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ const backgrounds = {
|
|||||||
'light-pillar': () => import('../demo/Backgrounds/LightPillarDemo.vue'),
|
'light-pillar': () => import('../demo/Backgrounds/LightPillarDemo.vue'),
|
||||||
'pixel-snow': () => import('../demo/Backgrounds/PixelSnowDemo.vue'),
|
'pixel-snow': () => import('../demo/Backgrounds/PixelSnowDemo.vue'),
|
||||||
'grid-scan': () => import('../demo/Backgrounds/GridScanDemo.vue'),
|
'grid-scan': () => import('../demo/Backgrounds/GridScanDemo.vue'),
|
||||||
|
'grainient': () => import('../demo/Backgrounds/GrainientDemo.vue'),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const componentMap = {
|
export const componentMap = {
|
||||||
|
|||||||
@@ -765,6 +765,14 @@ export const componentMetadata: ComponentMetadata = {
|
|||||||
docsUrl: 'https://vue-bits.dev/backgrounds/gradient-blinds',
|
docsUrl: 'https://vue-bits.dev/backgrounds/gradient-blinds',
|
||||||
tags: []
|
tags: []
|
||||||
},
|
},
|
||||||
|
'Backgrounds/Grainient': {
|
||||||
|
videoUrl: '/assets/videos/grainient.webm',
|
||||||
|
description: 'Grainy gradient swirls with soft wave distortion.',
|
||||||
|
category: 'Backgrounds',
|
||||||
|
name: 'Grainient',
|
||||||
|
docsUrl: 'https://vue-bits.dev/backgrounds/grainient',
|
||||||
|
tags: []
|
||||||
|
},
|
||||||
'Backgrounds/GridDistortion': {
|
'Backgrounds/GridDistortion': {
|
||||||
videoUrl: '/assets/videos/griddistortion.webm',
|
videoUrl: '/assets/videos/griddistortion.webm',
|
||||||
description: 'Warped grid mesh distorts smoothly reacting to cursor.',
|
description: 'Warped grid mesh distorts smoothly reacting to cursor.',
|
||||||
|
|||||||
38
src/constants/code/Backgrounds/grainientCode.ts
Normal file
38
src/constants/code/Backgrounds/grainientCode.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import code from '@content/Backgrounds/Grainient/Grainient.vue?raw';
|
||||||
|
import { createCodeObject } from '../../../types/code';
|
||||||
|
|
||||||
|
export const grainient = createCodeObject(code, 'Backgrounds/Grainient', {
|
||||||
|
installation: `npm install ogl`,
|
||||||
|
usage: `<template>
|
||||||
|
<div style="width: 100%; height: 600px; position: relative;">
|
||||||
|
<Grainient
|
||||||
|
color1="#5227FF"
|
||||||
|
color2="#FF9FFC"
|
||||||
|
color3="#B19EEF"
|
||||||
|
:time-speed="0.25"
|
||||||
|
:color-balance="0.0"
|
||||||
|
:warp-strength="1.0"
|
||||||
|
:warp-frequency="5.0"
|
||||||
|
:warp-speed="2.0"
|
||||||
|
:warp-amplitude="50.0"
|
||||||
|
:blend-angle="0.0"
|
||||||
|
:blend-softness="0.05"
|
||||||
|
:rotation-amount="500.0"
|
||||||
|
:noise-scale="2.0"
|
||||||
|
:grain-amount="0.1"
|
||||||
|
:grain-scale="2.0"
|
||||||
|
:grain-animated="false"
|
||||||
|
:contrast="1.5"
|
||||||
|
:gamma="1.0"
|
||||||
|
:saturation="1.0"
|
||||||
|
:center-x="0.0"
|
||||||
|
:center-y="0.0"
|
||||||
|
:zoom="0.9"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import Grainient from "./Grainient.vue";
|
||||||
|
</script>`
|
||||||
|
});
|
||||||
285
src/content/Backgrounds/Grainient/Grainient.vue
Normal file
285
src/content/Backgrounds/Grainient/Grainient.vue
Normal file
@@ -0,0 +1,285 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { Mesh, Program, Renderer, Triangle } from 'ogl';
|
||||||
|
import { onBeforeUnmount, onMounted, useTemplateRef, watch } from 'vue';
|
||||||
|
|
||||||
|
interface GrainientProps {
|
||||||
|
timeSpeed?: number;
|
||||||
|
colorBalance?: number;
|
||||||
|
warpStrength?: number;
|
||||||
|
warpFrequency?: number;
|
||||||
|
warpSpeed?: number;
|
||||||
|
warpAmplitude?: number;
|
||||||
|
blendAngle?: number;
|
||||||
|
blendSoftness?: number;
|
||||||
|
rotationAmount?: number;
|
||||||
|
noiseScale?: number;
|
||||||
|
grainAmount?: number;
|
||||||
|
grainScale?: number;
|
||||||
|
grainAnimated?: boolean;
|
||||||
|
contrast?: number;
|
||||||
|
gamma?: number;
|
||||||
|
saturation?: number;
|
||||||
|
centerX?: number;
|
||||||
|
centerY?: number;
|
||||||
|
zoom?: number;
|
||||||
|
color1?: string;
|
||||||
|
color2?: string;
|
||||||
|
color3?: string;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hexToRgb = (hex: string): [number, number, number] => {
|
||||||
|
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||||
|
if (!result) return [1, 1, 1];
|
||||||
|
return [parseInt(result[1], 16) / 255, parseInt(result[2], 16) / 255, parseInt(result[3], 16) / 255];
|
||||||
|
};
|
||||||
|
|
||||||
|
const vertex = `#version 300 es
|
||||||
|
in vec2 position;
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(position, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const fragment = `#version 300 es
|
||||||
|
precision highp float;
|
||||||
|
uniform vec2 iResolution;
|
||||||
|
uniform float iTime;
|
||||||
|
uniform float uTimeSpeed;
|
||||||
|
uniform float uColorBalance;
|
||||||
|
uniform float uWarpStrength;
|
||||||
|
uniform float uWarpFrequency;
|
||||||
|
uniform float uWarpSpeed;
|
||||||
|
uniform float uWarpAmplitude;
|
||||||
|
uniform float uBlendAngle;
|
||||||
|
uniform float uBlendSoftness;
|
||||||
|
uniform float uRotationAmount;
|
||||||
|
uniform float uNoiseScale;
|
||||||
|
uniform float uGrainAmount;
|
||||||
|
uniform float uGrainScale;
|
||||||
|
uniform float uGrainAnimated;
|
||||||
|
uniform float uContrast;
|
||||||
|
uniform float uGamma;
|
||||||
|
uniform float uSaturation;
|
||||||
|
uniform vec2 uCenterOffset;
|
||||||
|
uniform float uZoom;
|
||||||
|
uniform vec3 uColor1;
|
||||||
|
uniform vec3 uColor2;
|
||||||
|
uniform vec3 uColor3;
|
||||||
|
out vec4 fragColor;
|
||||||
|
#define S(a,b,t) smoothstep(a,b,t)
|
||||||
|
mat2 Rot(float a){float s=sin(a),c=cos(a);return mat2(c,-s,s,c);}
|
||||||
|
vec2 hash(vec2 p){p=vec2(dot(p,vec2(2127.1,81.17)),dot(p,vec2(1269.5,283.37)));return fract(sin(p)*43758.5453);}
|
||||||
|
float noise(vec2 p){vec2 i=floor(p),f=fract(p),u=f*f*(3.0-2.0*f);float n=mix(mix(dot(-1.0+2.0*hash(i+vec2(0.0,0.0)),f-vec2(0.0,0.0)),dot(-1.0+2.0*hash(i+vec2(1.0,0.0)),f-vec2(1.0,0.0)),u.x),mix(dot(-1.0+2.0*hash(i+vec2(0.0,1.0)),f-vec2(0.0,1.0)),dot(-1.0+2.0*hash(i+vec2(1.0,1.0)),f-vec2(1.0,1.0)),u.x),u.y);return 0.5+0.5*n;}
|
||||||
|
void mainImage(out vec4 o, vec2 C){
|
||||||
|
float t=iTime*uTimeSpeed;
|
||||||
|
vec2 uv=C/iResolution.xy;
|
||||||
|
float ratio=iResolution.x/iResolution.y;
|
||||||
|
vec2 tuv=uv-0.5+uCenterOffset;
|
||||||
|
tuv/=max(uZoom,0.001);
|
||||||
|
|
||||||
|
float degree=noise(vec2(t*0.1,tuv.x*tuv.y)*uNoiseScale);
|
||||||
|
tuv.y*=1.0/ratio;
|
||||||
|
tuv*=Rot(radians((degree-0.5)*uRotationAmount+180.0));
|
||||||
|
tuv.y*=ratio;
|
||||||
|
|
||||||
|
float frequency=uWarpFrequency;
|
||||||
|
float ws=max(uWarpStrength,0.001);
|
||||||
|
float amplitude=uWarpAmplitude/ws;
|
||||||
|
float warpTime=t*uWarpSpeed;
|
||||||
|
tuv.x+=sin(tuv.y*frequency+warpTime)/amplitude;
|
||||||
|
tuv.y+=sin(tuv.x*(frequency*1.5)+warpTime)/(amplitude*0.5);
|
||||||
|
|
||||||
|
vec3 colLav=uColor1;
|
||||||
|
vec3 colOrg=uColor2;
|
||||||
|
vec3 colDark=uColor3;
|
||||||
|
float b=uColorBalance;
|
||||||
|
float s=max(uBlendSoftness,0.0);
|
||||||
|
mat2 blendRot=Rot(radians(uBlendAngle));
|
||||||
|
float blendX=(tuv*blendRot).x;
|
||||||
|
float edge0=-0.3-b-s;
|
||||||
|
float edge1=0.2-b+s;
|
||||||
|
float v0=0.5-b+s;
|
||||||
|
float v1=-0.3-b-s;
|
||||||
|
vec3 layer1=mix(colDark,colOrg,S(edge0,edge1,blendX));
|
||||||
|
vec3 layer2=mix(colOrg,colLav,S(edge0,edge1,blendX));
|
||||||
|
vec3 col=mix(layer1,layer2,S(v0,v1,tuv.y));
|
||||||
|
|
||||||
|
vec2 grainUv=uv*max(uGrainScale,0.001);
|
||||||
|
if(uGrainAnimated>0.5){grainUv+=vec2(iTime*0.05);}
|
||||||
|
float grain=fract(sin(dot(grainUv,vec2(12.9898,78.233)))*43758.5453);
|
||||||
|
col+=(grain-0.5)*uGrainAmount;
|
||||||
|
|
||||||
|
col=(col-0.5)*uContrast+0.5;
|
||||||
|
float luma=dot(col,vec3(0.2126,0.7152,0.0722));
|
||||||
|
col=mix(vec3(luma),col,uSaturation);
|
||||||
|
col=pow(max(col,0.0),vec3(1.0/max(uGamma,0.001)));
|
||||||
|
col=clamp(col,0.0,1.0);
|
||||||
|
|
||||||
|
o=vec4(col,1.0);
|
||||||
|
}
|
||||||
|
void main(){
|
||||||
|
vec4 o=vec4(0.0);
|
||||||
|
mainImage(o,gl_FragCoord.xy);
|
||||||
|
fragColor=o;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<GrainientProps>(), {
|
||||||
|
timeSpeed: 0.25,
|
||||||
|
colorBalance: 0.0,
|
||||||
|
warpStrength: 1.0,
|
||||||
|
warpFrequency: 5.0,
|
||||||
|
warpSpeed: 2.0,
|
||||||
|
warpAmplitude: 50.0,
|
||||||
|
blendAngle: 0.0,
|
||||||
|
blendSoftness: 0.05,
|
||||||
|
rotationAmount: 500.0,
|
||||||
|
noiseScale: 2.0,
|
||||||
|
grainAmount: 0.1,
|
||||||
|
grainScale: 2.0,
|
||||||
|
grainAnimated: false,
|
||||||
|
contrast: 1.5,
|
||||||
|
gamma: 1.0,
|
||||||
|
saturation: 1.0,
|
||||||
|
centerX: 0.0,
|
||||||
|
centerY: 0.0,
|
||||||
|
zoom: 0.9,
|
||||||
|
color1: '#FF9FFC',
|
||||||
|
color2: '#5227FF',
|
||||||
|
color3: '#B19EEF',
|
||||||
|
className: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const containerRef = useTemplateRef<HTMLDivElement>('containerRef');
|
||||||
|
|
||||||
|
let cleanup: (() => void) | null = null;
|
||||||
|
const setup = () => {
|
||||||
|
if (!containerRef.value) return;
|
||||||
|
|
||||||
|
const renderer = new Renderer({
|
||||||
|
webgl: 2,
|
||||||
|
alpha: true,
|
||||||
|
antialias: false,
|
||||||
|
dpr: Math.min(window.devicePixelRatio || 1, 2)
|
||||||
|
});
|
||||||
|
|
||||||
|
const gl = renderer.gl;
|
||||||
|
const canvas = gl.canvas as HTMLCanvasElement;
|
||||||
|
canvas.style.width = '100%';
|
||||||
|
canvas.style.height = '100%';
|
||||||
|
canvas.style.display = 'block';
|
||||||
|
|
||||||
|
const container = containerRef.value;
|
||||||
|
container.appendChild(canvas);
|
||||||
|
|
||||||
|
const geometry = new Triangle(gl);
|
||||||
|
const program = new Program(gl, {
|
||||||
|
vertex,
|
||||||
|
fragment,
|
||||||
|
uniforms: {
|
||||||
|
iTime: { value: 0 },
|
||||||
|
iResolution: { value: new Float32Array([1, 1]) },
|
||||||
|
uTimeSpeed: { value: props.timeSpeed },
|
||||||
|
uColorBalance: { value: props.colorBalance },
|
||||||
|
uWarpStrength: { value: props.warpStrength },
|
||||||
|
uWarpFrequency: { value: props.warpFrequency },
|
||||||
|
uWarpSpeed: { value: props.warpSpeed },
|
||||||
|
uWarpAmplitude: { value: props.warpAmplitude },
|
||||||
|
uBlendAngle: { value: props.blendAngle },
|
||||||
|
uBlendSoftness: { value: props.blendSoftness },
|
||||||
|
uRotationAmount: { value: props.rotationAmount },
|
||||||
|
uNoiseScale: { value: props.noiseScale },
|
||||||
|
uGrainAmount: { value: props.grainAmount },
|
||||||
|
uGrainScale: { value: props.grainScale },
|
||||||
|
uGrainAnimated: { value: props.grainAnimated ? 1.0 : 0.0 },
|
||||||
|
uContrast: { value: props.contrast },
|
||||||
|
uGamma: { value: props.gamma },
|
||||||
|
uSaturation: { value: props.saturation },
|
||||||
|
uCenterOffset: { value: new Float32Array([props.centerX, props.centerY]) },
|
||||||
|
uZoom: { value: props.zoom },
|
||||||
|
uColor1: { value: new Float32Array(hexToRgb(props.color1)) },
|
||||||
|
uColor2: { value: new Float32Array(hexToRgb(props.color2)) },
|
||||||
|
uColor3: { value: new Float32Array(hexToRgb(props.color3)) }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const mesh = new Mesh(gl, { geometry, program });
|
||||||
|
|
||||||
|
const setSize = () => {
|
||||||
|
const rect = container.getBoundingClientRect();
|
||||||
|
const width = Math.max(1, Math.floor(rect.width));
|
||||||
|
const height = Math.max(1, Math.floor(rect.height));
|
||||||
|
renderer.setSize(width, height);
|
||||||
|
const res = (program.uniforms.iResolution as { value: Float32Array }).value;
|
||||||
|
res[0] = gl.drawingBufferWidth;
|
||||||
|
res[1] = gl.drawingBufferHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ro = new ResizeObserver(setSize);
|
||||||
|
ro.observe(container);
|
||||||
|
setSize();
|
||||||
|
|
||||||
|
let raf = 0;
|
||||||
|
const t0 = performance.now();
|
||||||
|
const loop = (t: number) => {
|
||||||
|
(program.uniforms.iTime as { value: number }).value = (t - t0) * 0.001;
|
||||||
|
renderer.render({ scene: mesh });
|
||||||
|
raf = requestAnimationFrame(loop);
|
||||||
|
};
|
||||||
|
raf = requestAnimationFrame(loop);
|
||||||
|
|
||||||
|
cleanup = () => {
|
||||||
|
cancelAnimationFrame(raf);
|
||||||
|
ro.disconnect();
|
||||||
|
try {
|
||||||
|
container.removeChild(canvas);
|
||||||
|
} catch {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(setup);
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
cleanup?.();
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [
|
||||||
|
props.timeSpeed,
|
||||||
|
props.colorBalance,
|
||||||
|
props.warpStrength,
|
||||||
|
props.warpFrequency,
|
||||||
|
props.warpSpeed,
|
||||||
|
props.warpAmplitude,
|
||||||
|
props.blendAngle,
|
||||||
|
props.blendSoftness,
|
||||||
|
props.rotationAmount,
|
||||||
|
props.noiseScale,
|
||||||
|
props.grainAmount,
|
||||||
|
props.grainScale,
|
||||||
|
props.grainAnimated,
|
||||||
|
props.contrast,
|
||||||
|
props.gamma,
|
||||||
|
props.saturation,
|
||||||
|
props.centerX,
|
||||||
|
props.centerY,
|
||||||
|
props.zoom,
|
||||||
|
props.color1,
|
||||||
|
props.color2,
|
||||||
|
props.color3
|
||||||
|
],
|
||||||
|
() => {
|
||||||
|
cleanup?.();
|
||||||
|
setup();
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div ref="containerRef" :class="['relative h-full w-full overflow-hidden', className]" />
|
||||||
|
</template>
|
||||||
259
src/demo/Backgrounds/GrainientDemo.vue
Normal file
259
src/demo/Backgrounds/GrainientDemo.vue
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
<template>
|
||||||
|
<TabbedLayout>
|
||||||
|
<template #preview>
|
||||||
|
<div class="relative p-0 h-[600px] overflow-hidden demo-container">
|
||||||
|
<Grainient
|
||||||
|
:key="rerenderKey"
|
||||||
|
:color1="color1"
|
||||||
|
:color2="color2"
|
||||||
|
:color3="color3"
|
||||||
|
:time-speed="timeSpeed"
|
||||||
|
:color-balance="colorBalance"
|
||||||
|
:warp-strength="warpStrength"
|
||||||
|
:warp-frequency="warpFrequency"
|
||||||
|
:warp-speed="warpSpeed"
|
||||||
|
:warp-amplitude="warpAmplitude"
|
||||||
|
:blend-angle="blendAngle"
|
||||||
|
:blend-softness="blendSoftness"
|
||||||
|
:rotation-amount="rotationAmount"
|
||||||
|
:noise-scale="noiseScale"
|
||||||
|
:grain-amount="grainAmount"
|
||||||
|
:grain-scale="grainScale"
|
||||||
|
:grain-animated="grainAnimated"
|
||||||
|
:contrast="contrast"
|
||||||
|
:gamma="gamma"
|
||||||
|
:saturation="saturation"
|
||||||
|
:centerX="centerX"
|
||||||
|
:centerY="centerY"
|
||||||
|
:zoom="zoom"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<BackgroundContent pill-text="New Background" headline="Grainy gradient colors with soft motion." />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Customize>
|
||||||
|
<div class="gap-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 mb-4">
|
||||||
|
<PreviewColor title="Color 1" v-model="color1" />
|
||||||
|
<PreviewColor title="Color 2" v-model="color2" />
|
||||||
|
<PreviewColor title="Color 3" v-model="color3" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gap-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
|
||||||
|
<PreviewSlider title="Time Speed" :min="0" :max="5" :step="0.05" v-model="timeSpeed" />
|
||||||
|
<PreviewSlider title="Color Balance" :min="-1" :max="1" :step="0.01" v-model="colorBalance" />
|
||||||
|
<PreviewSlider title="Warp Strength" :min="0" :max="4" :step="0.05" v-model="warpStrength" />
|
||||||
|
<PreviewSlider title="Warp Frequency" :min="0" :max="12" :step="0.1" v-model="warpFrequency" />
|
||||||
|
<PreviewSlider title="Warp Speed" :min="0" :max="6" :step="0.1" v-model="warpSpeed" />
|
||||||
|
<PreviewSlider title="Warp Amplitude" :min="5" :max="80" :step="1" v-model="warpAmplitude" />
|
||||||
|
<PreviewSlider title="Blend Angle" :min="-180" :max="180" :step="1" v-model="blendAngle" />
|
||||||
|
<PreviewSlider title="Blend Softness" :min="0" :max="1" :step="0.01" v-model="blendSoftness" />
|
||||||
|
<PreviewSlider title="Rotation Amount" :min="0" :max="1440" :step="10" v-model="rotationAmount" />
|
||||||
|
<PreviewSlider title="Noise Scale" :min="0" :max="4" :step="0.05" v-model="noiseScale" />
|
||||||
|
<PreviewSlider title="Grain Amount" :min="0" :max="0.4" :step="0.01" v-model="grainAmount" />
|
||||||
|
<PreviewSlider title="Grain Scale" :min="0.2" :max="8" :step="0.1" v-model="grainScale" />
|
||||||
|
<PreviewSwitch title="Grain Animated" v-model="grainAnimated" />
|
||||||
|
<PreviewSlider title="Contrast" :min="0" :max="2.5" :step="0.05" v-model="contrast" />
|
||||||
|
<PreviewSlider title="Gamma" :min="0.4" :max="2.5" :step="0.05" v-model="gamma" />
|
||||||
|
<PreviewSlider title="Saturation" :min="0" :max="2.5" :step="0.05" v-model="saturation" />
|
||||||
|
<PreviewSlider title="Center Offset X" :min="-1" :max="1" :step="0.01" v-model="centerX" />
|
||||||
|
<PreviewSlider title="Center Offset Y" :min="-1" :max="1" :step="0.01" v-model="centerY" />
|
||||||
|
<PreviewSlider title="Zoom" :min="0.3" :max="3" :step="0.05" v-model="zoom" />
|
||||||
|
</div>
|
||||||
|
</Customize>
|
||||||
|
|
||||||
|
<PropTable :data="propData" />
|
||||||
|
<Dependencies :dependency-list="['ogl']" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #code>
|
||||||
|
<CodeExample :code-object="grainient" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #cli>
|
||||||
|
<CliInstallation :command="grainient.cli" />
|
||||||
|
</template>
|
||||||
|
</TabbedLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import CliInstallation from '@/components/code/CliInstallation.vue';
|
||||||
|
import CodeExample from '@/components/code/CodeExample.vue';
|
||||||
|
import Dependencies from '@/components/code/Dependencies.vue';
|
||||||
|
import BackgroundContent from '@/components/common/BackgroundContent.vue';
|
||||||
|
import Customize from '@/components/common/Customize.vue';
|
||||||
|
import PreviewColor from '@/components/common/PreviewColor.vue';
|
||||||
|
import PreviewSlider from '@/components/common/PreviewSlider.vue';
|
||||||
|
import PreviewSwitch from '@/components/common/PreviewSwitch.vue';
|
||||||
|
import PropTable from '@/components/common/PropTable.vue';
|
||||||
|
import TabbedLayout from '@/components/common/TabbedLayout.vue';
|
||||||
|
import { useForceRerender } from '@/composables/useForceRerender';
|
||||||
|
import { grainient } from '@/constants/code/Backgrounds/grainientCode';
|
||||||
|
import Grainient from '@/content/Backgrounds/Grainient/Grainient.vue';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
const { rerenderKey } = useForceRerender();
|
||||||
|
|
||||||
|
const color1 = ref('#5227FF');
|
||||||
|
const color2 = ref('#FF9FFC');
|
||||||
|
const color3 = ref('#B19EEF');
|
||||||
|
const timeSpeed = ref(0.25);
|
||||||
|
const colorBalance = ref(0.0);
|
||||||
|
const warpStrength = ref(1.0);
|
||||||
|
const warpFrequency = ref(5.0);
|
||||||
|
const warpSpeed = ref(2.0);
|
||||||
|
const warpAmplitude = ref(50.0);
|
||||||
|
const blendAngle = ref(0.0);
|
||||||
|
const blendSoftness = ref(0.05);
|
||||||
|
const rotationAmount = ref(500.0);
|
||||||
|
const noiseScale = ref(2.0);
|
||||||
|
const grainAmount = ref(0.1);
|
||||||
|
const grainScale = ref(2.0);
|
||||||
|
const grainAnimated = ref(false);
|
||||||
|
const contrast = ref(1.5);
|
||||||
|
const gamma = ref(1.0);
|
||||||
|
const saturation = ref(1.0);
|
||||||
|
const centerX = ref(0.0);
|
||||||
|
const centerY = ref(0.0);
|
||||||
|
const zoom = ref(0.9);
|
||||||
|
|
||||||
|
const propData = [
|
||||||
|
{
|
||||||
|
name: 'color1',
|
||||||
|
type: 'string',
|
||||||
|
default: "'#48FF28'",
|
||||||
|
description: 'Primary light color used in the gradient blend.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'color2',
|
||||||
|
type: 'string',
|
||||||
|
default: "'#A2FFC6'",
|
||||||
|
description: 'Secondary accent color used in the gradient blend.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'color3',
|
||||||
|
type: 'string',
|
||||||
|
default: "'#9EF19E'",
|
||||||
|
description: 'Deep base color used in the gradient blend.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'timeSpeed',
|
||||||
|
type: 'number',
|
||||||
|
default: '0.25',
|
||||||
|
description: 'Animation speed multiplier for the gradient motion.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'colorBalance',
|
||||||
|
type: 'number',
|
||||||
|
default: '0.0',
|
||||||
|
description: 'Shifts the palette balance toward dark or lighter tones.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'warpStrength',
|
||||||
|
type: 'number',
|
||||||
|
default: '1.0',
|
||||||
|
description: 'Strength of the wave warp distortion (0 = none).'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'warpFrequency',
|
||||||
|
type: 'number',
|
||||||
|
default: '5.0',
|
||||||
|
description: 'Frequency of the wave warp.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'warpSpeed',
|
||||||
|
type: 'number',
|
||||||
|
default: '2.0',
|
||||||
|
description: 'Speed multiplier for the warp animation.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'warpAmplitude',
|
||||||
|
type: 'number',
|
||||||
|
default: '50.0',
|
||||||
|
description: 'Base amplitude for the warp distortion.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'blendAngle',
|
||||||
|
type: 'number',
|
||||||
|
default: '0.0',
|
||||||
|
description: 'Rotation angle for the color blend axis (degrees).'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'blendSoftness',
|
||||||
|
type: 'number',
|
||||||
|
default: '0.05',
|
||||||
|
description: 'Softens the blend edges between color layers.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'rotationAmount',
|
||||||
|
type: 'number',
|
||||||
|
default: '500.0',
|
||||||
|
description: 'Rotation amount driven by noise.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'noiseScale',
|
||||||
|
type: 'number',
|
||||||
|
default: '2.0',
|
||||||
|
description: 'Scales the noise frequency that drives rotation.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'grainAmount',
|
||||||
|
type: 'number',
|
||||||
|
default: '0.1',
|
||||||
|
description: 'Amount of film grain applied to the gradient.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'grainScale',
|
||||||
|
type: 'number',
|
||||||
|
default: '2.0',
|
||||||
|
description: 'Scale of the grain pattern.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'grainAnimated',
|
||||||
|
type: 'boolean',
|
||||||
|
default: 'false',
|
||||||
|
description: 'Animate grain over time.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'contrast',
|
||||||
|
type: 'number',
|
||||||
|
default: '1.5',
|
||||||
|
description: 'Overall contrast applied to the final color.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'gamma',
|
||||||
|
type: 'number',
|
||||||
|
default: '1.0',
|
||||||
|
description: 'Gamma correction for the final color.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'saturation',
|
||||||
|
type: 'number',
|
||||||
|
default: '1.0',
|
||||||
|
description: 'Saturation amount for the final color.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'centerX',
|
||||||
|
type: 'number',
|
||||||
|
default: '0.0',
|
||||||
|
description: 'Horizontal offset of the gradient center.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'centerY',
|
||||||
|
type: 'number',
|
||||||
|
default: '0.0',
|
||||||
|
description: 'Vertical offset of the gradient center.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'zoom',
|
||||||
|
type: 'number',
|
||||||
|
default: '0.9',
|
||||||
|
description: 'Zoom level for the gradient field.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'className',
|
||||||
|
type: 'string',
|
||||||
|
default: "''",
|
||||||
|
description: 'Additional CSS classes applied to the container.'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user