init
This commit is contained in:
43
src/component/colorPicker/EyeDropper.vue
Normal file
43
src/component/colorPicker/EyeDropper.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<svg
|
||||
t="1651169382813"
|
||||
class="icon"
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="2529"
|
||||
width="27"
|
||||
height="27"
|
||||
>
|
||||
<path
|
||||
d="M769.3 409.1c-4.3-16.2-14.7-29.7-29.2-38l-51.3-29.6-10 17.3c-3.7 6.4-10.4 10-17.3 10-3.4 0-6.8-0.9-10-2.7l68.6 39.6c5.2 3 9 7.9 10.5 13.7 1.6 5.8 0.8 11.9-2.3 17.2l-6.6 11.5c-6.2 10.8-20.1 14.5-30.9 8.3L441 312.2c-5.2-3-9-7.9-10.5-13.7-1.6-5.8-0.8-11.9 2.3-17.2l6.6-11.5c3-5.2 7.9-9 13.7-10.5 1.9-0.5 3.9-0.8 5.9-0.8 3.9 0 7.8 1 11.3 3l69.3 40c-9.6-5.5-12.8-17.8-7.3-27.3l10-17.3-52-30c-14.5-8.4-31.4-10.6-47.5-6.3-16.2 4.3-29.7 14.7-38 29.2l-6.6 11.5c-8.4 14.5-10.6 31.4-6.3 47.5 4.3 16.2 14.7 29.7 29.2 38l52 30 10-17.3c5.5-9.6 17.8-12.8 27.3-7.3 9.6 5.5 12.8 17.8 7.3 27.3l-10 17.3 77.2 44.6 10-17.3c5.5-9.6 17.8-12.8 27.3-7.3 9.6 5.5 12.8 17.8 7.3 27.3l-10 17.3 51.3 29.6c9.8 5.7 20.6 8.4 31.2 8.4 21.7 0 42.7-11.2 54.3-31.3l6.6-11.5c8.5-14.5 10.7-31.4 6.4-47.5z"
|
||||
fill="#515151"
|
||||
p-id="2530"
|
||||
></path>
|
||||
<path
|
||||
d="M644.2 338.8l10-17.3-77.2-44.6-10 17.3c-5.5 9.6-17.8 12.8-27.3 7.3l111.8 64.6c-9.6-5.5-12.9-17.8-7.3-27.3zM539.6 301.5zM651.5 366.1z"
|
||||
fill="#515151"
|
||||
p-id="2531"
|
||||
></path>
|
||||
<path
|
||||
d="M624.1 195.2c12.3-21.3 39.6-28.6 60.9-16.3 10.3 6 17.7 15.6 20.8 27.1s1.5 23.5-4.5 33.8l-47.2 81.7 34.6 20 47.2-81.7c11.3-19.6 14.3-42.4 8.5-64.2-5.8-21.8-19.8-40.1-39.4-51.4-40.4-23.3-92.2-9.4-115.5 31l-47.2 81.7 34.6 20 47.2-81.7z"
|
||||
fill="#515151"
|
||||
p-id="2532"
|
||||
></path>
|
||||
<path
|
||||
d="M644.2 338.8c-5.5 9.6-2.2 21.8 7.3 27.3 3.1 1.8 6.6 2.7 10 2.7 6.9 0 13.6-3.6 17.3-10l10-17.3-34.6-20-10 17.3zM539.6 301.5c9.6 5.5 21.8 2.2 27.3-7.3l10-17.3-34.6-20-10 17.3c-5.5 9.6-2.2 21.8 7.3 27.3z"
|
||||
fill="#515151"
|
||||
p-id="2533"
|
||||
></path>
|
||||
<path
|
||||
d="M395.4 769.6c-2.6 4.4-6.5 7.6-11 9-2.3 0.7-6.9 1.5-11.3-1-9.6-5.5-21.8-2.2-27.3 7.3l-23.1 40c-1.7 2.9-4.2 5-7.1 5.8-1.7 0.5-4.1 0.8-6.5-0.5-2.4-1.4-3.3-3.7-3.7-5.4-0.7-2.9-0.1-6.2 1.5-9l22.9-39.7c5.6-9.7 2.3-22.2-7.4-27.8-7.3-4.2-9.2-14.7-4.2-23.3l189.5-328.2-34.6-20L283.6 705c-12.4 21.4-10.1 47.2 3.7 64.8l-15 26c-6.7 11.6-8.8 25.1-5.9 37.9 3 13.4 11.1 24.4 22.7 31.1 7.3 4.2 15.4 6.4 23.7 6.4 4.9 0 9.8-0.7 14.6-2.2 12.6-3.9 23.2-12.4 29.9-24.1l15-26c7.8 1.1 15.9 0.4 23.8-2 14.2-4.4 26.2-14.1 33.8-27.3l189.5-328.2-34.6-20-189.4 328.2z"
|
||||
fill="#515151"
|
||||
p-id="2534"
|
||||
></path>
|
||||
<path
|
||||
d="M622.2 416.8c-9.6-5.5-21.8-2.2-27.3 7.3l-10 17.3 34.6 20 10-17.3c5.6-9.6 2.3-21.8-7.3-27.3zM517.7 379.5c5.5-9.6 2.2-21.8-7.3-27.3-9.6-5.5-21.8-2.2-27.3 7.3l-10 17.3 34.6 20 10-17.3z"
|
||||
fill="#515151"
|
||||
p-id="2535"
|
||||
></path>
|
||||
</svg>
|
||||
</template>
|
||||
389
src/component/colorPicker/index.less
Normal file
389
src/component/colorPicker/index.less
Normal file
@@ -0,0 +1,389 @@
|
||||
@import "../dropdown/index.less";
|
||||
|
||||
.layui-color-picker {
|
||||
position: relative;
|
||||
user-select: none;
|
||||
width: 320px;
|
||||
background: #fff;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.saturation-value {
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.saturation-value > div {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.point {
|
||||
box-sizing: border-box;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background-color: transparent;
|
||||
border: 2px solid #ccc;
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
position: absolute;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.saturation-value-2 {
|
||||
background: linear-gradient(to right, white, #ffffff00);
|
||||
}
|
||||
|
||||
.saturation-value-3 {
|
||||
background: linear-gradient(to top, black, #ffffff00);
|
||||
}
|
||||
|
||||
.layui-color-picker-middle {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.hue-slider {
|
||||
position: relative;
|
||||
margin-bottom: 6px;
|
||||
height: 10px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
red 0,
|
||||
#ff0 17%,
|
||||
#0f0 33%,
|
||||
#0ff 50%,
|
||||
#00f 67%,
|
||||
#f0f 83%,
|
||||
red
|
||||
);
|
||||
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.alpha-slider {
|
||||
position: relative;
|
||||
height: 10px;
|
||||
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
|
||||
background: #fff
|
||||
url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAWElEQVRIiWM8fubkfwYygKWJOSM5+mCAhRLNoxaPWjxq8ajFoxbTyeL/DAfJ0Xjs3Cl7Siwmu4Yht1aDgZEYx6MWj1o8avGoxaMWD3qLya5X//4nqx6HAQC7RBGFzolqTAAAAABJRU5ErkJggg==");
|
||||
background-size: 10px 10px;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: absolute;
|
||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
|
||||
box-sizing: border-box;
|
||||
width: 6px;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.color-diamond {
|
||||
position: relative;
|
||||
margin-left: 5px;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAWElEQVRIiWM8fubkfwYygKWJOSM5+mCAhRLNoxaPWjxq8ajFoxbTyeL/DAfJ0Xjs3Cl7Siwmu4Yht1aDgZEYx6MWj1o8avGoxaMWD3qLya5X//4nqx6HAQC7RBGFzolqTAAAAABJRU5ErkJggg==");
|
||||
background-size: 10px 10px;
|
||||
}
|
||||
|
||||
.layui-colorpicker > span {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
display: block;
|
||||
border-radius: var(--global-border-radius);
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAWElEQVRIiWM8fubkfwYygKWJOSM5+mCAhRLNoxaPWjxq8ajFoxbTyeL/DAfJ0Xjs3Cl7Siwmu4Yht1aDgZEYx6MWj1o8avGoxaMWD3qLya5X//4nqx6HAQC7RBGFzolqTAAAAABJRU5ErkJggg==");
|
||||
background-size: 10px 10px;
|
||||
}
|
||||
|
||||
.color-value {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.color-value div {
|
||||
padding: 0 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.color-value input {
|
||||
font-size: 12px;
|
||||
box-sizing: border-box;
|
||||
width: 34px;
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
outline: none;
|
||||
text-align: center;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
|
||||
.color-value p {
|
||||
font-size: 12px;
|
||||
margin: 3px 0 0;
|
||||
}
|
||||
|
||||
.color-value .rgba-a {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.color-value .hex {
|
||||
flex: 1;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.color-value .hex input {
|
||||
width: 100%;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.preset {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin: 10px 0 0;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.preset li {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
padding: 0px;
|
||||
margin-right: 6px;
|
||||
margin-bottom: 6px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.layui-colorpicker {
|
||||
border: 1px solid var(--global-neutral-color-3);
|
||||
padding: 5px;
|
||||
border-radius: var(--global-border-radius);
|
||||
line-height: 24px;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
-webkit-transition: all 0.3s;
|
||||
}
|
||||
|
||||
.layui-colorpicker:hover {
|
||||
border-color: var(--global-neutral-color-6);
|
||||
}
|
||||
|
||||
.layui-colorpicker.layui-colorpicker-lg {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.layui-colorpicker.layui-colorpicker-sm {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.layui-colorpicker.layui-colorpicker-xs {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.layui-colorpicker-trigger-bgcolor {
|
||||
display: block;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.layui-colorpicker-trigger-span {
|
||||
display: block;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
border-radius: var(--global-border-radius);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.layui-colorpicker-trigger-i {
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.layui-colorpicker-trigger-i.layui-icon-close {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.layui-colorpicker-main {
|
||||
position: absolute;
|
||||
left: -999999px;
|
||||
top: -999999px;
|
||||
z-index: 66666666;
|
||||
width: 280px;
|
||||
margin: 5px 0;
|
||||
padding: 7px;
|
||||
background: #fff;
|
||||
border: 1px solid var(--global-neutral-color-6);
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.layui-colorpicker-main-wrapper {
|
||||
height: 180px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.layui-colorpicker-basis {
|
||||
width: 260px;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.layui-colorpicker-basis-white {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: linear-gradient(90deg, #fff, hsla(0, 0%, 100%, 0));
|
||||
}
|
||||
|
||||
.layui-colorpicker-basis-black {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: linear-gradient(0deg, #000, transparent);
|
||||
}
|
||||
|
||||
.layui-colorpicker-basis-cursor {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
right: -3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.layui-colorpicker-side {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 12px;
|
||||
height: 100%;
|
||||
background: linear-gradient(red, #ff0, #0f0, #0ff, #00f, #f0f, red);
|
||||
}
|
||||
|
||||
.layui-colorpicker-side-slider {
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
box-shadow: 0 0 1px #888;
|
||||
background: #fff;
|
||||
border-radius: 1px;
|
||||
border: 1px solid #f0f0f0;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.layui-colorpicker-main-alpha {
|
||||
display: none;
|
||||
height: 12px;
|
||||
margin-top: 7px;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
|
||||
}
|
||||
|
||||
.layui-colorpicker-alpha-bgcolor {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.layui-colorpicker-alpha-slider {
|
||||
width: 5px;
|
||||
height: 100%;
|
||||
box-shadow: 0 0 1px #888;
|
||||
background: #fff;
|
||||
border-radius: 1px;
|
||||
border: 1px solid #f0f0f0;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.layui-colorpicker-main-pre {
|
||||
padding-top: 7px;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.layui-colorpicker-pre {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 2px;
|
||||
display: inline-block;
|
||||
margin-left: 6px;
|
||||
margin-bottom: 7px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.layui-colorpicker-pre:nth-child(11n + 1) {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.layui-colorpicker-pre-isalpha {
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
|
||||
}
|
||||
|
||||
.layui-colorpicker-pre.layui-this {
|
||||
box-shadow: 0 0 3px 2px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.layui-colorpicker-pre > div {
|
||||
height: 100%;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.layui-colorpicker-main-input {
|
||||
text-align: right;
|
||||
padding-top: 7px;
|
||||
}
|
||||
|
||||
.layui-colorpicker-main-input .layui-btn-container .layui-btn {
|
||||
margin: 0 0 0 10px;
|
||||
}
|
||||
|
||||
.layui-colorpicker-main-input div.layui-inline {
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.layui-colorpicker-main-input input.layui-input {
|
||||
width: 150px;
|
||||
height: 30px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.layui-colorpicker-disabled {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.layui-colorpicker-disabled,
|
||||
.layui-colorpicker-disabled * {
|
||||
cursor: not-allowed !important;
|
||||
}
|
||||
5
src/component/colorPicker/index.ts
Normal file
5
src/component/colorPicker/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { withInstall, WithInstallType } from "../../utils";
|
||||
import Component from "./index.vue";
|
||||
|
||||
const component: WithInstallType<typeof Component> = withInstall(Component);
|
||||
export default component;
|
||||
512
src/component/colorPicker/index.vue
Normal file
512
src/component/colorPicker/index.vue
Normal file
@@ -0,0 +1,512 @@
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "LayColorPicker",
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import "./index.less";
|
||||
import LayDropdown from "../dropdown/index.vue";
|
||||
import EyeDropper from "./EyeDropper.vue";
|
||||
import { ref, computed, watch, onMounted, StyleValue } from "vue";
|
||||
import { useEyeDropper } from "@vueuse/core";
|
||||
|
||||
export interface ColorPicker {
|
||||
modelValue?: any;
|
||||
preset?: any;
|
||||
disabled?: boolean;
|
||||
eyeDropper?: boolean;
|
||||
contentClass?: string | Array<string | object> | object;
|
||||
contentStyle?: StyleValue;
|
||||
}
|
||||
|
||||
const emit = defineEmits(["update:modelValue"]);
|
||||
|
||||
const props = withDefaults(defineProps<ColorPicker>(), {
|
||||
modelValue: { r: 255, g: 255, b: 255, a: 1 },
|
||||
preset: ["#009688", "#1e9fff", "#ffb800", "#ff5722", "#5fb878"],
|
||||
disabled: false,
|
||||
});
|
||||
|
||||
const saturationValue = ref<null | HTMLElement>(null);
|
||||
const hueSlider = ref<null | HTMLElement>(null);
|
||||
const alphaSlider = ref<null | HTMLElement>(null);
|
||||
const { isSupported, open, sRGBHex } = useEyeDropper();
|
||||
|
||||
let pointStyle = ref("top: 25%;left: 80%;");
|
||||
let hueSliderStyle = ref("left: 0;");
|
||||
let alphaSliderStyle = ref("left: calc(100% - 6px);");
|
||||
|
||||
let hue = ref(0);
|
||||
let saturation = ref(1);
|
||||
let value = ref(1);
|
||||
|
||||
let red = ref(255);
|
||||
let green = ref(0);
|
||||
let blue = ref(0);
|
||||
let alpha = ref(1);
|
||||
|
||||
const openEyeDropper = function () {
|
||||
if (isSupported) {
|
||||
open();
|
||||
} else {
|
||||
console.warn("LayColorPicker: Eye dropper not supported by your browser!");
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
let { r, g, b, a } = parseColor(props.modelValue);
|
||||
red.value = r;
|
||||
green.value = g;
|
||||
blue.value = b;
|
||||
alpha.value = a;
|
||||
});
|
||||
|
||||
watch(sRGBHex, (sRGBHex) => {
|
||||
let { r, g, b, a } = hex2rgba(sRGBHex);
|
||||
red.value = r;
|
||||
green.value = g;
|
||||
blue.value = b;
|
||||
alpha.value = a;
|
||||
});
|
||||
|
||||
watch([red, green, blue], (newValue) => {
|
||||
emit(
|
||||
"update:modelValue",
|
||||
rgba2hex(red.value, green.value, blue.value, alpha.value)
|
||||
);
|
||||
let { h, s, v } = rgb2hsv(red.value, green.value, blue.value);
|
||||
hue.value = h;
|
||||
saturation.value = s;
|
||||
value.value = v;
|
||||
pointStyle.value = `top: ${100 - v * 100}%;left: ${s * 100}%;`;
|
||||
hueSliderStyle.value = `left: ${(hue.value / 360) * 100}%;`;
|
||||
});
|
||||
|
||||
watch(alpha, () => {
|
||||
emit(
|
||||
"update:modelValue",
|
||||
rgba2hex(red.value, green.value, blue.value, alpha.value)
|
||||
);
|
||||
alphaSliderStyle.value = `left: ${
|
||||
alpha.value >= 1 ? "calc(100% - 6px)" : alpha.value * 100 + "%"
|
||||
};`;
|
||||
});
|
||||
|
||||
let colorObj = computed(() => {
|
||||
let r = red.value;
|
||||
let g = green.value;
|
||||
let b = blue.value;
|
||||
let a = alpha.value;
|
||||
let h = hue.value;
|
||||
let s = saturation.value;
|
||||
let v = value.value;
|
||||
return {
|
||||
rgb: `rgba(${r},${g},${b})`,
|
||||
rgba: `rgba(${r},${g},${b},${a})`,
|
||||
hex6: rgba2hex(r, g, b),
|
||||
hex8: rgba2hex(r, g, b, a),
|
||||
hsv: `hsv(${h},${s},${v})`,
|
||||
hsl: ``,
|
||||
};
|
||||
});
|
||||
|
||||
function hexChange(e: any) {
|
||||
let v = e.target.value;
|
||||
if (/^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(v)) {
|
||||
let { r, g, b, a } = hex2rgba(v);
|
||||
red.value = r;
|
||||
green.value = g;
|
||||
blue.value = b;
|
||||
alpha.value = a;
|
||||
}
|
||||
}
|
||||
|
||||
function redChange(e: any) {
|
||||
let v = e.target.value;
|
||||
if (v !== "") {
|
||||
v > 255 && (red.value = 255);
|
||||
v < 0 && (red.value = 0);
|
||||
v >= 0 && v <= 255 && (red.value = parseInt(v));
|
||||
}
|
||||
}
|
||||
|
||||
function greenChange(e: any) {
|
||||
let v = e.target.value;
|
||||
if (v !== "") {
|
||||
v > 255 && (green.value = 255);
|
||||
v < 0 && (green.value = 0);
|
||||
v >= 0 && v <= 255 && (green.value = parseInt(v));
|
||||
}
|
||||
}
|
||||
|
||||
function blueChange(e: any) {
|
||||
let v = e.target.value;
|
||||
if (v !== "") {
|
||||
v > 255 && (blue.value = 255);
|
||||
v < 0 && (blue.value = 0);
|
||||
v >= 0 && v <= 255 && (blue.value = parseInt(v));
|
||||
}
|
||||
}
|
||||
|
||||
function alphaChange(e: any) {
|
||||
let v = e.target.value;
|
||||
if (v !== "") {
|
||||
v = parseFloat(v);
|
||||
alpha.value = v;
|
||||
v > 1 && (alpha.value = 1);
|
||||
v < 0 && (alpha.value = 0);
|
||||
v >= 0 && v <= 1 && (alpha.value = v);
|
||||
}
|
||||
}
|
||||
|
||||
function presetChange(item: any) {
|
||||
if (/^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(item)) {
|
||||
let { r, g, b, a } = hex2rgba(item);
|
||||
red.value = r;
|
||||
green.value = g;
|
||||
blue.value = b;
|
||||
alpha.value = a;
|
||||
}
|
||||
}
|
||||
|
||||
function handleChangeSV(e: any) {
|
||||
// @ts-ignore
|
||||
let w = saturationValue.value.clientWidth;
|
||||
// @ts-ignore
|
||||
let h = saturationValue.value.clientHeight;
|
||||
// @ts-ignore
|
||||
let x = e.pageX - saturationValue.value.getBoundingClientRect().left;
|
||||
// @ts-ignore
|
||||
let y = e.pageY - saturationValue.value.getBoundingClientRect().top;
|
||||
x = x < w && x > 0 ? x : x > w ? w : 0;
|
||||
y = y < h && y > 0 ? y : y > h ? h : 0;
|
||||
// 计算饱和度和亮度
|
||||
saturation.value = Math.floor((x / w) * 100 + 0.5) / 100;
|
||||
value.value = Math.floor((1 - y / h) * 100 + 0.5) / 100;
|
||||
// hsv转化为rgb
|
||||
let { r, g, b } = hsv2rgb(hue.value, saturation.value, value.value);
|
||||
red.value = r;
|
||||
green.value = g;
|
||||
blue.value = b;
|
||||
// 移动背景板圆圈
|
||||
pointStyle.value = `top: ${y}px;left: ${x}px;`;
|
||||
}
|
||||
|
||||
function mousedownSV(e: any) {
|
||||
// 鼠标按下计算饱和度和亮度并添加事件
|
||||
handleChangeSV(e);
|
||||
// 添加整个页面的鼠标事件
|
||||
window.addEventListener("mousemove", handleChangeSV);
|
||||
window.addEventListener("mouseup", mouseupSV);
|
||||
}
|
||||
|
||||
function mouseupSV(e: any) {
|
||||
// 鼠标松开后移除事件
|
||||
window.removeEventListener("mousemove", handleChangeSV);
|
||||
window.removeEventListener("mouseup", mouseupSV);
|
||||
}
|
||||
|
||||
// 色调
|
||||
function handleChangeHue(e: any) {
|
||||
// @ts-ignore
|
||||
let w = hueSlider.value.clientWidth;
|
||||
// @ts-ignore
|
||||
let x = e.pageX - saturationValue.value.getBoundingClientRect().left;
|
||||
x = x < w && x > 0 ? x : x > w ? w : 0;
|
||||
// 计算色调
|
||||
hue.value = Math.floor((x / w) * 360 + 0.5);
|
||||
// hsv转化为rgb
|
||||
let { r, g, b } = hsv2rgb(hue.value, saturation.value, value.value);
|
||||
red.value = r;
|
||||
green.value = g;
|
||||
blue.value = b;
|
||||
// 移动滑块
|
||||
hueSliderStyle.value = `left: ${x >= w - 6 ? w - 6 : x}px;`;
|
||||
}
|
||||
|
||||
function mousedownHue(e: any) {
|
||||
handleChangeHue(e);
|
||||
window.addEventListener("mousemove", handleChangeHue);
|
||||
window.addEventListener("mouseup", mouseupHue);
|
||||
}
|
||||
|
||||
function mouseupHue(e: any) {
|
||||
window.removeEventListener("mousemove", handleChangeHue);
|
||||
window.removeEventListener("mouseup", mouseupHue);
|
||||
}
|
||||
|
||||
// 透明度
|
||||
function handleChangeAlpha(e: any) {
|
||||
// @ts-ignore
|
||||
let w = alphaSlider.value.clientWidth;
|
||||
// @ts-ignore
|
||||
let x = e.pageX - saturationValue.value.getBoundingClientRect().left;
|
||||
x = x < w && x > 0 ? x : x > w ? w : 0;
|
||||
// 计算透明度
|
||||
alpha.value = Math.floor((x / w) * 100 + 0.5) / 100;
|
||||
// 移动滑块
|
||||
alphaSliderStyle.value = `left: ${x >= w - 6 ? w - 6 : x}px;`;
|
||||
}
|
||||
|
||||
function mousedownAlpha(e: any) {
|
||||
handleChangeAlpha(e);
|
||||
window.addEventListener("mousemove", handleChangeAlpha);
|
||||
window.addEventListener("mouseup", mouseupAlpha);
|
||||
}
|
||||
|
||||
function mouseupAlpha(e: any) {
|
||||
window.removeEventListener("mousemove", handleChangeAlpha);
|
||||
window.removeEventListener("mouseup", mouseupAlpha);
|
||||
}
|
||||
|
||||
function parseColor(color: any) {
|
||||
if (color) {
|
||||
let r, g, b, a;
|
||||
if (typeof color === "string") {
|
||||
if (
|
||||
/^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{8}|[0-9a-fA-F]{3}|[0-9a-fA-F]{4})$/.test(
|
||||
color
|
||||
)
|
||||
) {
|
||||
return hex2rgba(color);
|
||||
}
|
||||
} else {
|
||||
r = color.r > 255 ? 255 : color.r < 0 ? 0 : color.r;
|
||||
g = color.g > 255 ? 255 : color.g < 0 ? 0 : color.g;
|
||||
b = color.b > 255 ? 255 : color.b < 0 ? 0 : color.b;
|
||||
a = color.a > 1 ? 1 : color.a < 0 ? 0 : color.a;
|
||||
return { r, g, b, a };
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function hsv2rgb(h: any, s: any, v: any) {
|
||||
h === 360 && (h = 0);
|
||||
let i = Math.floor(h / 60) % 6;
|
||||
let f = h / 60 - i;
|
||||
let p = v * (1 - s);
|
||||
let q = v * (1 - s * f);
|
||||
let t = v * (1 - s * (1 - f));
|
||||
let r, g, b;
|
||||
if (i === 0) {
|
||||
r = v;
|
||||
g = t;
|
||||
b = p;
|
||||
} else if (i === 1) {
|
||||
r = q;
|
||||
g = v;
|
||||
b = p;
|
||||
} else if (i === 2) {
|
||||
r = p;
|
||||
g = v;
|
||||
b = t;
|
||||
} else if (i === 3) {
|
||||
r = p;
|
||||
g = q;
|
||||
b = v;
|
||||
} else if (i === 4) {
|
||||
r = t;
|
||||
g = p;
|
||||
b = v;
|
||||
} else if (i === 5) {
|
||||
r = v;
|
||||
g = p;
|
||||
b = q;
|
||||
}
|
||||
r = Math.floor(r * 255 + 0.5);
|
||||
g = Math.floor(g * 255 + 0.5);
|
||||
b = Math.floor(b * 255 + 0.5);
|
||||
return { r, g, b };
|
||||
}
|
||||
|
||||
function rgb2hsv(r: any, g: any, b: any) {
|
||||
let r1 = r / 255;
|
||||
let g1 = g / 255;
|
||||
let b1 = b / 255;
|
||||
let cmax = Math.max(r1, g1, b1);
|
||||
let cmin = Math.min(r1, g1, b1);
|
||||
let d = cmax - cmin;
|
||||
let h, s, v;
|
||||
if (d === 0) {
|
||||
h = 0;
|
||||
} else if (cmax === r1) {
|
||||
h = ((60 * (g1 - b1)) / d + 360) % 360;
|
||||
} else if (cmax === g1) {
|
||||
h = 60 * ((b1 - r1) / d + 2);
|
||||
} else if (cmax === b1) {
|
||||
h = 60 * ((r1 - g1) / d + 4);
|
||||
}
|
||||
if (cmax === 0) {
|
||||
s = 0;
|
||||
} else {
|
||||
s = d / cmax;
|
||||
}
|
||||
v = cmax;
|
||||
// @ts-ignore
|
||||
h = Math.floor(h + 0.5);
|
||||
s = Math.floor(s * 100 + 0.5) / 100;
|
||||
v = Math.floor(v * 100 + 0.5) / 100;
|
||||
return { h, s, v };
|
||||
}
|
||||
|
||||
function rgba2hex(r: any, g: any, b: any, a = 1) {
|
||||
r = parseInt(r);
|
||||
let r1 = r.toString(16).length !== 2 ? "0" + r.toString(16) : r.toString(16);
|
||||
g = parseInt(g);
|
||||
let g1 = g.toString(16).length !== 2 ? "0" + g.toString(16) : g.toString(16);
|
||||
b = parseInt(b);
|
||||
let b1 = b.toString(16).length !== 2 ? "0" + b.toString(16) : b.toString(16);
|
||||
// @ts-ignore
|
||||
a = parseFloat(a);
|
||||
let a1 = "";
|
||||
if (a !== 1) {
|
||||
let temp = Math.floor(256 * a);
|
||||
a1 =
|
||||
temp.toString(16).length !== 2
|
||||
? "0" + temp.toString(16)
|
||||
: temp.toString(16);
|
||||
}
|
||||
return `#${r1}${g1}${b1}${a1}`.toUpperCase();
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
function hex2rgba(s: any) {
|
||||
if (/^#?[0-9a-fA-F]{3}$/.test(s)) {
|
||||
let b = s.substring(s.length - 1, s.length);
|
||||
let g = s.substring(s.length - 2, s.length - 1);
|
||||
let r = s.substring(s.length - 3, s.length - 2);
|
||||
return hex2rgba(`${r + r}${g + g}${b + b}`);
|
||||
}
|
||||
if (/^#?[0-9a-fA-F]{4}$/.test(s)) {
|
||||
let a = s.substring(s.length - 1, s.length);
|
||||
let b = s.substring(s.length - 2, s.length - 1);
|
||||
let g = s.substring(s.length - 3, s.length - 2);
|
||||
let r = s.substring(s.length - 4, s.length - 3);
|
||||
return hex2rgba(`${r + r}${g + g}${b + b}${a + a}`);
|
||||
}
|
||||
if (/^#?[0-9a-fA-F]{6}$/.test(s)) {
|
||||
let b = parseInt("0x" + s.substring(s.length - 2, s.length));
|
||||
let g = parseInt("0x" + s.substring(s.length - 4, s.length - 2));
|
||||
let r = parseInt("0x" + s.substring(s.length - 6, s.length - 4));
|
||||
return { r, g, b, a: 1 };
|
||||
}
|
||||
if (/^#?[0-9a-fA-F]{8}$/.test(s)) {
|
||||
let a = parseInt("0x" + s.substring(s.length - 2, s.length));
|
||||
a = a / 255;
|
||||
let b = parseInt("0x" + s.substring(s.length - 4, s.length - 2));
|
||||
let g = parseInt("0x" + s.substring(s.length - 6, s.length - 4));
|
||||
let r = parseInt("0x" + s.substring(s.length - 8, s.length - 6));
|
||||
return { r, g, b, a };
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<lay-dropdown
|
||||
:disabled="disabled"
|
||||
:contentClass="contentClass"
|
||||
:contentStyle="contentStyle"
|
||||
updateAtScroll
|
||||
>
|
||||
<div
|
||||
class="layui-unselect layui-colorpicker"
|
||||
:class="[{ 'layui-colorpicker-disabled': disabled }]"
|
||||
>
|
||||
<span>
|
||||
<span
|
||||
class="layui-colorpicker-trigger-span"
|
||||
lay-type=""
|
||||
:style="`background-color: ${colorObj.rgba}`"
|
||||
>
|
||||
<i class="layui-icon layui-colorpicker-trigger-i layui-icon-down"></i>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<template #content>
|
||||
<div class="layui-color-picker">
|
||||
<div
|
||||
class="saturation-value"
|
||||
ref="saturationValue"
|
||||
@mousedown="mousedownSV"
|
||||
>
|
||||
<div :style="`background-color: hsl(${hue}, 100%, 50%);`">
|
||||
<div class="point" :style="pointStyle"></div>
|
||||
</div>
|
||||
<div class="saturation-value-2"></div>
|
||||
<div class="saturation-value-3"></div>
|
||||
</div>
|
||||
<div class="layui-color-picker-middle">
|
||||
<div style="flex: auto">
|
||||
<div class="hue-slider" ref="hueSlider" @mousedown="mousedownHue">
|
||||
<div class="slider" :style="hueSliderStyle"></div>
|
||||
</div>
|
||||
<div
|
||||
class="alpha-slider"
|
||||
ref="alphaSlider"
|
||||
@mousedown="mousedownAlpha"
|
||||
>
|
||||
<div class="slider" :style="alphaSliderStyle"></div>
|
||||
<div
|
||||
:style="`background: linear-gradient(to right, rgba(0,0,0,0), ${colorObj.rgb});width: 100%;height: 100%`"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="eyeDropper"
|
||||
@click="openEyeDropper"
|
||||
style="margin-left: 5px"
|
||||
>
|
||||
<EyeDropper />
|
||||
</div>
|
||||
<div class="color-diamond">
|
||||
<div
|
||||
:style="`background-color: ${colorObj.rgba};width: 100%;height: 100%;box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .15), inset 0 0 4px rgba(0, 0, 0, .25);`"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="color-value">
|
||||
<div class="hex">
|
||||
<label>
|
||||
<input
|
||||
:value="colorObj.hex8"
|
||||
@input="hexChange"
|
||||
spellcheck="false"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div class="rgba-r">
|
||||
<label>
|
||||
<input :value="red" @input="redChange" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="rgba-g">
|
||||
<label>
|
||||
<input :value="green" @input="greenChange" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="rgba-b">
|
||||
<label>
|
||||
<input :value="blue" @input="blueChange" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="rgba-a">
|
||||
<label>
|
||||
<input :value="alpha" @input="alphaChange" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="preset">
|
||||
<li
|
||||
v-for="item in preset"
|
||||
:key="item"
|
||||
:style="`background-color: ${item}`"
|
||||
@click="presetChange(item)"
|
||||
></li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
</lay-dropdown>
|
||||
</template>
|
||||
Reference in New Issue
Block a user