修复 src 结构
This commit is contained in:
113
src/component/colorPicker/ColorBox.vue
Normal file
113
src/component/colorPicker/ColorBox.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "ColorBox",
|
||||
};
|
||||
</script>
|
||||
<script setup lang="ts">
|
||||
import { Nullable } from "../type";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import { HSBToHEX, RGBSTo, RGBToHSB } from "./colorUtil";
|
||||
import ColorPicker from "./ColorPicker.vue";
|
||||
import { usePosition } from "@layui/hooks-vue";
|
||||
|
||||
interface BoxProps {
|
||||
color?: string;
|
||||
size?: Nullable<string>;
|
||||
alpha?: boolean;
|
||||
format?: "hex" | "rgb";
|
||||
predefine?: boolean;
|
||||
colors?: string[];
|
||||
}
|
||||
|
||||
const colorBoxProps = withDefaults(defineProps<BoxProps>(), {
|
||||
color: "",
|
||||
size: () => null,
|
||||
alpha: false,
|
||||
format: "hex",
|
||||
predefine: false,
|
||||
colors: () => [
|
||||
//默认预定义颜色列表
|
||||
"#009688",
|
||||
"#5FB878",
|
||||
"#1E9FFF",
|
||||
"#FF5722",
|
||||
"#FFB800",
|
||||
"#01AAED",
|
||||
"#999",
|
||||
"#c00",
|
||||
"#ff8c00",
|
||||
"#ffd700",
|
||||
"#90ee90",
|
||||
"#00ced1",
|
||||
"#1e90ff",
|
||||
"#c71585",
|
||||
"rgb(0, 186, 189)",
|
||||
"rgb(255, 120, 0)",
|
||||
"rgb(250, 212, 0)",
|
||||
"#393D49",
|
||||
"rgba(0,0,0,.5)",
|
||||
"rgba(255, 69, 0, 0.68)",
|
||||
"rgba(144, 240, 144, 0.5)",
|
||||
"rgba(31, 147, 255, 0.73)",
|
||||
],
|
||||
});
|
||||
|
||||
const triggerSpanStyle = computed(() => {
|
||||
let bgstr = "";
|
||||
if (colorBoxProps.color) {
|
||||
bgstr = colorBoxProps.color;
|
||||
|
||||
if ((colorBoxProps.color.match(/[0-9]{1,3}/g) || []).length > 3) {
|
||||
//需要优化
|
||||
if (!(colorBoxProps.alpha && colorBoxProps.format == "rgb")) {
|
||||
bgstr = "#" + HSBToHEX(RGBToHSB(RGBSTo(colorBoxProps.color)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
background: bgstr,
|
||||
};
|
||||
});
|
||||
|
||||
const colorPickerWrapper = computed(() => {
|
||||
return colorBoxProps.size ? `layui-colorpicker-${colorBoxProps.size}` : "";
|
||||
});
|
||||
|
||||
const colorBoxRefEl = ref<HTMLElement | null>(null);
|
||||
const colorPickerRefEl = ref<HTMLElement | null>(null);
|
||||
|
||||
onMounted(() => {
|
||||
console.log("colorPickerRefEl =>>>", colorPickerRefEl.value.teleportRefEl);
|
||||
usePosition(colorBoxRefEl.value, colorPickerRefEl.value.teleportRefEl);
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div ref="colorBoxRefEl" class="layui-unselect layui-colorpicker">
|
||||
<span
|
||||
:class="[
|
||||
{
|
||||
'layui-colorpicker-trigger-bgcolor': format == 'rgb' && alpha,
|
||||
},
|
||||
size ? colorPickerWrapper : '',
|
||||
]"
|
||||
>
|
||||
<span class="layui-colorpicker-trigger-span" :style="triggerSpanStyle">
|
||||
<!-- ICON_PICKER_DOWN = 'layui-icon-down', ICON_PICKER_CLOSE = 'layui-icon-close' -->
|
||||
<i
|
||||
:class="[
|
||||
'layui-icon layui-colorpicker-trigger-i',
|
||||
color ? 'layui-icon-down' : 'layui-icon-close',
|
||||
]"
|
||||
></i>
|
||||
</span>
|
||||
</span>
|
||||
<ColorPicker
|
||||
ref="colorPickerRefEl"
|
||||
:visible="true"
|
||||
:alpha="alpha"
|
||||
:predefine="predefine"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="less"></style>
|
||||
91
src/component/colorPicker/ColorPicker.vue
Normal file
91
src/component/colorPicker/ColorPicker.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "ColorPicker",
|
||||
};
|
||||
</script>
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
|
||||
interface CProps {
|
||||
visible: boolean;
|
||||
alpha: boolean;
|
||||
predefine: boolean;
|
||||
}
|
||||
|
||||
const props = defineProps<CProps>();
|
||||
|
||||
const domRefEl = ref<HTMLElement | null>(null);
|
||||
defineExpose({
|
||||
teleportRefEl: domRefEl,
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<teleport to="body">
|
||||
<div
|
||||
v-if="visible"
|
||||
ref="domRefEl"
|
||||
class="layui-anim layui-anim-downbit layui-colorpicker-main"
|
||||
>
|
||||
<!-- //颜色面板-->
|
||||
<div class="layui-colorpicker-main-wrapper">
|
||||
<div class="layui-colorpicker-basis">
|
||||
<div class="layui-colorpicker-basis-white"></div>
|
||||
<div class="layui-colorpicker-basis-black"></div>
|
||||
<div class="layui-colorpicker-basis-cursor"></div>
|
||||
</div>
|
||||
<div class="layui-colorpicker-side">
|
||||
<div class="layui-colorpicker-side-slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- //透明度条块-->
|
||||
<div
|
||||
:class="[
|
||||
{
|
||||
'layui-colorpicker-main-alpha': true,
|
||||
'layui-show': alpha,
|
||||
},
|
||||
]"
|
||||
>
|
||||
<div class="layui-colorpicker-alpha-bgcolor">
|
||||
<div class="layui-colorpicker-alpha-slider"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- //预设颜色列表-->
|
||||
<div v-if="predefine" class="layui-colorpicker-main-pre">
|
||||
<div
|
||||
v-for="c in colors"
|
||||
:key="c"
|
||||
:class="{
|
||||
'layui-colorpicker-pre': true,
|
||||
'layui-colorpicker-pre-isalpha':
|
||||
(c.match(/[0-9]{1,3}/g) || []).length > 3,
|
||||
}"
|
||||
>
|
||||
<div :style="{ background: c }"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- //底部表单元素区域-->
|
||||
<div class="layui-colorpicker-main-input">
|
||||
<div class="layui-inline">
|
||||
<input type="text" class="layui-input" />
|
||||
</div>
|
||||
<div class="layui-btn-container">
|
||||
<button
|
||||
class="layui-btn layui-btn-primary layui-btn-sm"
|
||||
colorpicker-events="clear"
|
||||
>
|
||||
清空
|
||||
</button>
|
||||
<button
|
||||
class="layui-btn layui-btn-sm"
|
||||
colorpicker-events="confirm"
|
||||
type="submit"
|
||||
>
|
||||
确定
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</teleport>
|
||||
</template>
|
||||
<style scoped lang="less"></style>
|
||||
34
src/component/colorPicker/colorPicker.type.ts
Normal file
34
src/component/colorPicker/colorPicker.type.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
export interface ColorPickerProps {
|
||||
/**
|
||||
* 默认颜色,不管你是使用 hex、rgb 还是 rgba 的格式输入,最终会以指定的格式显示。
|
||||
* v-model:color
|
||||
*/
|
||||
color: string;
|
||||
/**
|
||||
* 颜色显示/输入格式,可选值: hex、rgb
|
||||
* 若在 rgb 格式下开启了透明度,格式会自动变成 rgba。在没有输入颜色的前提下,组件会默认为 #000 也就是黑色。
|
||||
* default: hex(即 16 进制色值)
|
||||
*/
|
||||
format: "hex" | "rgb";
|
||||
/**
|
||||
* 是否开启透明度,若不开启,则不会显示透明框。开启了透明度选项时,当你的默认颜色为 hex 或 rgb 格式,
|
||||
* 组件会默认加上值为 1 的透明度。相同的,当你没有开启透明度,却以 rgba 格式设置默认颜色时,组件会默认没有透明度。
|
||||
* 注意:该参数必须配合 rgba 颜色值使用
|
||||
* default: false
|
||||
*/
|
||||
alpha: boolean;
|
||||
/**
|
||||
* 预定义颜色是否开启
|
||||
* default: false
|
||||
*/
|
||||
predefine: boolean;
|
||||
/**
|
||||
* 预定义颜色,此参数需配合 predefine: true 使用。
|
||||
* 此处列举一部分:['#ff4500','#1e90ff','rgba(255, 69, 0, 0.68)','rgb(255, 120, 0)']
|
||||
*/
|
||||
colors: string[];
|
||||
/**
|
||||
* 下拉框大小,可以选择:lg、sm、xs。
|
||||
*/
|
||||
size: "lg" | "sm" | "xs";
|
||||
}
|
||||
113
src/component/colorPicker/colorUtil.ts
Normal file
113
src/component/colorPicker/colorUtil.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
export interface RGB {
|
||||
h: number;
|
||||
s: number;
|
||||
b: number;
|
||||
}
|
||||
|
||||
// RGB转HSB
|
||||
export function RGBToHSB(rgb: any) {
|
||||
const hsb = { h: 0, s: 0, b: 0 };
|
||||
const min = Math.min(rgb.r, rgb.g, rgb.b);
|
||||
const max = Math.max(rgb.r, rgb.g, rgb.b);
|
||||
const delta = max - min;
|
||||
hsb.b = max;
|
||||
hsb.s = max != 0 ? (255 * delta) / max : 0;
|
||||
if (hsb.s != 0) {
|
||||
if (rgb.r == max) {
|
||||
hsb.h = (rgb.g - rgb.b) / delta;
|
||||
} else if (rgb.g == max) {
|
||||
hsb.h = 2 + (rgb.b - rgb.r) / delta;
|
||||
} else {
|
||||
hsb.h = 4 + (rgb.r - rgb.g) / delta;
|
||||
}
|
||||
} else {
|
||||
hsb.h = -1;
|
||||
}
|
||||
if (max == min) {
|
||||
hsb.h = 0;
|
||||
}
|
||||
hsb.h *= 60;
|
||||
if (hsb.h < 0) {
|
||||
hsb.h += 360;
|
||||
}
|
||||
hsb.s *= 100 / 255;
|
||||
hsb.b *= 100 / 255;
|
||||
return hsb;
|
||||
}
|
||||
|
||||
// HEX转HSB
|
||||
export function HEXToHSB(hex: any) {
|
||||
hex = hex.indexOf("#") > -1 ? hex.substring(1) : hex;
|
||||
if (hex.length == 3) {
|
||||
const num = hex.split("");
|
||||
hex = num[0] + num[0] + num[1] + num[1] + num[2] + num[2];
|
||||
}
|
||||
hex = parseInt(hex, 16);
|
||||
const rgb = { r: hex >> 16, g: (hex & 0x00ff00) >> 8, b: hex & 0x0000ff };
|
||||
return RGBToHSB(rgb);
|
||||
}
|
||||
|
||||
// HSB转RGB
|
||||
export function HSBToRGB(hsb: any) {
|
||||
const rgb: any = {};
|
||||
let h = hsb.h;
|
||||
const s = (hsb.s * 255) / 100;
|
||||
const b = (hsb.b * 255) / 100;
|
||||
if (s == 0) {
|
||||
rgb.r = rgb.g = rgb.b = b;
|
||||
} else {
|
||||
const t1 = b;
|
||||
const t2 = ((255 - s) * b) / 255;
|
||||
const t3 = ((t1 - t2) * (h % 60)) / 60;
|
||||
if (h == 360) h = 0;
|
||||
if (h < 60) {
|
||||
rgb.r = t1;
|
||||
rgb.b = t2;
|
||||
rgb.g = t2 + t3;
|
||||
} else if (h < 120) {
|
||||
rgb.g = t1;
|
||||
rgb.b = t2;
|
||||
rgb.r = t1 - t3;
|
||||
} else if (h < 180) {
|
||||
rgb.g = t1;
|
||||
rgb.r = t2;
|
||||
rgb.b = t2 + t3;
|
||||
} else if (h < 240) {
|
||||
rgb.b = t1;
|
||||
rgb.r = t2;
|
||||
rgb.g = t1 - t3;
|
||||
} else if (h < 300) {
|
||||
rgb.b = t1;
|
||||
rgb.g = t2;
|
||||
rgb.r = t2 + t3;
|
||||
} else if (h < 360) {
|
||||
rgb.r = t1;
|
||||
rgb.g = t2;
|
||||
rgb.b = t1 - t3;
|
||||
} else {
|
||||
rgb.r = 0;
|
||||
rgb.g = 0;
|
||||
rgb.b = 0;
|
||||
}
|
||||
}
|
||||
return { r: Math.round(rgb.r), g: Math.round(rgb.g), b: Math.round(rgb.b) };
|
||||
}
|
||||
|
||||
// HSB转HEX
|
||||
export function HSBToHEX(hsb: any) {
|
||||
const rgb = HSBToRGB(hsb);
|
||||
const hex = [rgb.r.toString(16), rgb.g.toString(16), rgb.b.toString(16)];
|
||||
hex.forEach((val, nr) => {
|
||||
if (val.length == 1) {
|
||||
hex[nr] = "0" + val;
|
||||
}
|
||||
});
|
||||
return hex.join("");
|
||||
}
|
||||
|
||||
//转化成所需rgb格式
|
||||
export function RGBSTo(rgbs: any) {
|
||||
const regexp = /[0-9]{1,3}/g;
|
||||
const re = rgbs.match(regexp) || [];
|
||||
return { r: re[0], g: re[1], b: re[2] };
|
||||
}
|
||||
9
src/component/colorPicker/index.ts
Normal file
9
src/component/colorPicker/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import type { App } from "vue";
|
||||
import Component from "./index.vue";
|
||||
import type { IDefineComponent } from "../type/index";
|
||||
|
||||
Component.install = (app: App) => {
|
||||
app.component(Component.name || "LayColorPicker", Component);
|
||||
};
|
||||
|
||||
export default Component as IDefineComponent;
|
||||
58
src/component/colorPicker/index.vue
Normal file
58
src/component/colorPicker/index.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "LayColorPicker",
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Nullable } from "/@src/module/type";
|
||||
import ColorBox from "./ColorBox.vue";
|
||||
|
||||
interface ColorPickerProps {
|
||||
color?: string;
|
||||
size?: Nullable<string>;
|
||||
alpha?: boolean;
|
||||
format?: "hex" | "rgb";
|
||||
predefine?: boolean;
|
||||
colors?: string[];
|
||||
}
|
||||
|
||||
const colorPickerProps = withDefaults(defineProps<ColorPickerProps>(), {
|
||||
color: "",
|
||||
size: () => null,
|
||||
alpha: false,
|
||||
format: "hex",
|
||||
predefine: false,
|
||||
colors: () => [
|
||||
//默认预定义颜色列表
|
||||
"#009688",
|
||||
"#5FB878",
|
||||
"#1E9FFF",
|
||||
"#FF5722",
|
||||
"#FFB800",
|
||||
"#01AAED",
|
||||
"#999",
|
||||
"#c00",
|
||||
"#ff8c00",
|
||||
"#ffd700",
|
||||
"#90ee90",
|
||||
"#00ced1",
|
||||
"#1e90ff",
|
||||
"#c71585",
|
||||
"rgb(0, 186, 189)",
|
||||
"rgb(255, 120, 0)",
|
||||
"rgb(250, 212, 0)",
|
||||
"#393D49",
|
||||
"rgba(0,0,0,.5)",
|
||||
"rgba(255, 69, 0, 0.68)",
|
||||
"rgba(144, 240, 144, 0.5)",
|
||||
"rgba(31, 147, 255, 0.73)",
|
||||
],
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="layui-inline'">
|
||||
<ColorBox />
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user