Palette, Slider Components and Util Updates
This commit is contained in:
parent
7aa882c568
commit
2ec8ed5464
|
@ -0,0 +1,32 @@
|
||||||
|
<script>
|
||||||
|
import Slider from "./Slider.svelte";
|
||||||
|
import Palette from "./Palette.svelte";
|
||||||
|
|
||||||
|
export let value = "#00000000";
|
||||||
|
|
||||||
|
let h = 0;
|
||||||
|
let s = 0;
|
||||||
|
let v = 0;
|
||||||
|
let a = 1;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.colorpicker-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 300px;
|
||||||
|
width: 250px;
|
||||||
|
background: #ffffff;
|
||||||
|
border: 1px solid #e8e8ef;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="colorpicker-container">
|
||||||
|
|
||||||
|
<Palette {h} {a} />
|
||||||
|
|
||||||
|
<Slider type="hue" on:change={hue => (h = hue.detail)} />
|
||||||
|
|
||||||
|
<Slider type="alpha" on:change={alpha => (a = alpha.detail)} />
|
||||||
|
</div>
|
|
@ -0,0 +1,49 @@
|
||||||
|
<script>
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
export let h,
|
||||||
|
a = 0;
|
||||||
|
|
||||||
|
let palette;
|
||||||
|
let dimensions;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (palette) {
|
||||||
|
dimensions = palette.getBoundingClientRect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleClick(event) {
|
||||||
|
const { left, top, width, height } = dimensions;
|
||||||
|
let pickerX = (event.clientX - left) / width;
|
||||||
|
let pickerY = (event.clientY - top) / height;
|
||||||
|
//Saturation - adds white: pickerX * 100
|
||||||
|
//value - adds black: 100 - pickerY * 100
|
||||||
|
console.log("X", pickerX, "Y", pickerY);
|
||||||
|
}
|
||||||
|
|
||||||
|
$: paletteGradient = `linear-gradient(to top, rgba(0, 0, 0, 1), transparent),
|
||||||
|
linear-gradient(to left, hsla(${h}, 100%, 50%, ${a}), rgba(255, 255, 255, ${a}))
|
||||||
|
`;
|
||||||
|
$: style = `background: ${paletteGradient};`;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.palette {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 175px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker {
|
||||||
|
position: absolute;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
background: transparent;
|
||||||
|
border: 2px solid white;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div bind:this={palette} on:click={handleClick} class="palette" {style}>
|
||||||
|
<div class="picker" />
|
||||||
|
</div>
|
|
@ -0,0 +1,87 @@
|
||||||
|
<script>
|
||||||
|
import { onMount, createEventDispatcher } from "svelte";
|
||||||
|
import dragable from "./drag.js";
|
||||||
|
|
||||||
|
export let type = "hue";
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
let slider;
|
||||||
|
let dimensions = {};
|
||||||
|
let thumbPosition = 0;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (slider) {
|
||||||
|
dimensions = slider.getBoundingClientRect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleClick(mouseX) {
|
||||||
|
const { left, width } = dimensions;
|
||||||
|
let clickPosition = mouseX - left;
|
||||||
|
debugger;
|
||||||
|
if (clickPosition >= 0 && clickPosition <= width) {
|
||||||
|
thumbPosition = clickPosition;
|
||||||
|
let percentageClick = thumbPosition / width;
|
||||||
|
let value =
|
||||||
|
type === "hue"
|
||||||
|
? Math.round(360 * percentageClick).toString()
|
||||||
|
: percentageClick.toFixed(2);
|
||||||
|
dispatch("change", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$: style = `transform: translateX(${thumbPosition - 6}px);`;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.color-format-slider {
|
||||||
|
position: relative;
|
||||||
|
align-self: center;
|
||||||
|
height: 8px;
|
||||||
|
width: 220px;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 10px 0px;
|
||||||
|
border: 1px solid #e8e8ef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hue {
|
||||||
|
background: linear-gradient(
|
||||||
|
to right,
|
||||||
|
hsl(0, 100%, 50%),
|
||||||
|
hsl(60, 100%, 50%),
|
||||||
|
hsl(120, 100%, 50%),
|
||||||
|
hsl(180, 100%, 50%),
|
||||||
|
hsl(240, 100%, 50%),
|
||||||
|
hsl(300, 100%, 50%),
|
||||||
|
hsl(360, 100%, 50%)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.alpha {
|
||||||
|
background: linear-gradient(to right, transparent, rgb(0 0 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-thumb {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -3px;
|
||||||
|
height: 12px;
|
||||||
|
width: 12px;
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div
|
||||||
|
bind:this={slider}
|
||||||
|
on:click={event => handleClick(event.clientX)}
|
||||||
|
class="color-format-slider"
|
||||||
|
class:hue={type === 'hue'}
|
||||||
|
class:alpha={type === 'alpha'}>
|
||||||
|
<div
|
||||||
|
use:dragable
|
||||||
|
on:drag={e => handleClick(e.detail)}
|
||||||
|
class="slider-thumb"
|
||||||
|
{style} />
|
||||||
|
</div>
|
|
@ -0,0 +1,23 @@
|
||||||
|
export default function(node) {
|
||||||
|
function handleMouseDown() {
|
||||||
|
window.addEventListener('mousemove', handleMouseMove);
|
||||||
|
window.addEventListener('mouseup', handleMouseUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMouseMove(event) {
|
||||||
|
let mouseX = event.clientX;
|
||||||
|
console.log(mouseX);
|
||||||
|
node.dispatchEvent(
|
||||||
|
new CustomEvent('drag', {
|
||||||
|
detail: mouseX
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMouseUp() {
|
||||||
|
window.removeEventListener('mousedown', handleMouseDown);
|
||||||
|
window.removeEventListener('mousemove', handleMouseMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
node.addEventListener('mousedown', handleMouseDown);
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
import Colorpicker from './Colorpicker.svelte';
|
||||||
|
export default Colorpicker;
|
|
@ -0,0 +1,146 @@
|
||||||
|
export const getRgbaValues = (rgbaString) => rgbaString.replace(/[a-z()\s]/gi, '').split(',');
|
||||||
|
|
||||||
|
export const getHexaValues = (hexString) => hexString.match(/[A-F]{2}|[A-F]\d{1}|\d{2}|\d[A-F]/gi);
|
||||||
|
|
||||||
|
export const isValidRgba = (rgba) => {
|
||||||
|
let [ r, g, b, a = 1 ] = rgba;
|
||||||
|
|
||||||
|
let isValidLengthRange = rgba.length === 3 || rgba.length === 4;
|
||||||
|
let isValidColorRange = [ r, g, b ].every((v) => v >= 0 && v <= 255);
|
||||||
|
let isValidAlphaRange = rgba.length === 3 || (a >= 0 && a <= 1);
|
||||||
|
|
||||||
|
return isValidLengthRange && isValidColorRange && isValidAlphaRange;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const determineColorType = (color) => {
|
||||||
|
let hsva = [];
|
||||||
|
if (color.startsWith('#')) {
|
||||||
|
let [ rHex, gHex, bHex, aHex ] = getHexaValues(color);
|
||||||
|
hsva = hexaToHSVA([ rHex, gHex, bHex ], aHex);
|
||||||
|
} else if (color.startsWith('rgb')) {
|
||||||
|
let rgba = getRgbaValues(color);
|
||||||
|
hsva = rgbaToHSVA(rgba);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getHSLA = (hsv, a) => {
|
||||||
|
const [ h, s, l ] = hsvToHSL(hsv);
|
||||||
|
return `hsla(${h}, ${s}, ${l}, ${a})`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const hexaToHSVA = (hex, alpha = 'FF') => {
|
||||||
|
const rgba = hex.map((v) => parseInt(v, 16)).concat((parseInt(alpha, 16) / 255).toFixed(1));
|
||||||
|
return rgbaToHSVA(rgba);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const rgbaToHSVA = (rgba) => {
|
||||||
|
if (isValidRgba(rgba)) {
|
||||||
|
const [ r, g, b, a = '1' ] = rgba;
|
||||||
|
let hsv = rgbToHSV([ r, g, b ]);
|
||||||
|
return [ ...hsv, a ];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const hsvaToHexa = () => {
|
||||||
|
const [ r, g, b, a ] = hsvaToRgba();
|
||||||
|
const hexa = [ r, g, b ].map((v) => v.toString(16)).concat((a * 255).toFixed(1).toString(16));
|
||||||
|
return hexa;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const hsvaToRgba = (h, s, v, a) => {
|
||||||
|
let rgb = _hsvToRgb([ h, s, v ]);
|
||||||
|
return [ ...rgb, a ];
|
||||||
|
};
|
||||||
|
|
||||||
|
//Credit : https://github.com/Qix-/color-convert
|
||||||
|
export const _rgbToHSV = (rgb) => {
|
||||||
|
let rdif;
|
||||||
|
let gdif;
|
||||||
|
let bdif;
|
||||||
|
let h;
|
||||||
|
let s;
|
||||||
|
|
||||||
|
const r = rgb[0] / 255;
|
||||||
|
const g = rgb[1] / 255;
|
||||||
|
const b = rgb[2] / 255;
|
||||||
|
const v = Math.max(r, g, b);
|
||||||
|
const diff = v - Math.min(r, g, b);
|
||||||
|
const diffc = function(c) {
|
||||||
|
return (v - c) / 6 / diff + 1 / 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (diff === 0) {
|
||||||
|
h = 0;
|
||||||
|
s = 0;
|
||||||
|
} else {
|
||||||
|
s = diff / v;
|
||||||
|
rdif = diffc(r);
|
||||||
|
gdif = diffc(g);
|
||||||
|
bdif = diffc(b);
|
||||||
|
|
||||||
|
if (r === v) {
|
||||||
|
h = bdif - gdif;
|
||||||
|
} else if (g === v) {
|
||||||
|
h = 1 / 3 + rdif - bdif;
|
||||||
|
} else if (b === v) {
|
||||||
|
h = 2 / 3 + gdif - rdif;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h < 0) {
|
||||||
|
h += 1;
|
||||||
|
} else if (h > 1) {
|
||||||
|
h -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const hsvResult = [ h * 360, s * 100, v * 100 ].map((v) => v.toFixed(0));
|
||||||
|
return hsvResult;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Credit : https://github.com/Qix-/color-convert
|
||||||
|
export const _hsvToRgb = (hsv) => {
|
||||||
|
const h = hsv[0] / 60;
|
||||||
|
const s = hsv[1] / 100;
|
||||||
|
let v = hsv[2] / 100;
|
||||||
|
const hi = Math.floor(h) % 6;
|
||||||
|
|
||||||
|
const f = h - Math.floor(h);
|
||||||
|
const p = 255 * v * (1 - s);
|
||||||
|
const q = 255 * v * (1 - s * f);
|
||||||
|
const t = 255 * v * (1 - s * (1 - f));
|
||||||
|
v *= 255;
|
||||||
|
|
||||||
|
switch (hi) {
|
||||||
|
case 0:
|
||||||
|
return [ v, t, p ];
|
||||||
|
case 1:
|
||||||
|
return [ q, v, p ];
|
||||||
|
case 2:
|
||||||
|
return [ p, v, t ];
|
||||||
|
case 3:
|
||||||
|
return [ p, q, v ];
|
||||||
|
case 4:
|
||||||
|
return [ t, p, v ];
|
||||||
|
case 5:
|
||||||
|
return [ v, p, q ];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//Credit : https://github.com/Qix-/color-convert
|
||||||
|
export const _hsvToHSL = (hsv) => {
|
||||||
|
const h = hsv[0];
|
||||||
|
const s = hsv[1] / 100;
|
||||||
|
const v = hsv[2] / 100;
|
||||||
|
const vmin = Math.max(v, 0.01);
|
||||||
|
let sl;
|
||||||
|
let l;
|
||||||
|
|
||||||
|
l = (2 - s) * v;
|
||||||
|
const lmin = (2 - s) * vmin;
|
||||||
|
sl = s * vmin;
|
||||||
|
sl /= lmin <= 1 ? lmin : 2 - lmin;
|
||||||
|
sl = sl || 0;
|
||||||
|
l /= 2;
|
||||||
|
|
||||||
|
return [ h, sl * 100, l * 100 ];
|
||||||
|
};
|
|
@ -1,66 +0,0 @@
|
||||||
import {
|
|
||||||
getHexaValues,
|
|
||||||
getRgbaValues,
|
|
||||||
hsvToHSL,
|
|
||||||
isValidRgba,
|
|
||||||
rgbToHSV,
|
|
||||||
hsvToRgb,
|
|
||||||
} from "./utils"
|
|
||||||
|
|
||||||
export class HSVAColor {
|
|
||||||
h = 0
|
|
||||||
s = 0
|
|
||||||
v = 0
|
|
||||||
a = 1
|
|
||||||
|
|
||||||
constructor(color) {
|
|
||||||
if (color.startsWith("#")) {
|
|
||||||
let [rHex, gHex, bHex, aHex] = getHexaValues(color)
|
|
||||||
this.hexaToHSVA([rHex, gHex, bHex], aHex)
|
|
||||||
} else if (color.startsWith("rgb")) {
|
|
||||||
let rgba = getRgbaValues(color)
|
|
||||||
this.rgbaToHSVA(rgba)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setHSVA([h, s, v, a]) {
|
|
||||||
this.h = h
|
|
||||||
this.s = s
|
|
||||||
this.v = v
|
|
||||||
this.a = a
|
|
||||||
}
|
|
||||||
|
|
||||||
getHSLA() {
|
|
||||||
const [h, s, l] = hsvToHSL([this.h, this.s, this.v])
|
|
||||||
return `hsla(${h}, ${s}, ${l}, ${this.a})`
|
|
||||||
}
|
|
||||||
|
|
||||||
hexaToHSVA(hex, alpha = "FF") {
|
|
||||||
const rgba = hex
|
|
||||||
.map(v => parseInt(v, 16))
|
|
||||||
.concat((parseInt(alpha, 16) / 255).toFixed(1))
|
|
||||||
this.rgbaToHSVA(rgba)
|
|
||||||
}
|
|
||||||
|
|
||||||
rgbaToHSVA(rgba) {
|
|
||||||
if (isValidRgba(rgba)) {
|
|
||||||
const [r, g, b, a = "1"] = rgba
|
|
||||||
let hsv = rgbToHSV([r, g, b])
|
|
||||||
this.setHSVA([...hsv, a])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hsvaToHexa() {
|
|
||||||
const [r, g, b, a] = this.hsvaToRgba()
|
|
||||||
const hexa = [r, g, b]
|
|
||||||
.map(v => v.toString(16))
|
|
||||||
.concat((a * 255).toFixed(1).toString(16))
|
|
||||||
return hexa
|
|
||||||
}
|
|
||||||
|
|
||||||
hsvaToRgba() {
|
|
||||||
const { h, s, v, a } = this
|
|
||||||
let rgb = hsvToRgb([h, s, v])
|
|
||||||
return [...rgb, a]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,108 +0,0 @@
|
||||||
export const getRgbaValues = rgbaString =>
|
|
||||||
rgbaString.replace(/[a-z\(\)\s]/gi, "").split(",")
|
|
||||||
|
|
||||||
export const getHexaValues = hexString =>
|
|
||||||
hexString.match(/[A-F]{2}|[A-F]\d{1}|\d{2}|\d[A-F]/gi)
|
|
||||||
|
|
||||||
export const isValidRgba = rgba => {
|
|
||||||
let [r, g, b, a = 1] = rgba
|
|
||||||
|
|
||||||
let isValidLengthRange = rgba.length === 3 || rgba.length === 4
|
|
||||||
let isValidColorRange = [r, g, b].every(v => v >= 0 && v <= 255)
|
|
||||||
let isValidAlphaRange = rgba.length === 3 || (a >= 0 && a <= 1)
|
|
||||||
|
|
||||||
return isValidLengthRange && isValidColorRange && isValidAlphaRange
|
|
||||||
}
|
|
||||||
|
|
||||||
//Credit : https://github.com/Qix-/color-convert
|
|
||||||
export const rgbToHSV = rgb => {
|
|
||||||
let rdif
|
|
||||||
let gdif
|
|
||||||
let bdif
|
|
||||||
let h
|
|
||||||
let s
|
|
||||||
|
|
||||||
const r = rgb[0] / 255
|
|
||||||
const g = rgb[1] / 255
|
|
||||||
const b = rgb[2] / 255
|
|
||||||
const v = Math.max(r, g, b)
|
|
||||||
const diff = v - Math.min(r, g, b)
|
|
||||||
const diffc = function(c) {
|
|
||||||
return (v - c) / 6 / diff + 1 / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diff === 0) {
|
|
||||||
h = 0
|
|
||||||
s = 0
|
|
||||||
} else {
|
|
||||||
s = diff / v
|
|
||||||
rdif = diffc(r)
|
|
||||||
gdif = diffc(g)
|
|
||||||
bdif = diffc(b)
|
|
||||||
|
|
||||||
if (r === v) {
|
|
||||||
h = bdif - gdif
|
|
||||||
} else if (g === v) {
|
|
||||||
h = 1 / 3 + rdif - bdif
|
|
||||||
} else if (b === v) {
|
|
||||||
h = 2 / 3 + gdif - rdif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h < 0) {
|
|
||||||
h += 1
|
|
||||||
} else if (h > 1) {
|
|
||||||
h -= 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const hsvResult = [h * 360, s * 100, v * 100].map(v => v.toFixed(0))
|
|
||||||
return hsvResult
|
|
||||||
}
|
|
||||||
|
|
||||||
//Credit : https://github.com/Qix-/color-convert
|
|
||||||
export const hsvToRgb = hsv => {
|
|
||||||
const h = hsv[0] / 60
|
|
||||||
const s = hsv[1] / 100
|
|
||||||
let v = hsv[2] / 100
|
|
||||||
const hi = Math.floor(h) % 6
|
|
||||||
|
|
||||||
const f = h - Math.floor(h)
|
|
||||||
const p = 255 * v * (1 - s)
|
|
||||||
const q = 255 * v * (1 - s * f)
|
|
||||||
const t = 255 * v * (1 - s * (1 - f))
|
|
||||||
v *= 255
|
|
||||||
|
|
||||||
switch (hi) {
|
|
||||||
case 0:
|
|
||||||
return [v, t, p]
|
|
||||||
case 1:
|
|
||||||
return [q, v, p]
|
|
||||||
case 2:
|
|
||||||
return [p, v, t]
|
|
||||||
case 3:
|
|
||||||
return [p, q, v]
|
|
||||||
case 4:
|
|
||||||
return [t, p, v]
|
|
||||||
case 5:
|
|
||||||
return [v, p, q]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Credit : https://github.com/Qix-/color-convert
|
|
||||||
export const hsvToHSL = hsv => {
|
|
||||||
const h = hsv[0]
|
|
||||||
const s = hsv[1] / 100
|
|
||||||
const v = hsv[2] / 100
|
|
||||||
const vmin = Math.max(v, 0.01)
|
|
||||||
let sl
|
|
||||||
let l
|
|
||||||
|
|
||||||
l = (2 - s) * v
|
|
||||||
const lmin = (2 - s) * vmin
|
|
||||||
sl = s * vmin
|
|
||||||
sl /= lmin <= 1 ? lmin : 2 - lmin
|
|
||||||
sl = sl || 0
|
|
||||||
l /= 2
|
|
||||||
|
|
||||||
return [h, sl * 100, l * 100]
|
|
||||||
}
|
|
Loading…
Reference in New Issue