Palette, Slider Components and Util Updates

This commit is contained in:
Conor_Mack 2020-05-31 20:55:51 +01:00
parent 28307c27b8
commit 4ef62452ef
8 changed files with 339 additions and 174 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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);
}

View File

@ -0,0 +1,2 @@
import Colorpicker from './Colorpicker.svelte';
export default Colorpicker;

View File

@ -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 ];
};

View File

@ -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]
}
}

View File

@ -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]
}