mirror of
https://github.com/DavidHDev/vue-bits.git
synced 2026-03-07 22:49:31 -07:00
Merge branch 'main' into feat/defineModel-support
This commit is contained in:
@@ -14,17 +14,13 @@
|
||||
</div>
|
||||
|
||||
<Customize>
|
||||
<div class="space-y-2">
|
||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-gray-100">Color Stops</h3>
|
||||
|
||||
<div class="flex gap-4">
|
||||
<PreviewColor
|
||||
v-for="(color, index) in colorStops"
|
||||
:key="index"
|
||||
:title="`Color ${index + 1}`"
|
||||
v-model="colorStops[index]"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<PreviewColor
|
||||
v-for="(_, index) in colorStops"
|
||||
:key="index"
|
||||
:title="`Color ${index + 1}`"
|
||||
v-model="colorStops[index]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<PreviewSlider title="Amplitude" v-model="amplitude" :min="0" :max="2" :step="0.1" />
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</div>
|
||||
|
||||
<Customize>
|
||||
<div class="flex gap-4">
|
||||
<div class="flex gap-2">
|
||||
<PreviewColor
|
||||
v-for="(_, index) in colorStops"
|
||||
:key="index"
|
||||
@@ -23,7 +23,7 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<PreviewSlider title="Pixelation" v-model="pixelation" :min="0" :max="2000" :step="10" />
|
||||
<PreviewSlider title="Pixelation" v-model="pixelation" :min="100" :max="2000" :step="10" />
|
||||
|
||||
<PreviewSwitch title="Enable Mouse Interaction" v-model="mouseInteractionEnabled" />
|
||||
|
||||
|
||||
220
src/demo/Backgrounds/BallpitDemo.vue
Normal file
220
src/demo/Backgrounds/BallpitDemo.vue
Normal file
@@ -0,0 +1,220 @@
|
||||
<template>
|
||||
<TabbedLayout>
|
||||
<template #preview>
|
||||
<div class="relative p-0 h-[500px] overflow-hidden demo-container">
|
||||
<RefreshButton @click="forceRerender" />
|
||||
<p class="z-0 absolute font-black text-[#271e37] text-[200px]">Balls.</p>
|
||||
<Ballpit
|
||||
className="relative"
|
||||
:key="key"
|
||||
:count="count"
|
||||
:gravity="gravity"
|
||||
:friction="friction"
|
||||
:wallBounce="wallBounce"
|
||||
:followCursor="followCursor"
|
||||
:colors="colors"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Customize>
|
||||
<PreviewSwitch title="Display Cursor" v-model="followCursor" @update:model-value="forceRerender" />
|
||||
|
||||
<PreviewSlider
|
||||
title="Ball Count"
|
||||
:min="50"
|
||||
:max="500"
|
||||
:step="10"
|
||||
v-model="count"
|
||||
@onChange="
|
||||
(val: number) => {
|
||||
count = val;
|
||||
}
|
||||
"
|
||||
/>
|
||||
|
||||
<PreviewSlider
|
||||
title="Gravity"
|
||||
:min="0.1"
|
||||
:max="1"
|
||||
:step="0.1"
|
||||
v-model="gravity"
|
||||
@onChange="
|
||||
(val: number) => {
|
||||
gravity = val;
|
||||
}
|
||||
"
|
||||
/>
|
||||
|
||||
<PreviewSlider
|
||||
title="Friction"
|
||||
:min="0.9"
|
||||
:max="1"
|
||||
:step="0.001"
|
||||
v-model="friction"
|
||||
@onChange="
|
||||
(val: number) => {
|
||||
friction = val;
|
||||
}
|
||||
"
|
||||
/>
|
||||
|
||||
<PreviewSlider
|
||||
title="Wall Bounce"
|
||||
:min="0.1"
|
||||
:max="1"
|
||||
:step="0.05"
|
||||
v-model="wallBounce"
|
||||
@onChange="
|
||||
(val: number) => {
|
||||
wallBounce = val;
|
||||
}
|
||||
"
|
||||
/>
|
||||
</Customize>
|
||||
|
||||
<PropTable :data="propData" />
|
||||
<Dependencies :dependency-list="['three']" />
|
||||
</template>
|
||||
|
||||
<template #code>
|
||||
<CodeExample :code-object="ballpit" />
|
||||
</template>
|
||||
|
||||
<template #cli>
|
||||
<CliInstallation :command="ballpit.cli" />
|
||||
</template>
|
||||
</TabbedLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useForceRerender } from '@/composables/useForceRerender';
|
||||
import { ref, watch } from 'vue';
|
||||
import CliInstallation from '../../components/code/CliInstallation.vue';
|
||||
import CodeExample from '../../components/code/CodeExample.vue';
|
||||
import Dependencies from '../../components/code/Dependencies.vue';
|
||||
import Customize from '../../components/common/Customize.vue';
|
||||
import PreviewSlider from '../../components/common/PreviewSlider.vue';
|
||||
import PreviewSwitch from '../../components/common/PreviewSwitch.vue';
|
||||
import PropTable from '../../components/common/PropTable.vue';
|
||||
import RefreshButton from '../../components/common/RefreshButton.vue';
|
||||
import TabbedLayout from '../../components/common/TabbedLayout.vue';
|
||||
import { ballpit } from '../../constants/code/Backgrounds/ballpitCode';
|
||||
import Ballpit from '../../content/Backgrounds/Ballpit/Ballpit.vue';
|
||||
|
||||
const { rerenderKey: key, forceRerender } = useForceRerender();
|
||||
|
||||
const count = ref(100);
|
||||
const gravity = ref(0.5);
|
||||
const friction = ref(0.9975);
|
||||
const wallBounce = ref(0.95);
|
||||
const followCursor = ref(false);
|
||||
|
||||
const colors = [0xffffff, 0x000000, 0x27ff64];
|
||||
|
||||
watch(
|
||||
[count, gravity, friction, wallBounce, followCursor],
|
||||
() => {
|
||||
forceRerender();
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
const propData = [
|
||||
{
|
||||
name: 'count',
|
||||
type: 'number',
|
||||
default: '200',
|
||||
description: 'Sets the number of balls in the ballpit.'
|
||||
},
|
||||
{
|
||||
name: 'gravity',
|
||||
type: 'number',
|
||||
default: '0.5',
|
||||
description: 'Controls the gravity affecting the balls.'
|
||||
},
|
||||
{
|
||||
name: 'friction',
|
||||
type: 'number',
|
||||
default: '0.9975',
|
||||
description: 'Sets the friction applied to the ball movement.'
|
||||
},
|
||||
{
|
||||
name: 'wallBounce',
|
||||
type: 'number',
|
||||
default: '0.95',
|
||||
description: 'Determines how much balls bounce off walls.'
|
||||
},
|
||||
{
|
||||
name: 'followCursor',
|
||||
type: 'boolean',
|
||||
default: 'true',
|
||||
description: 'Enables or disables the sphere following the cursor.'
|
||||
},
|
||||
{
|
||||
name: 'colors',
|
||||
type: 'array',
|
||||
default: '[0, 0, 0]',
|
||||
description: 'Defines the colors of the balls.'
|
||||
},
|
||||
{
|
||||
name: 'ambientColor',
|
||||
type: 'number',
|
||||
default: '16777215',
|
||||
description: 'Sets the ambient light color.'
|
||||
},
|
||||
{
|
||||
name: 'ambientIntensity',
|
||||
type: 'number',
|
||||
default: '1',
|
||||
description: 'Controls the intensity of ambient light.'
|
||||
},
|
||||
{
|
||||
name: 'lightIntensity',
|
||||
type: 'number',
|
||||
default: '200',
|
||||
description: 'Sets the intensity of the main light source.'
|
||||
},
|
||||
{
|
||||
name: 'minSize',
|
||||
type: 'number',
|
||||
default: '0.5',
|
||||
description: 'Specifies the minimum size of the balls.'
|
||||
},
|
||||
{
|
||||
name: 'maxSize',
|
||||
type: 'number',
|
||||
default: '1',
|
||||
description: 'Specifies the maximum size of the balls.'
|
||||
},
|
||||
{
|
||||
name: 'size0',
|
||||
type: 'number',
|
||||
default: '1',
|
||||
description: 'Initial size value for the cursor ball.'
|
||||
},
|
||||
{
|
||||
name: 'maxVelocity',
|
||||
type: 'number',
|
||||
default: '0.15',
|
||||
description: 'Limits the maximum velocity of the balls.'
|
||||
},
|
||||
{
|
||||
name: 'maxX',
|
||||
type: 'number',
|
||||
default: '5',
|
||||
description: 'Defines the maximum X-coordinate boundary.'
|
||||
},
|
||||
{
|
||||
name: 'maxY',
|
||||
type: 'number',
|
||||
default: '5',
|
||||
description: 'Defines the maximum Y-coordinate boundary.'
|
||||
},
|
||||
{
|
||||
name: 'maxZ',
|
||||
type: 'number',
|
||||
default: '2',
|
||||
description: 'Defines the maximum Z-coordinate boundary.'
|
||||
}
|
||||
];
|
||||
</script>
|
||||
126
src/demo/Backgrounds/OrbDemo.vue
Normal file
126
src/demo/Backgrounds/OrbDemo.vue
Normal file
@@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<TabbedLayout>
|
||||
<template #preview>
|
||||
<div class="relative p-0 h-[500px] overflow-hidden demo-container">
|
||||
<Orb
|
||||
:hue="debouncedHue"
|
||||
:hoverIntensity="debouncedHoverIntensity"
|
||||
:rotateOnHover="rotateOnHover"
|
||||
:forceHoverState="forceHoverState"
|
||||
/>
|
||||
<p class="z-0 absolute mb-0 font-black text-[clamp(2rem,2vw,6rem)] mix-blend-difference">Hover.</p>
|
||||
</div>
|
||||
|
||||
<Customize>
|
||||
<PreviewSlider
|
||||
title="Hue Shift"
|
||||
:min="0"
|
||||
:max="360"
|
||||
:step="1"
|
||||
v-model="hue"
|
||||
@onChange="
|
||||
(val: number) => {
|
||||
hue = val;
|
||||
}
|
||||
"
|
||||
/>
|
||||
|
||||
<PreviewSlider
|
||||
title="Hover Intensity"
|
||||
:min="0"
|
||||
:max="5"
|
||||
:step="0.01"
|
||||
v-model="hoverIntensity"
|
||||
@onChange="
|
||||
(val: number) => {
|
||||
hoverIntensity = val;
|
||||
}
|
||||
"
|
||||
/>
|
||||
|
||||
<PreviewSwitch title="Rotate on Hover" v-model="rotateOnHover" @update:model-value="forceRerender" />
|
||||
|
||||
<PreviewSwitch title="Force Hover State" v-model="forceHoverState" @update:model-value="forceRerender" />
|
||||
</Customize>
|
||||
|
||||
<PropTable :data="propData" />
|
||||
<Dependencies :dependency-list="['ogl']" />
|
||||
</template>
|
||||
|
||||
<template #code>
|
||||
<CodeExample :code-object="orb" />
|
||||
</template>
|
||||
|
||||
<template #cli>
|
||||
<CliInstallation :command="orb.cli" />
|
||||
</template>
|
||||
</TabbedLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useForceRerender } from '@/composables/useForceRerender';
|
||||
import { ref, watch } from 'vue';
|
||||
import CliInstallation from '../../components/code/CliInstallation.vue';
|
||||
import CodeExample from '../../components/code/CodeExample.vue';
|
||||
import Dependencies from '../../components/code/Dependencies.vue';
|
||||
import Customize from '../../components/common/Customize.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 { orb } from '../../constants/code/Backgrounds/orbCode';
|
||||
import Orb from '../../content/Backgrounds/Orb/Orb.vue';
|
||||
|
||||
const { forceRerender } = useForceRerender();
|
||||
|
||||
const hue = ref(100);
|
||||
const hoverIntensity = ref(0.5);
|
||||
const rotateOnHover = ref(true);
|
||||
const forceHoverState = ref(false);
|
||||
|
||||
const debouncedHue = ref(100);
|
||||
const debouncedHoverIntensity = ref(0.5);
|
||||
|
||||
let hueTimeout: number;
|
||||
let hoverIntensityTimeout: number;
|
||||
|
||||
watch(hue, newValue => {
|
||||
clearTimeout(hueTimeout);
|
||||
hueTimeout = setTimeout(() => {
|
||||
debouncedHue.value = newValue;
|
||||
}, 300);
|
||||
});
|
||||
watch(hoverIntensity, newValue => {
|
||||
clearTimeout(hoverIntensityTimeout);
|
||||
hoverIntensityTimeout = setTimeout(() => {
|
||||
debouncedHoverIntensity.value = newValue;
|
||||
}, 300);
|
||||
});
|
||||
|
||||
const propData = [
|
||||
{
|
||||
name: 'hue',
|
||||
type: 'number',
|
||||
default: '100',
|
||||
description: 'The base hue for the orb (in degrees).'
|
||||
},
|
||||
{
|
||||
name: 'hoverIntensity',
|
||||
type: 'number',
|
||||
default: '0.2',
|
||||
description: 'Controls the intensity of the hover distortion effect.'
|
||||
},
|
||||
{
|
||||
name: 'rotateOnHover',
|
||||
type: 'boolean',
|
||||
default: 'true',
|
||||
description: 'Toggle to enable or disable continuous rotation on hover.'
|
||||
},
|
||||
{
|
||||
name: 'forceHoverState',
|
||||
type: 'boolean',
|
||||
default: 'false',
|
||||
description: 'Force hover animations even when the orb is not actually hovered.'
|
||||
}
|
||||
];
|
||||
</script>
|
||||
Reference in New Issue
Block a user