mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-04-23 00:06:15 -04:00
feat: ColorConverter
Signed-off-by: Corentin Thomasset <corentin.thomasset74@gmail.com>
This commit is contained in:
parent
da2891751d
commit
d4f57fde34
2 changed files with 209 additions and 0 deletions
|
@ -10,6 +10,7 @@ import TextCypher from "./routes/tools/TextCypher";
|
||||||
import TextStats from "./routes/tools/TextStats";
|
import TextStats from "./routes/tools/TextStats";
|
||||||
import BaseConverter from "./routes/tools/BaseConverter";
|
import BaseConverter from "./routes/tools/BaseConverter";
|
||||||
import UuidGenerator from "./routes/tools/UuidGenerator";
|
import UuidGenerator from "./routes/tools/UuidGenerator";
|
||||||
|
import ColorConverter from "./routes/tools/ColorConverter";
|
||||||
|
|
||||||
Vue.use(VueRouter)
|
Vue.use(VueRouter)
|
||||||
|
|
||||||
|
@ -66,6 +67,13 @@ const toolsComponents = [
|
||||||
component: BaseConverter,
|
component: BaseConverter,
|
||||||
keywords: ['binary', 'hexadecimal', 'decimal']
|
keywords: ['binary', 'hexadecimal', 'decimal']
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
icon: 'fa-palette',
|
||||||
|
text: 'Color picker/converter',
|
||||||
|
path: '/color-picker-converter',
|
||||||
|
component: ColorConverter,
|
||||||
|
keywords: ['rgb', 'rgba', 'hexadecimal', 'hsla', 'red', 'green', 'blue', 'alpha']
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
201
src/routes/tools/ColorConverter.vue
Normal file
201
src/routes/tools/ColorConverter.vue
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
<template>
|
||||||
|
<v-card class="single-card">
|
||||||
|
<v-card-title>Color picker/converter</v-card-title>
|
||||||
|
|
||||||
|
<v-card-text>
|
||||||
|
<v-row no-gutters align="center" align-content="center" justify="center">
|
||||||
|
<v-col cols="12" sm="6" align="center">
|
||||||
|
<v-color-picker
|
||||||
|
flat
|
||||||
|
canvas-height="300"
|
||||||
|
hide-inputs
|
||||||
|
mode="rgba"
|
||||||
|
v-model="rgba"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" sm="6" align="center">
|
||||||
|
<v-form v-model="valid" ref="form">
|
||||||
|
<v-text-field
|
||||||
|
outlined
|
||||||
|
label="hex"
|
||||||
|
v-model="_hex"
|
||||||
|
:rules="rules.hex"
|
||||||
|
dense
|
||||||
|
/>
|
||||||
|
<v-text-field
|
||||||
|
outlined
|
||||||
|
label="hexa"
|
||||||
|
:rules="rules.hexa"
|
||||||
|
v-model="_hexa"
|
||||||
|
dense
|
||||||
|
/>
|
||||||
|
<v-text-field
|
||||||
|
outlined
|
||||||
|
label="rgb"
|
||||||
|
v-model="_rgb"
|
||||||
|
:rules="rules.rgb"
|
||||||
|
dense
|
||||||
|
/>
|
||||||
|
<v-text-field
|
||||||
|
outlined
|
||||||
|
label="rgba"
|
||||||
|
v-model="_rgba"
|
||||||
|
:rules="rules.rgba"
|
||||||
|
dense
|
||||||
|
/>
|
||||||
|
<v-text-field
|
||||||
|
outlined
|
||||||
|
label="hsl"
|
||||||
|
v-model="_hsl"
|
||||||
|
dense
|
||||||
|
/>
|
||||||
|
|
||||||
|
</v-form>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const required = v => !!v || 'A value is required'
|
||||||
|
const intToHex = (int) => Math.floor(int).toString(16).toUpperCase().padStart(2, '0');
|
||||||
|
const hexToInt = (hex) => parseInt(hex, 16);
|
||||||
|
const rgbToHSL = ({r, g, b}) => {
|
||||||
|
r /= 255, g /= 255, b /= 255;
|
||||||
|
const max = Math.max(r, g, b), min = Math.min(r, g, b);
|
||||||
|
let h, s, l = (max + min) / 2;
|
||||||
|
|
||||||
|
if (max === min) {
|
||||||
|
h = s = 0; // achromatic
|
||||||
|
} else {
|
||||||
|
const d = max - min;
|
||||||
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||||
|
switch (max) {
|
||||||
|
case r:
|
||||||
|
h = (g - b) / d + (g < b ? 6 : 0);
|
||||||
|
break;
|
||||||
|
case g:
|
||||||
|
h = (b - r) / d + 2;
|
||||||
|
break;
|
||||||
|
case b:
|
||||||
|
h = (r - g) / d + 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
h /= 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {h: h * 360, s: s * 100, l: l * 100};
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
name: "ColorConverter",
|
||||||
|
data: () => ({
|
||||||
|
rgba: {
|
||||||
|
"r": 76,
|
||||||
|
"g": 175,
|
||||||
|
"b": 80,
|
||||||
|
"a": 1
|
||||||
|
},
|
||||||
|
console: console,
|
||||||
|
valid: true,
|
||||||
|
rules: {
|
||||||
|
hexa: [
|
||||||
|
required,
|
||||||
|
v => /^#(?:[0-9a-fA-F]{8})$/.test(v) || 'Format should be like #112233aa'
|
||||||
|
],
|
||||||
|
hex: [
|
||||||
|
required,
|
||||||
|
v => /^#([0-9a-fA-F]{3}){1,2}$/.test(v) || 'Format should be like #112233'
|
||||||
|
],
|
||||||
|
rgb: [
|
||||||
|
required,
|
||||||
|
v => /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/.test(v) || 'Format should be like rgb(255, 0, 0)'
|
||||||
|
],
|
||||||
|
rgba: [
|
||||||
|
required,
|
||||||
|
v => /^rgba\((\d+),\s*(\d+),\s*(\d+),\s*(\d+(?:\.\d+)?)\)$/.test(v) || 'Format should be like rgb(255, 0, 0, 1)'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
computed: {
|
||||||
|
_hex: {
|
||||||
|
get() {
|
||||||
|
return `#${intToHex(this.rgba.r)}${intToHex(this.rgba.g)}${intToHex(this.rgba.b)}`
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
if (this.$refs.form.validate()) {
|
||||||
|
value = value.replace(/#/, '');
|
||||||
|
value = value.length === 3 ? value.split('').map(v => v + v) : value.match(/.{2}/g);
|
||||||
|
console.log(value);
|
||||||
|
this.rgba = {
|
||||||
|
r: hexToInt(value[0]),
|
||||||
|
g: hexToInt(value[1]),
|
||||||
|
b: hexToInt(value[2]),
|
||||||
|
a: '1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_hexa: {
|
||||||
|
get() {
|
||||||
|
return `#${intToHex(this.rgba.r)}${intToHex(this.rgba.g)}${intToHex(this.rgba.b)}${intToHex((this.rgba.a ?? 0) * 255)}`
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
if (this.$refs.form.validate()) {
|
||||||
|
value = value.replace(/#/, '');
|
||||||
|
value = value.match(/.{2}/g);
|
||||||
|
|
||||||
|
this.rgba = {
|
||||||
|
r: hexToInt(value[0]),
|
||||||
|
g: hexToInt(value[1]),
|
||||||
|
b: hexToInt(value[2]),
|
||||||
|
a: hexToInt(value[3]) / 255,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_rgb: {
|
||||||
|
get() {
|
||||||
|
return `rgb(${this.rgba.r}, ${this.rgba.g}, ${this.rgba.b})`
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
if (this.$refs.form.validate()) {
|
||||||
|
const [, r, g, b] = value.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
|
||||||
|
|
||||||
|
this.rgba = {r, g, b, a: 1}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_rgba: {
|
||||||
|
get() {
|
||||||
|
return `rgba(${this.rgba.r}, ${this.rgba.g}, ${this.rgba.b}, ${parseFloat((this.rgba.a ?? 0).toFixed(2))})`
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
if (this.$refs.form.validate()) {
|
||||||
|
const [, r, g, b, a] = value.match(/^rgba\((\d+),\s*(\d+),\s*(\d+),\s*(\d+(?:\.\d+)?)\)$/);
|
||||||
|
|
||||||
|
this.rgba = {r, g, b, a: parseFloat(a)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_hsl: {
|
||||||
|
get() {
|
||||||
|
const {h, s, l} = rgbToHSL(this.rgba)
|
||||||
|
|
||||||
|
return `hsl(${Math.floor(h)}, ${Math.floor(s )}%, ${Math.floor(l)}%)`
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
if (this.$refs.form.validate()) {
|
||||||
|
const [, r, g, b, a] = value.match(/^rgba\((\d+),\s*(\d+),\s*(\d+),\s*(\d+(?:\.\d+)?)\)$/);
|
||||||
|
|
||||||
|
this.rgba = {r, g, b, a: parseFloat(a)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
Loading…
Add table
Add a link
Reference in a new issue