mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
258 lines
5.9 KiB
Vue
258 lines
5.9 KiB
Vue
<template>
|
|
<div class="color-picker" @contextmenu.prevent>
|
|
<div class="picker-saturation-wrap">
|
|
<Saturation :value="color" :hue="hue" @change="value => changeColor(value)" />
|
|
</div>
|
|
<div class="picker-controls">
|
|
<div class="picker-color-wrap">
|
|
<div class="picker-current-color" :style="{ background: currentColor }"></div>
|
|
<Checkboard />
|
|
</div>
|
|
<div class="picker-sliders">
|
|
<div class="picker-hue-wrap">
|
|
<Hue :value="color" :hue="hue" @change="value => changeColor(value)" />
|
|
</div>
|
|
<div class="picker-alpha-wrap">
|
|
<Alpha :value="color" @change="value => changeColor(value)" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="picker-field">
|
|
<EditableInput :value="color" @change="value => changeColor(value)" />
|
|
</div>
|
|
|
|
<div class="picker-presets">
|
|
<div
|
|
class="picker-presets-color"
|
|
v-for="c in themeColors"
|
|
:key="c"
|
|
:style="{background: c}"
|
|
@click="selectPresetColor(c)"
|
|
></div>
|
|
</div>
|
|
|
|
<div class="picker-gradient-presets">
|
|
<div
|
|
class="picker-gradient-col"
|
|
v-for="(col, index) in presetColors"
|
|
:key="index"
|
|
>
|
|
<div class="picker-gradient-color"
|
|
v-for="c in col"
|
|
:key="c"
|
|
:style="{background: c}"
|
|
@click="selectPresetColor(c)"
|
|
></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="picker-presets">
|
|
<div
|
|
v-for="c in standardColors"
|
|
:key="c"
|
|
class="picker-presets-color"
|
|
:style="{ background: c }"
|
|
@click="selectPresetColor(c)"
|
|
></div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { computed, defineComponent, ref } from 'vue'
|
|
import tinycolor, { ColorFormats } from 'tinycolor2'
|
|
|
|
import Alpha from './Alpha.vue'
|
|
import Checkboard from './Checkboard.vue'
|
|
import Hue from './Hue.vue'
|
|
import Saturation from './Saturation.vue'
|
|
import EditableInput from './EditableInput.vue'
|
|
|
|
const presetColorConfig = [
|
|
['#7f7f7f', '#f2f2f2'],
|
|
['#0d0d0d', '#808080'],
|
|
['#1c1a10', '#ddd8c3'],
|
|
['#0e243d', '#c6d9f0'],
|
|
['#233f5e', '#dae5f0'],
|
|
['#632623', '#f2dbdb'],
|
|
['#4d602c', '#eaf1de'],
|
|
['#3f3150', '#e6e0ec'],
|
|
['#1e5867', '#d9eef3'],
|
|
['#99490f', '#fee9da'],
|
|
]
|
|
|
|
const gradient = (startColor: string, endColor: string, step: number) => {
|
|
const _startColor = tinycolor(startColor).toRgb()
|
|
const _endColor = tinycolor(endColor).toRgb()
|
|
|
|
const rStep = (_endColor.r - _startColor.r) / step
|
|
const gStep = (_endColor.g - _startColor.g) / step
|
|
const bStep = (_endColor.b - _startColor.b) / step
|
|
const gradientColorArr = []
|
|
|
|
for(let i = 0; i < step; i++) {
|
|
const gradientColor = tinycolor({
|
|
r: _startColor.r + rStep * i,
|
|
g: _startColor.g + gStep * i,
|
|
b: _startColor.b + bStep * i,
|
|
}).toRgbString()
|
|
gradientColorArr.push(gradientColor)
|
|
}
|
|
return gradientColorArr
|
|
}
|
|
|
|
const getPresetColors = () => {
|
|
const presetColors = []
|
|
for(const color of presetColorConfig) {
|
|
presetColors.push(gradient(color[1], color[0], 5))
|
|
}
|
|
return presetColors
|
|
}
|
|
|
|
export default defineComponent({
|
|
name: 'color-picker',
|
|
components: {
|
|
Alpha,
|
|
Checkboard,
|
|
Hue,
|
|
Saturation,
|
|
EditableInput,
|
|
},
|
|
props: {
|
|
modelValue: {
|
|
type: String,
|
|
default: '#e86b99',
|
|
},
|
|
},
|
|
setup(props, { emit }) {
|
|
const hue = ref(0)
|
|
|
|
const color = computed({
|
|
get() {
|
|
return tinycolor(props.modelValue).toRgb()
|
|
},
|
|
set(rgba: ColorFormats.RGBA) {
|
|
const rgbaString = `rgba(${[rgba.r, rgba.g, rgba.b, rgba.a].join(',')})`
|
|
emit('update:modelValue', rgbaString)
|
|
},
|
|
})
|
|
|
|
const themeColors = ['#000000', '#ffffff', '#eeece1', '#1e497b', '#4e81bb', '#e2534d', '#9aba60', '#8165a0', '#47acc5', '#f9974c']
|
|
const standardColors = ['#c21401', '#ff1e02', '#ffc12a', '#ffff3a', '#90cf5b', '#00af57', '#00afee', '#0071be', '#00215f', '#72349d']
|
|
const presetColors = getPresetColors()
|
|
|
|
const currentColor = computed(() => {
|
|
return `rgba(${[color.value.r, color.value.g, color.value.b, color.value.a].join(',')})`
|
|
})
|
|
|
|
const selectPresetColor = (colorString: string) => {
|
|
emit('update:modelValue', colorString)
|
|
}
|
|
|
|
const changeColor = (value: ColorFormats.RGBA | ColorFormats.HSLA | ColorFormats.HSVA) => {
|
|
if('h' in value) {
|
|
hue.value = value.h
|
|
color.value = tinycolor(value).toRgb()
|
|
}
|
|
else color.value = value
|
|
}
|
|
|
|
return {
|
|
themeColors,
|
|
standardColors,
|
|
presetColors,
|
|
color,
|
|
hue,
|
|
currentColor,
|
|
changeColor,
|
|
selectPresetColor,
|
|
}
|
|
},
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.color-picker {
|
|
position: relative;
|
|
width: 240px;
|
|
background: #fff;
|
|
user-select: none;
|
|
margin-bottom: -10px;
|
|
}
|
|
.picker-saturation-wrap {
|
|
width: 100%;
|
|
padding-bottom: 50%;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
.picker-controls {
|
|
display: flex;
|
|
}
|
|
.picker-sliders {
|
|
padding: 4px 0;
|
|
flex: 1;
|
|
}
|
|
.picker-hue-wrap {
|
|
position: relative;
|
|
height: 10px;
|
|
}
|
|
.picker-alpha-wrap {
|
|
position: relative;
|
|
height: 10px;
|
|
margin-top: 4px;
|
|
overflow: hidden;
|
|
}
|
|
.picker-color-wrap {
|
|
width: 24px;
|
|
height: 24px;
|
|
position: relative;
|
|
margin-top: 4px;
|
|
margin-right: 4px;
|
|
|
|
.checkerboard {
|
|
background-size: auto;
|
|
}
|
|
}
|
|
.picker-current-color {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
z-index: 2;
|
|
}
|
|
|
|
.picker-field {
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.picker-presets {
|
|
@include grid-layout-wrapper();
|
|
}
|
|
.picker-presets-color {
|
|
@include grid-layout-item(10, 7%);
|
|
|
|
height: 0;
|
|
padding-bottom: 7%;
|
|
flex-shrink: 0;
|
|
position: relative;
|
|
cursor: pointer;
|
|
}
|
|
.picker-gradient-presets {
|
|
@include grid-layout-wrapper();
|
|
}
|
|
.picker-gradient-col {
|
|
@include grid-layout-item(10, 7%);
|
|
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
.picker-gradient-color {
|
|
width: 100%;
|
|
height: 0;
|
|
padding-bottom: 100%;
|
|
position: relative;
|
|
cursor: pointer;
|
|
}
|
|
</style> |