颜色选择器将选项式改组合式并改用TS
This commit is contained in:
parent
f0200ac849
commit
2f8bbb6ca2
@ -1,3 +1,391 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, watch, nextTick, getCurrentInstance } from 'vue';
|
||||
|
||||
// 类型定义
|
||||
interface RGBAColor {
|
||||
r: number;
|
||||
g: number;
|
||||
b: number;
|
||||
a: number;
|
||||
}
|
||||
|
||||
interface HSBColor {
|
||||
h: number;
|
||||
s: number;
|
||||
b: number;
|
||||
}
|
||||
|
||||
interface SitePosition {
|
||||
top: number;
|
||||
left: number;
|
||||
}
|
||||
|
||||
interface ElementPosition {
|
||||
top: number;
|
||||
left: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'confirm', data: { rgba: RGBAColor; hex: string }): void;
|
||||
}>();
|
||||
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
const props = defineProps({
|
||||
color: {
|
||||
type: Object as () => RGBAColor,
|
||||
default() {
|
||||
return { r: 0, g: 0, b: 0, a: 0 }
|
||||
}
|
||||
},
|
||||
spareColor: {
|
||||
type: Array as () => RGBAColor[],
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 响应式数据
|
||||
const show = ref<boolean>(false);
|
||||
const active = ref<boolean>(false);
|
||||
const rgba = reactive<RGBAColor>({ r: 0, g: 0, b: 0, a: 1 });
|
||||
const hsb = reactive<HSBColor>({ h: 0, s: 0, b: 0 });
|
||||
const site = reactive<SitePosition[]>([{ top: 0, left: 0 }, { left: 0, top: 0 }, { left: 0, top: 0 }]);
|
||||
const index = ref<number>(0);
|
||||
const bgcolor = reactive<RGBAColor>({ r: 255, g: 0, b: 0, a: 1 });
|
||||
const hex = ref<string>('#000000');
|
||||
const mode = ref<boolean>(true);
|
||||
const position = ref<ElementPosition[] | null>(null);
|
||||
const colorList = ref<RGBAColor[]>([
|
||||
{ r: 244, g: 67, b: 54, a: 1 },
|
||||
{ r: 233, g: 30, b: 99, a: 1 },
|
||||
{ r: 156, g: 39, b: 176, a: 1 },
|
||||
{ r: 103, g: 58, b: 183, a: 1 },
|
||||
{ r: 63, g: 81, b: 181, a: 1 },
|
||||
{ r: 33, g: 150, b: 243, a: 1 },
|
||||
{ r: 3, g: 169, b: 244, a: 1 },
|
||||
{ r: 0, g: 188, b: 212, a: 1 },
|
||||
{ r: 0, g: 150, b: 136, a: 1 },
|
||||
{ r: 76, g: 175, b: 80, a: 1 },
|
||||
{ r: 139, g: 195, b: 74, a: 1 },
|
||||
{ r: 205, g: 220, b: 57, a: 1 },
|
||||
{ r: 255, g: 235, b: 59, a: 1 },
|
||||
{ r: 255, g: 193, b: 7, a: 1 },
|
||||
{ r: 255, g: 152, b: 0, a: 1 },
|
||||
{ r: 255, g: 87, b: 34, a: 1 },
|
||||
{ r: 121, g: 85, b: 72, a: 1 },
|
||||
{ r: 158, g: 158, b: 158, a: 1 },
|
||||
{ r: 0, g: 0, b: 0, a: 0.5 },
|
||||
{ r: 0, g: 0, b: 0, a: 0 },
|
||||
]);
|
||||
|
||||
// 初始化(替代 created 钩子)
|
||||
Object.assign(rgba, props.color);
|
||||
if (props.spareColor.length !== 0) {
|
||||
colorList.value = props.spareColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
const init = (): void => {
|
||||
// hsb 颜色
|
||||
Object.assign(hsb, rgbToHsb(rgba));
|
||||
setValue(rgba);
|
||||
};
|
||||
|
||||
const moveHandle = (): void => { };
|
||||
|
||||
const open = (): void => {
|
||||
show.value = true;
|
||||
nextTick(() => {
|
||||
init();
|
||||
setTimeout(() => {
|
||||
active.value = true;
|
||||
setTimeout(() => {
|
||||
getSelectorQuery();
|
||||
}, 350)
|
||||
}, 50)
|
||||
})
|
||||
};
|
||||
|
||||
const close = (): void => {
|
||||
active.value = false;
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
show.value = false;
|
||||
}, 500)
|
||||
})
|
||||
};
|
||||
|
||||
const confirm = (): void => {
|
||||
close();
|
||||
emit('confirm', {
|
||||
rgba: rgba,
|
||||
hex: hex.value
|
||||
})
|
||||
};
|
||||
|
||||
// 选择模式
|
||||
const select = (): void => {
|
||||
mode.value = !mode.value
|
||||
};
|
||||
|
||||
// 常用颜色选择
|
||||
const selectColor = (item: RGBAColor): void => {
|
||||
setColorBySelect(item)
|
||||
};
|
||||
|
||||
const touchstart = (e: TouchEvent, idx: number): void => {
|
||||
const { pageX, pageY, clientX, clientY } = e.touches[0];
|
||||
setPosition(clientX, clientY, idx);
|
||||
};
|
||||
|
||||
const touchmove = (e: TouchEvent, idx: number): void => {
|
||||
const { pageX, pageY, clientX, clientY } = e.touches[0];
|
||||
setPosition(clientX, clientY, idx);
|
||||
};
|
||||
|
||||
const touchend = (e: TouchEvent, idx: number): void => {
|
||||
// 原代码为空实现
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置位置
|
||||
*/
|
||||
const setPosition = (x: number, y: number, idx: number): void => {
|
||||
index.value = idx;
|
||||
if (!position.value || !position.value[idx]) return;
|
||||
|
||||
const {
|
||||
top,
|
||||
left,
|
||||
width,
|
||||
height
|
||||
} = position.value[idx];
|
||||
// 设置最大最小值
|
||||
|
||||
site[idx].left = Math.max(0, Math.min(parseInt(String(x - left)), width));
|
||||
if (idx === 0) {
|
||||
site[idx].top = Math.max(0, Math.min(parseInt(String(y - top)), height));
|
||||
// 设置颜色
|
||||
hsb.s = parseInt(String((100 * site[idx].left) / width));
|
||||
hsb.b = parseInt(String(100 - (100 * (site[idx].top as number)) / height));
|
||||
setColor();
|
||||
setValue(rgba);
|
||||
} else {
|
||||
setControl(idx, site[idx].left);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置 rgb 颜色
|
||||
*/
|
||||
const setColor = (): void => {
|
||||
const rgb = HSBToRGB(hsb);
|
||||
rgba.r = rgb.r;
|
||||
rgba.g = rgb.g;
|
||||
rgba.b = rgb.b;
|
||||
};
|
||||
|
||||
/**
|
||||
* 设置二进制颜色
|
||||
* @param {RGBAColor} rgb
|
||||
*/
|
||||
const setValue = (rgb: RGBAColor): void => {
|
||||
hex.value = '#' + rgbToHex(rgb);
|
||||
};
|
||||
|
||||
const setControl = (idx: number, x: number): void => {
|
||||
if (!position.value || !position.value[idx]) return;
|
||||
|
||||
const {
|
||||
width
|
||||
} = position.value[idx];
|
||||
|
||||
if (idx === 1) {
|
||||
hsb.h = parseInt(String((360 * x) / width));
|
||||
const newRgb = HSBToRGB({
|
||||
h: hsb.h,
|
||||
s: 100,
|
||||
b: 100
|
||||
});
|
||||
bgcolor.r = newRgb.r;
|
||||
bgcolor.g = newRgb.g;
|
||||
bgcolor.b = newRgb.b;
|
||||
setColor();
|
||||
} else {
|
||||
rgba.a = parseFloat((x / width).toFixed(1));
|
||||
}
|
||||
setValue(rgba);
|
||||
};
|
||||
|
||||
/**
|
||||
* rgb 转 二进制 hex
|
||||
* @param {RGBAColor} rgb
|
||||
* @returns {string} 十六进制颜色字符串(不含#)
|
||||
*/
|
||||
const rgbToHex = (rgb: RGBAColor): string => {
|
||||
let hex = [rgb.r.toString(16), rgb.g.toString(16), rgb.b.toString(16)];
|
||||
hex.map(function (str, i) {
|
||||
if (str.length == 1) {
|
||||
hex[i] = '0' + str;
|
||||
}
|
||||
});
|
||||
return hex.join('');
|
||||
};
|
||||
|
||||
const setColorBySelect = (getrgb: RGBAColor): void => {
|
||||
const {
|
||||
r,
|
||||
g,
|
||||
b,
|
||||
a
|
||||
} = getrgb;
|
||||
|
||||
rgba.r = r ? parseInt(String(r)) : 0;
|
||||
rgba.g = g ? parseInt(String(g)) : 0;
|
||||
rgba.b = b ? parseInt(String(b)) : 0;
|
||||
rgba.a = a ? a : 0;
|
||||
|
||||
Object.assign(hsb, rgbToHsb(rgba));
|
||||
changeViewByHsb();
|
||||
};
|
||||
|
||||
const changeViewByHsb = (): void => {
|
||||
if (!position.value || position.value.length < 3) return;
|
||||
|
||||
const [a, b, c] = position.value;
|
||||
site[0].left = parseInt(String(hsb.s * a.width / 100));
|
||||
site[0].top = parseInt(String((100 - hsb.b) * a.height / 100));
|
||||
setColor();
|
||||
setValue(rgba);
|
||||
|
||||
const newRgb = HSBToRGB({
|
||||
h: hsb.h,
|
||||
s: 100,
|
||||
b: 100
|
||||
});
|
||||
bgcolor.r = newRgb.r;
|
||||
bgcolor.g = newRgb.g;
|
||||
bgcolor.b = newRgb.b;
|
||||
|
||||
site[1].left = hsb.h / 360 * b.width;
|
||||
site[2].left = rgba.a * c.width;
|
||||
};
|
||||
|
||||
/**
|
||||
* hsb 转 rgb
|
||||
* @param {HSBColor} hsb 颜色模式 H(hues)表示色相,S(saturation)表示饱和度,B(brightness)表示亮度
|
||||
* @returns {RGBAColor} RGB颜色对象
|
||||
*/
|
||||
const HSBToRGB = (hsb: HSBColor): RGBAColor => {
|
||||
let rgb: { r: number; g: number; b: number } = { r: 0, g: 0, b: 0 };
|
||||
let h = Math.round(hsb.h);
|
||||
let s = Math.round((hsb.s * 255) / 100);
|
||||
let v = Math.round((hsb.b * 255) / 100);
|
||||
if (s == 0) {
|
||||
rgb.r = rgb.g = rgb.b = v;
|
||||
} else {
|
||||
let t1 = v;
|
||||
let t2 = ((255 - s) * v) / 255;
|
||||
let 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),
|
||||
a: 1
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* rgb转hsb
|
||||
* @param {RGBAColor} rgb RGB颜色对象
|
||||
* @returns {HSBColor} HSB颜色对象
|
||||
*/
|
||||
const rgbToHsb = (rgb: RGBAColor): HSBColor => {
|
||||
let hsb = {
|
||||
h: 0,
|
||||
s: 0,
|
||||
b: 0
|
||||
};
|
||||
let min = Math.min(rgb.r, rgb.g, rgb.b);
|
||||
let max = Math.max(rgb.r, rgb.g, rgb.b);
|
||||
let 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;
|
||||
hsb.h *= 60;
|
||||
if (hsb.h < 0) hsb.h = 0;
|
||||
hsb.s *= 100 / 255;
|
||||
hsb.b *= 100 / 255;
|
||||
return hsb;
|
||||
};
|
||||
|
||||
const getSelectorQuery = (): void => {
|
||||
const views = uni.createSelectorQuery().in(instance!.proxy);
|
||||
views.selectAll('.boxs')
|
||||
.boundingClientRect(data => {
|
||||
if (Array.isArray(data) ? data.length === 0 : !data) {
|
||||
setTimeout(() => getSelectorQuery(), 20)
|
||||
return
|
||||
}
|
||||
position.value = data as unknown as ElementPosition[];
|
||||
setColorBySelect(rgba);
|
||||
})
|
||||
.exec();
|
||||
};
|
||||
|
||||
// 监听 props
|
||||
watch(() => props.spareColor, (newVal) => {
|
||||
colorList.value = newVal;
|
||||
});
|
||||
|
||||
// 暴露组件方法供父组件调用
|
||||
defineExpose({
|
||||
open,
|
||||
close,
|
||||
confirm
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<view v-show="show" class="t-wrapper" @touchmove.stop.prevent="moveHandle">
|
||||
<view class="t-mask" :class="{ active: active }" @click.stop="close"></view>
|
||||
@ -11,23 +399,28 @@
|
||||
<view class="t-background boxs" @touchstart="touchstart($event, 0)" @touchmove="touchmove($event, 0)"
|
||||
@touchend="touchend($event, 0)">
|
||||
<view class="t-color-mask"></view>
|
||||
<view class="t-pointer" :style="{ top: site[0].top - 8 + 'px', left: site[0].left - 8 + 'px' }"></view>
|
||||
<view class="t-pointer" :style="{
|
||||
top: site[0].top - 8 + 'px',
|
||||
left: site[0].left - 8 + 'px'
|
||||
}">
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="t-control__box">
|
||||
<view class="t-control__color">
|
||||
<view class="t-control__color-content"
|
||||
:style="{ background: 'rgba(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ',' + rgba.a + ')' }"></view>
|
||||
:style="{ background: 'rgba(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ',' + rgba.a + ')' }">
|
||||
</view>
|
||||
</view>
|
||||
<view class="t-control-box__item">
|
||||
<view class="t-controller boxs" @touchstart="touchstart($event, 1)" @touchmove="touchmove($event, 1)"
|
||||
@touchend="touchend($event, 1)">
|
||||
<view class="t-controller boxs" @touchstart="touchstart($event, 1)"
|
||||
@touchmove="touchmove($event, 1)" @touchend="touchend($event, 1)">
|
||||
<view class="t-hue">
|
||||
<view class="t-circle" :style="{ left: site[1].left - 12 + 'px' }"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="t-controller boxs" @touchstart="touchstart($event, 2)" @touchmove="touchmove($event, 2)"
|
||||
@touchend="touchend($event, 2)">
|
||||
<view class="t-controller boxs" @touchstart="touchstart($event, 2)"
|
||||
@touchmove="touchmove($event, 2)" @touchend="touchend($event, 2)">
|
||||
<view class="t-transparency">
|
||||
<view class="t-circle" :style="{ left: site[2].left - 12 + 'px' }"></view>
|
||||
</view>
|
||||
@ -76,336 +469,6 @@
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
color: {
|
||||
type: Object,
|
||||
default() {
|
||||
return { r: 0, g: 0, b: 0, a: 0 }
|
||||
}
|
||||
},
|
||||
spareColor: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
active: false,
|
||||
// rgba 颜色
|
||||
rgba: { r: 0, g: 0, b: 0, a: 1 },
|
||||
// hsb 颜色
|
||||
hsb: { h: 0, s: 0, b: 0 },
|
||||
site: [{ top: 0, left: 0 }, { left: 0 }, { left: 0 }],
|
||||
index: 0,
|
||||
bgcolor: { r: 255, g: 0, b: 0, a: 1 },
|
||||
hex: '#000000',
|
||||
mode: true,
|
||||
colorList: [
|
||||
{ r: 244, g: 67, b: 54, a: 1 },
|
||||
{ r: 233, g: 30, b: 99, a: 1 },
|
||||
{ r: 156, g: 39, b: 176, a: 1 },
|
||||
{ r: 103, g: 58, b: 183, a: 1 },
|
||||
{ r: 63, g: 81, b: 181, a: 1 },
|
||||
{ r: 33, g: 150, b: 243, a: 1 },
|
||||
{ r: 3, g: 169, b: 244, a: 1 },
|
||||
{ r: 0, g: 188, b: 212, a: 1 },
|
||||
{ r: 0, g: 150, b: 136, a: 1 },
|
||||
{ r: 76, g: 175, b: 80, a: 1 },
|
||||
{ r: 139, g: 195, b: 74, a: 1 },
|
||||
{ r: 205, g: 220, b: 57, a: 1 },
|
||||
{ r: 255, g: 235, b: 59, a: 1 },
|
||||
{ r: 255, g: 193, b: 7, a: 1 },
|
||||
{ r: 255, g: 152, b: 0, a: 1 },
|
||||
{ r: 255, g: 87, b: 34, a: 1 },
|
||||
{ r: 121, g: 85, b: 72, a: 1 },
|
||||
{ r: 158, g: 158, b: 158, a: 1 },
|
||||
{ r: 0, g: 0, b: 0, a: 0.5 },
|
||||
{ r: 0, g: 0, b: 0, a: 0 },
|
||||
]
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.rgba = this.color;
|
||||
if (this.spareColor.length !== 0) {
|
||||
this.colorList = this.spareColor;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
init() {
|
||||
// hsb 颜色
|
||||
this.hsb = this.rgbToHex(this.rgba);
|
||||
this.setValue(this.rgba);
|
||||
},
|
||||
moveHandle() { },
|
||||
open() {
|
||||
this.show = true;
|
||||
this.$nextTick(() => {
|
||||
this.init();
|
||||
setTimeout(() => {
|
||||
this.active = true;
|
||||
setTimeout(() => {
|
||||
this.getSelectorQuery();
|
||||
}, 350)
|
||||
}, 50)
|
||||
})
|
||||
|
||||
},
|
||||
close() {
|
||||
this.active = false;
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.show = false;
|
||||
}, 500)
|
||||
})
|
||||
},
|
||||
confirm() {
|
||||
this.close();
|
||||
this.$emit('confirm', {
|
||||
rgba: this.rgba,
|
||||
hex: this.hex
|
||||
})
|
||||
},
|
||||
// 选择模式
|
||||
select() {
|
||||
this.mode = !this.mode
|
||||
},
|
||||
// 常用颜色选择
|
||||
selectColor(item) {
|
||||
this.setColorBySelect(item)
|
||||
},
|
||||
touchstart(e, index) {
|
||||
const { pageX, pageY, clientX, clientY } = e.touches[0];
|
||||
this.pageX = clientX;
|
||||
this.pageY = clientY;
|
||||
this.setPosition(this.pageX, this.pageY, index);
|
||||
},
|
||||
touchmove(e, index) {
|
||||
const { pageX, pageY, clientX, clientY } = e.touches[0];
|
||||
this.moveX = clientX;
|
||||
this.moveY = clientY;
|
||||
this.setPosition(this.moveX, this.moveY, index);
|
||||
},
|
||||
touchend(e, index) {
|
||||
},
|
||||
/**
|
||||
* 设置位置
|
||||
*/
|
||||
setPosition(x, y, index) {
|
||||
this.index = index;
|
||||
const {
|
||||
top,
|
||||
left,
|
||||
width,
|
||||
height
|
||||
} = this.position[index];
|
||||
// 设置最大最小值
|
||||
|
||||
this.site[index].left = Math.max(0, Math.min(parseInt(x - left), width));
|
||||
if (index === 0) {
|
||||
this.site[index].top = Math.max(0, Math.min(parseInt(y - top), height));
|
||||
// 设置颜色
|
||||
this.hsb.s = parseInt((100 * this.site[index].left) / width);
|
||||
this.hsb.b = parseInt(100 - (100 * this.site[index].top) / height);
|
||||
this.setColor();
|
||||
this.setValue(this.rgba);
|
||||
} else {
|
||||
this.setControl(index, this.site[index].left);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 设置 rgb 颜色
|
||||
*/
|
||||
setColor() {
|
||||
const rgb = this.HSBToRGB(this.hsb);
|
||||
this.rgba.r = rgb.r;
|
||||
this.rgba.g = rgb.g;
|
||||
this.rgba.b = rgb.b;
|
||||
},
|
||||
/**
|
||||
* 设置二进制颜色
|
||||
* @param {Object} rgb
|
||||
*/
|
||||
setValue(rgb) {
|
||||
this.hex = '#' + this.rgbToHex(rgb);
|
||||
},
|
||||
setControl(index, x) {
|
||||
const {
|
||||
top,
|
||||
left,
|
||||
width,
|
||||
height
|
||||
} = this.position[index];
|
||||
|
||||
if (index === 1) {
|
||||
this.hsb.h = parseInt((360 * x) / width);
|
||||
this.bgcolor = this.HSBToRGB({
|
||||
h: this.hsb.h,
|
||||
s: 100,
|
||||
b: 100
|
||||
});
|
||||
this.setColor()
|
||||
} else {
|
||||
this.rgba.a = (x / width).toFixed(1);
|
||||
}
|
||||
this.setValue(this.rgba);
|
||||
},
|
||||
/**
|
||||
* rgb 转 二进制 hex
|
||||
* @param {Object} rgb
|
||||
*/
|
||||
rgbToHex(rgb) {
|
||||
let hex = [rgb.r.toString(16), rgb.g.toString(16), rgb.b.toString(16)];
|
||||
hex.map(function (str, i) {
|
||||
if (str.length == 1) {
|
||||
hex[i] = '0' + str;
|
||||
}
|
||||
});
|
||||
return hex.join('');
|
||||
},
|
||||
setColorBySelect(getrgb) {
|
||||
const {
|
||||
r,
|
||||
g,
|
||||
b,
|
||||
a
|
||||
} = getrgb;
|
||||
let rgb = {}
|
||||
rgb = {
|
||||
r: r ? parseInt(r) : 0,
|
||||
g: g ? parseInt(g) : 0,
|
||||
b: b ? parseInt(b) : 0,
|
||||
a: a ? a : 0,
|
||||
};
|
||||
this.rgba = rgb;
|
||||
this.hsb = this.rgbToHsb(rgb);
|
||||
this.changeViewByHsb();
|
||||
},
|
||||
changeViewByHsb() {
|
||||
const [a, b, c] = this.position;
|
||||
this.site[0].left = parseInt(this.hsb.s * a.width / 100);
|
||||
this.site[0].top = parseInt((100 - this.hsb.b) * a.height / 100);
|
||||
this.setColor(this.hsb.h);
|
||||
this.setValue(this.rgba);
|
||||
this.bgcolor = this.HSBToRGB({
|
||||
h: this.hsb.h,
|
||||
s: 100,
|
||||
b: 100
|
||||
});
|
||||
|
||||
this.site[1].left = this.hsb.h / 360 * b.width;
|
||||
this.site[2].left = this.rgba.a * c.width;
|
||||
|
||||
},
|
||||
/**
|
||||
* hsb 转 rgb
|
||||
* @param {Object} 颜色模式 H(hues)表示色相,S(saturation)表示饱和度,B(brightness)表示亮度
|
||||
*/
|
||||
HSBToRGB(hsb) {
|
||||
let rgb = {};
|
||||
let h = Math.round(hsb.h);
|
||||
let s = Math.round((hsb.s * 255) / 100);
|
||||
let v = Math.round((hsb.b * 255) / 100);
|
||||
if (s == 0) {
|
||||
rgb.r = rgb.g = rgb.b = v;
|
||||
} else {
|
||||
let t1 = v;
|
||||
let t2 = ((255 - s) * v) / 255;
|
||||
let 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)
|
||||
};
|
||||
},
|
||||
rgbToHsb(rgb) {
|
||||
let hsb = {
|
||||
h: 0,
|
||||
s: 0,
|
||||
b: 0
|
||||
};
|
||||
let min = Math.min(rgb.r, rgb.g, rgb.b);
|
||||
let max = Math.max(rgb.r, rgb.g, rgb.b);
|
||||
let 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;
|
||||
hsb.h *= 60;
|
||||
if (hsb.h < 0) hsb.h = 0;
|
||||
hsb.s *= 100 / 255;
|
||||
hsb.b *= 100 / 255;
|
||||
return hsb;
|
||||
},
|
||||
getSelectorQuery() {
|
||||
const views = uni.createSelectorQuery().in(this);
|
||||
views
|
||||
.selectAll('.boxs')
|
||||
.boundingClientRect(data => {
|
||||
if (!data || data.length === 0) {
|
||||
setTimeout(() => this.getSelectorQuery(), 20)
|
||||
return
|
||||
}
|
||||
this.position = data;
|
||||
// this.site[0].top = data[0].height;
|
||||
// this.site[0].left = 0;
|
||||
// this.site[1].left = data[1].width;
|
||||
// this.site[2].left = data[2].width;
|
||||
this.setColorBySelect(this.rgba);
|
||||
})
|
||||
.exec();
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
spareColor(newVal) {
|
||||
this.colorList = newVal;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.t-wrapper {
|
||||
position: fixed;
|
||||
@ -477,6 +540,7 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// 避免使用 &__box 写法,改为完整类名
|
||||
.t-color__box {
|
||||
position: relative;
|
||||
height: 400upx;
|
||||
@ -488,15 +552,6 @@ export default {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.t-background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
|
||||
}
|
||||
|
||||
.t-color-mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@ -508,6 +563,15 @@ export default {
|
||||
background: linear-gradient(to top, #000, rgba(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
.t-background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
|
||||
}
|
||||
|
||||
.t-pointer {
|
||||
position: absolute;
|
||||
bottom: -8px;
|
||||
@ -524,6 +588,7 @@ export default {
|
||||
height: 50upx;
|
||||
}
|
||||
|
||||
// 避免使用嵌套方式,使用完整类名
|
||||
.t-control__box {
|
||||
margin-top: 50upx;
|
||||
width: 100%;
|
||||
@ -593,6 +658,7 @@ export default {
|
||||
box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
// 使用完整的类名而不是嵌套
|
||||
.t-result__box {
|
||||
margin-top: 20upx;
|
||||
padding: 10upx;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user