You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
3.2 KiB
108 lines
3.2 KiB
<script lang="ts" context="module">
|
|
export const selectedColorPicker = writable<any>(null);</script>
|
|
|
|
<script lang="ts">
|
|
import type { Color } from "$lib/models/color";
|
|
import { rgb2hsv } from "$lib/utils/color";
|
|
import { tick } from "svelte";
|
|
import { writable } from "svelte/store";
|
|
|
|
export let color: Color;
|
|
export let id: any = null;
|
|
|
|
let xy: boolean;
|
|
let x: number;
|
|
let y: number;
|
|
|
|
$: {
|
|
if (color.xy) {
|
|
xy = true;
|
|
x = color.xy.x;
|
|
y = color.xy.y;
|
|
} else if (color.hs) {
|
|
xy = false;
|
|
x = Math.sin((360-color.hs.hue) * (Math.PI / 180)) * (color.hs.sat * 0.85);
|
|
y = Math.cos((360-color.hs.hue) * (Math.PI / 180)) * (color.hs.sat * 0.85);
|
|
} else if (color.k) {
|
|
const angle = 2.5 + ((color.k - 1000) / 11000) * 355;
|
|
|
|
x = Math.sin((180-angle) * (Math.PI / 180)) * 0.95;
|
|
y = Math.cos((180-angle) * (Math.PI / 180)) * 0.95;
|
|
} else if (color.rgb) {
|
|
const hs = rgb2hsv(color.rgb);
|
|
|
|
xy = false;
|
|
x = Math.sin((360-hs.hue) * (Math.PI / 180)) * (hs.sat * 0.85);
|
|
y = Math.cos((360-hs.hue) * (Math.PI / 180)) * (hs.sat * 0.85);
|
|
}
|
|
}
|
|
|
|
function onClickColor(event: MouseEvent & { currentTarget: EventTarget & HTMLDivElement; }) {
|
|
if (xy) {
|
|
const x = Math.floor((event.offsetX / event.currentTarget.offsetWidth) * 1000) / 1000;
|
|
const y = Math.floor((event.offsetY / event.currentTarget.offsetHeight) * 1000) / 1000;
|
|
color = { xy: { x, y } };
|
|
} else {
|
|
const x = 2 * ((event.offsetX / event.currentTarget.offsetWidth) - 0.505);
|
|
const y = 2 * ((event.offsetY / event.currentTarget.offsetHeight) - 0.505);
|
|
|
|
const dist = Math.sqrt((x*x)+(y*y));
|
|
const angle = ((Math.atan2(y/dist, x/dist)*(180/Math.PI))+360) % 360.0
|
|
|
|
if (dist > 0.9) {
|
|
color = { k: Math.max(Math.min(Math.floor((((((angle + 90) % 360)-2.5)/355) * 11000) + 1000), 12000), 1000) }
|
|
} else {
|
|
color = { hs: { hue: Math.floor((270+angle)%360), sat: Math.floor(Math.min(dist / 0.85, 1) * 100) / 100 } };
|
|
}
|
|
}
|
|
|
|
tick().then(() => {
|
|
tick().then(() => { $selectedColorPicker = id; });
|
|
});
|
|
}
|
|
</script>
|
|
|
|
{#if $selectedColorPicker == id}
|
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
<div class="color-picker" on:click={onClickColor}>
|
|
{#if xy}
|
|
<img draggable="false" alt="color wheel" src="/color-xy.png" />
|
|
<div class="dot" style="left: calc({x} * 10ch); top: calc({y-1} * 10ch)">
|
|
<div class="ring"></div>
|
|
</div>
|
|
{:else}
|
|
<img draggable="false" alt="color wheel" src="/color-hsk.png" />
|
|
<div class="dot" style="left: calc({((x/2)+0.5)} * 10ch + 0.5px); top: calc({((y/2)+0.5)-1} * 10ch + 0.5px)">
|
|
<div class="ring"></div>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
|
|
<style lang="sass">
|
|
@import "$lib/css/colors.sass"
|
|
|
|
div.color-picker
|
|
position: relative
|
|
width: 10ch
|
|
height: 10ch
|
|
|
|
> img
|
|
width: 10ch
|
|
height: 10ch
|
|
|
|
div.dot
|
|
position: relative
|
|
z-index: 10
|
|
pointer-events: none
|
|
|
|
div.ring
|
|
position: relative
|
|
left: -0.525ch
|
|
top: -0.95ch
|
|
width: 1ch
|
|
height: 1ch
|
|
border: 2px solid $color-main4
|
|
box-sizing: border-box
|
|
border-radius: 1ch
|
|
</style>
|