Skip to content

Instantly share code, notes, and snippets.

@jarred
Last active April 24, 2024 03:11
Show Gist options
  • Save jarred/cad9ad5be174cf715adde5f72812288f to your computer and use it in GitHub Desktop.
Save jarred/cad9ad5be174cf715adde5f72812288f to your computer and use it in GitHub Desktop.
<script lang="ts">
import knobdrag, { makeValueStore } from '$lib/knob-drag';
import { createEventDispatcher } from 'svelte';
import mediumKnob from '../../images/medium-knob.png';
export let value: number = 50;
export let disabled: boolean = false;
let min = 0;
let max = 100;
let step = 1;
$: glowOpacity = 0.4 + (value / 100) * 0.6;
let glowDiameter = 112;
const dispatch = createEventDispatcher();
const valueStore = makeValueStore(value, (newValue) => (value = newValue));
$: valueStore.set(value);
$: knobParams = { min, max, step, valueStore };
const handleMouse = (event: MouseEvent) => {
if (event.type === 'mousedown') {
document.addEventListener('mouseup', handleMouse);
document.body.classList.add('cursor-none');
dispatch('update-start');
} else if (event.type === 'mouseup') {
document.removeEventListener('mouseup', handleMouse);
dispatch('update-end');
document.body.classList.remove('cursor-none');
}
};
</script>
<div class="relative h-[152px] w-[152px]">
<img src={mediumKnob} class="absolute left-0 top-0 w-full" />
<svg width="152" height="152" viewBox="0 0 152 152" class:disabled>
<defs>
<filter
id="glowBlur"
x="-50%"
y="-50%"
height="200%"
width="200%"
xmlns="http://www.w3.org/2000/svg"
>
<feGaussianBlur in="SourceGraphic" stdDeviation="12" />
</filter>
<filter
id="reflectionBlur"
x="-40%"
y="-40%"
height="180%"
width="180%"
xmlns="http://www.w3.org/2000/svg"
>
<feGaussianBlur in="SourceGraphic" stdDeviation="4" />
</filter>
<filter
id="glintBlur"
x="-40%"
y="-40%"
height="180%"
width="180%"
xmlns="http://www.w3.org/2000/svg"
>
<feGaussianBlur in="SourceGraphic" stdDeviation="2" />
</filter>
</defs>
<circle
class="glow-bg"
r={glowDiameter / 2}
cx="76"
cy="76"
style:stroke-dashoffset="0"
style:stroke-dasharray={glowDiameter * Math.PI * 0.75}
transform="rotate(135 0 0)"
transform-origin="center center"
/>
<circle
class="glow"
r={glowDiameter / 2}
cx="76"
cy="76"
style:stroke-dashoffset={glowDiameter * Math.PI -
(glowDiameter * Math.PI * (value - min) * 0.75) / 100}
style:stroke-dasharray={glowDiameter * Math.PI}
transform="rotate(135 0 0)"
transform-origin="center center"
opacity={glowOpacity}
/>
<circle
class="blur"
r={glowDiameter / 2}
cx="76"
cy="76"
style:stroke-dashoffset={glowDiameter * Math.PI -
(glowDiameter * Math.PI * (value - min) * 0.75) / 100}
style:stroke-dasharray={glowDiameter * Math.PI}
transform="rotate(135 0 0)"
transform-origin="center center"
filter="url(#glowBlur)"
opacity={glowOpacity}
/>
<circle
class="glint"
r={glowDiameter / 2}
cx="76"
cy="76"
style:stroke-dashoffset={glowDiameter * Math.PI -
(glowDiameter * Math.PI * (value - min) * 0.75) / 100}
style:stroke-dasharray={glowDiameter * Math.PI}
transform="rotate(135 0 0)"
transform-origin="center center"
filter="url(#glintBlur)"
/>
{#if !disabled}
<circle
class="inner"
r="40"
cx="76"
cy="76"
use:knobdrag={knobParams}
on:mousedown={handleMouse}
/>
{/if}
<path
d="M76 56V62"
class="notch"
stroke-width="4"
stroke-linecap="round"
transform-origin="76 76"
transform="rotate({-135 + (value / max) * 270} 0 0)"
/>
<circle
class="reflection"
r="28"
cx="76"
cy="76"
style:stroke-dashoffset={56 * Math.PI - (56 * Math.PI * (value - min) * 0.75) / 100}
style:stroke-dasharray={56 * Math.PI}
transform="rotate(135 0 0)"
transform-origin="center center"
filter="url(#reflectionBlur)"
opacity={0.5 + glowOpacity * 0.5}
/>
</svg>
</div>
<style>
svg {
@apply pointer-events-auto relative;
}
.reflection,
.glow,
.blur,
.glint,
.glow-bg {
fill: none;
stroke: #000;
stroke-width: 8px;
stroke-linecap: round;
}
.reflection,
.blur,
.glow {
stroke: var(--fx-color);
}
.blur {
stroke-width: 8px;
}
.glint {
stroke: #fff;
stroke-width: 2px;
opacity: 0.4;
/* mix-blend-mode: overlay; */
}
.reflection {
stroke-width: 2px;
}
.inner {
fill: #000;
opacity: 0;
}
.notch {
@apply transition-[stroke];
stroke: #aaa;
}
svg.disabled {
& .notch {
stroke: #000;
}
}
svg:not(.disabled):hover {
& .notch {
stroke: #fff;
}
}
.glow,
.notch,
.blur,
.reflection {
@apply pointer-events-none;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment