mirror of
https://github.com/palxiao/poster-design.git
synced 2025-07-03 03:56:41 +08:00
730 lines
20 KiB
Vue
730 lines
20 KiB
Vue
<!--
|
|
* @Author: ShawnPhang
|
|
* @Date: 2023-05-26 17:42:26
|
|
* @Description: 调色板
|
|
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
|
* @LastEditTime: 2024-01-31 10:44:41
|
|
-->
|
|
<template>
|
|
<div class="color-picker">
|
|
<Tabs v-if="modes.length > 1" :value="mode" @update:value="onChangeMode">
|
|
<TabPanel v-for="label in modes" :key="label" :label="label"> </TabPanel>
|
|
</Tabs>
|
|
<div v-else class="title">{{ mode }}</div>
|
|
|
|
<template v-if="showGradient">
|
|
<div v-show="mode === '渐变'" class="cp__gradient flex-center">
|
|
<div class="cp__gradient-bar">
|
|
<div ref="elGradientTrack" class="cpgb__track" style="width: 100%" :style="{ background: value }">
|
|
<!-- tabindex="-1" 是元素可以触发 keydown 事件 -->
|
|
<div
|
|
v-for="(gradient, index) in gradients"
|
|
:key="index"
|
|
:class="[
|
|
'cpgb__pointer',
|
|
{
|
|
'cpgb__pointer--active': gradient === activeGradient,
|
|
},
|
|
]"
|
|
:data-sort="index"
|
|
:style="{
|
|
left: `${gradient.offset * 100}%`,
|
|
background: gradient.color,
|
|
}"
|
|
tabindex="-1"
|
|
@mousedown="onMousedownGradientPointer(gradient)"
|
|
@keydown.stop="onKeyupGradientPointer"
|
|
></div>
|
|
</div>
|
|
</div>
|
|
<AngleHandleVue v-model="angle" @change="angleChange" />
|
|
</div>
|
|
</template>
|
|
|
|
<div ref="elPalette" class="cp__palette" :style="{ background: paletteBackground }">
|
|
<div class="cpp__color-saturation"></div>
|
|
<div class="cpp__color-value"></div>
|
|
<div ref="elPalettePointer" class="cpp__pointer"></div>
|
|
</div>
|
|
|
|
<div ref="elSliderHux" class="cp__slider cp__slider-hux">
|
|
<div class="cps__track">
|
|
<div ref="elSliderHuxPointer" class="cpst__pointer"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div ref="elSliderAlpha" class="cp__slider cp__slider-alpha">
|
|
<div class="cpsa__background" :style="sliderAlphaBackgroundStyle"></div>
|
|
<div class="cps__track">
|
|
<div ref="elSliderAlphaPointer" class="cpst__pointer"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="cp__box">
|
|
<div class="item" @click="onClickStraw">
|
|
<xiguan v-if="hasEyeDrop" />
|
|
<input v-else class="native" type="color" @input="onClickStraw" />
|
|
</div>
|
|
<!-- <input :value="value" @input="$emit('update:value', $event.target.value)" class="input" /> -->
|
|
<input v-if="mode === '渐变'" class="input" :value="activeGradient.color" />
|
|
<input v-else :value="value" class="input" @blur="onInputBlur" />
|
|
<template v-if="mode === '纯色'">
|
|
<div v-for="pc in predefine" :key="pc" class="item item-color" :style="{ background: pc }" @click="onClickStraw({ target: { value: pc } })"></div>
|
|
</template>
|
|
<!-- <input :value="alpha" class="w-12" size="small" :min="0" :max="100" @input="onChangeAlpha" @change="onChangeAlpha" /> -->
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import './index.css'
|
|
export default {
|
|
name: 'ColorPicker',
|
|
inheritAttrs: false,
|
|
}
|
|
</script>
|
|
|
|
<script setup>
|
|
import { ref, reactive, computed, watch, onMounted, nextTick, onBeforeUnmount } from 'vue'
|
|
import { registerMoveableElement } from './utils/moveable.ts'
|
|
import { hexA2HSLA, HSLA2HexA, hex2RGB, RGB2HSL, hexA2RGBA, RGBA2HexA } from './utils/color.ts'
|
|
import { toGradientString, parseBackgroundValue, toolTip } from './utils/helper.ts'
|
|
import Tabs from './comps/Tabs.vue'
|
|
import xiguan from './comps/svg.vue'
|
|
import TabPanel from './comps/TabPanel.vue'
|
|
import { debounce } from 'throttle-debounce'
|
|
import AngleHandleVue from './comps/AngleHandle.vue'
|
|
|
|
const props = defineProps({
|
|
value: {
|
|
type: String,
|
|
default: '#ffffffff',
|
|
},
|
|
|
|
modes: {
|
|
type: Array,
|
|
default: () => ['纯色', '渐变'], // 图案
|
|
},
|
|
|
|
defaultColor: {
|
|
type: String,
|
|
default: '#ffffffff',
|
|
},
|
|
|
|
defaultGradient: {
|
|
type: String,
|
|
default: 'linear-gradient(90deg, #fffae0ff 0%, #ffd1f1ff 100%)',
|
|
},
|
|
|
|
defaultImage: {
|
|
type: String,
|
|
default: 'https://st0.dancf.com/csc/157/material-2d-textures/0/20190714-174653-ed3c.jpg',
|
|
},
|
|
})
|
|
|
|
const emit = defineEmits(['update:value', 'change', 'native-pick', 'blur'])
|
|
|
|
const mode = ref(parseBackgroundValue(props.value)) // 颜色、渐变、图片
|
|
const angle = ref(90)
|
|
const gradients = ref([])
|
|
const hsla = reactive({ h: 0, s: 0, l: 0, a: 0 })
|
|
const paletteBackground = ref('#f00')
|
|
const hex = ref('#000')
|
|
const alpha = ref(0)
|
|
let activeGradient = ref({})
|
|
const hasEyeDrop = 'EyeDropper' in window
|
|
|
|
const elGradientTrack = ref()
|
|
const elPalette = ref()
|
|
const elPalettePointer = ref()
|
|
const elSliderHuxPointer = ref()
|
|
const elSliderHux = ref()
|
|
const elSliderAlphaPointer = ref()
|
|
const elSliderAlpha = ref()
|
|
// const elStrawCanvas = ref();
|
|
|
|
let gradientMoveable = null
|
|
let paletteMoveable = null
|
|
let sliderHuxMoveable = null
|
|
let sliderAlphaMoveable = null
|
|
let mousedownGradientPointer = null
|
|
let backendHex = null
|
|
// 是否可以改变 palette sliderHux sliderAlpha 的 pointer 位置
|
|
let canChangeHSLAPointerPos = true
|
|
let canChangeHSLAPointerPosTimer = null
|
|
|
|
const predefine = ref([]) // 历史记录
|
|
|
|
const record = {
|
|
color: props.defaultColor,
|
|
gradient: props.defaultGradient,
|
|
image: props.defaultImage,
|
|
}
|
|
|
|
const showGradient = computed(() => {
|
|
return props.modes.includes('渐变')
|
|
})
|
|
|
|
const sliderAlphaBackgroundStyle = computed(() => {
|
|
const rgb = hex2RGB(hex.value).join(',')
|
|
return {
|
|
background: `linear-gradient(to right, rgba(${rgb}, 0) 0%, rgb(${rgb}) 100%)`,
|
|
}
|
|
})
|
|
|
|
watch(activeGradient, (value) => {
|
|
setColor(value.color)
|
|
})
|
|
|
|
watch(hex, (value) => {
|
|
onChangeHex(value)
|
|
})
|
|
|
|
watch(
|
|
() => props.value,
|
|
(value) => {
|
|
const _mode = parseBackgroundValue(value)
|
|
if (_mode !== mode.value) {
|
|
mode.value = _mode
|
|
}
|
|
changeMode(_mode)
|
|
recordValue(value)
|
|
addHistory(value)
|
|
},
|
|
)
|
|
|
|
// TODO: 添加选择历史记录
|
|
const addHistory = debounce(300, async (value) => {
|
|
const history = predefine.value
|
|
// 如果已经存在就提到前面来,避免重复
|
|
const index = history.indexOf(value)
|
|
if (index !== -1) {
|
|
predefine.value.splice(index, 1)
|
|
}
|
|
if (history.length >= 4) {
|
|
predefine.value.splice(history.length - 1, 1)
|
|
}
|
|
// 把最新的颜色放在头部
|
|
const head = [value]
|
|
predefine.value = head.concat(history)
|
|
})
|
|
|
|
const unwatchHSLA = watch(hsla, onChangeHSLA, { deep: true })
|
|
function onChangeHSLA(newHsla) {
|
|
const hexA = HSLA2HexA(...Object.values(newHsla))
|
|
|
|
let value
|
|
if (mode.value === '纯色') {
|
|
value = hexA
|
|
} else if (mode.value === '渐变') {
|
|
activeGradient.value.color = hexA
|
|
value = toGradientString(angle.value, gradients.value)
|
|
}
|
|
updateColorData(hexA)
|
|
updateValue(value)
|
|
}
|
|
|
|
onMounted(onMountedCallback)
|
|
async function onMountedCallback() {
|
|
elPalettePointer.value.style.left = `${hsla.s}%`
|
|
elPalettePointer.value.style.top = `${100 - hsla.l}%`
|
|
elSliderHuxPointer.value.style.left = `${(hsla.h / 360) * 100}%`
|
|
elSliderAlphaPointer.value.style.left = `${hsla.a * 100}%`
|
|
|
|
if (showGradient.value) {
|
|
gradientMoveable = registerMoveableElement(elGradientTrack.value, {
|
|
onmousedown: onMousedownGradient,
|
|
onmousemove: onMousemoveGradient,
|
|
onmouseup: onMouseupGradient,
|
|
})
|
|
}
|
|
|
|
function onMousedownGradient(position) {
|
|
if (mousedownGradientPointer) {
|
|
return
|
|
}
|
|
|
|
const index = gradients.value.findIndex((stop) => stop.offset >= position.x)
|
|
const start = gradients.value[index - 1]
|
|
const startRGBA = hexA2RGBA(start.color)
|
|
const end = gradients.value[index]
|
|
const endRGBA = hexA2RGBA(end.color)
|
|
|
|
const rgb = []
|
|
for (let i = 0; i < 3; i += 1) {
|
|
rgb.push(startRGBA[i] + (endRGBA[i] - startRGBA[i]) * position.x)
|
|
}
|
|
|
|
const a = end.offset - position.x - (position.x - start.offset) > 0 ? startRGBA[3] : endRGBA[3]
|
|
|
|
const color = RGBA2HexA(...rgb, a)
|
|
activeGradient.value = {
|
|
color,
|
|
offset: position.x,
|
|
}
|
|
|
|
gradients.value.splice(index, 0, activeGradient.value)
|
|
}
|
|
|
|
function onMousemoveGradient(position) {
|
|
if (!mousedownGradientPointer) return
|
|
|
|
activeGradient.value.offset = position.x
|
|
gradients.value.sort((a, b) => a.offset - b.offset)
|
|
|
|
const value = toGradientString(angle.value, gradients.value)
|
|
updateValue(value)
|
|
}
|
|
|
|
function onMouseupGradient() {
|
|
mousedownGradientPointer = false
|
|
}
|
|
|
|
paletteMoveable = registerMoveableElement(elPalette.value, {
|
|
onmousemove: onChangeSL,
|
|
onmouseup: onChangeSL,
|
|
})
|
|
|
|
function onChangeSL(position) {
|
|
disableChangeHSLA()
|
|
|
|
const x = position.x * 100
|
|
const y = position.y * 100
|
|
|
|
hsla.s = Math.round(x)
|
|
hsla.l = Math.round(100 - y)
|
|
|
|
elPalettePointer.value.style.left = `${x}%`
|
|
elPalettePointer.value.style.top = `${y}%`
|
|
}
|
|
|
|
sliderHuxMoveable = registerMoveableElement(elSliderHux.value, {
|
|
onmousemove: onChangeHux,
|
|
onmouseup: onChangeHux,
|
|
})
|
|
|
|
function onChangeHux(position) {
|
|
disableChangeHSLA()
|
|
|
|
hsla.h = position.x * 360
|
|
elSliderHuxPointer.value.style.left = `${position.x * 100}%`
|
|
}
|
|
|
|
sliderAlphaMoveable = registerMoveableElement(elSliderAlpha.value, {
|
|
onmousemove: onChangeAlpha,
|
|
onmouseup: onChangeAlpha,
|
|
})
|
|
|
|
function onChangeAlpha(position) {
|
|
disableChangeHSLA()
|
|
|
|
hsla.a = position.x
|
|
elSliderAlphaPointer.value.style.left = `${position.x * 100}%`
|
|
}
|
|
|
|
changeMode(mode.value)
|
|
recordValue(props.value)
|
|
}
|
|
|
|
onBeforeUnmount(() => {
|
|
paletteMoveable?.destroy()
|
|
sliderHuxMoveable?.destroy()
|
|
sliderAlphaMoveable?.destroy()
|
|
unwatchHSLA()
|
|
|
|
if (gradientMoveable) {
|
|
gradientMoveable.destroy()
|
|
}
|
|
})
|
|
|
|
function recordValue(value) {
|
|
if (mode.value === '纯色') {
|
|
record.color = value
|
|
} else if (mode.value === '渐变') {
|
|
record.gradient = value
|
|
} else if (mode.value === '图案') {
|
|
record.image = value
|
|
}
|
|
}
|
|
|
|
function updateValue(value) {
|
|
if (value === props.value) return
|
|
|
|
recordValue(value)
|
|
emit('update:value', value)
|
|
|
|
emit('change', {
|
|
mode: mode.value,
|
|
color: value,
|
|
angle: Number(angle.value),
|
|
stops: gradients.value,
|
|
})
|
|
}
|
|
|
|
async function onChangeMode(value) {
|
|
if (value === mode.value) return
|
|
mode.value = value
|
|
|
|
let color
|
|
if (value === '纯色') {
|
|
color = record.color
|
|
} else if (value === '渐变') {
|
|
color = record.gradient
|
|
} else if (value === '图案') {
|
|
color = record.image
|
|
}
|
|
updateValue(color)
|
|
}
|
|
|
|
function changeMode(mode) {
|
|
if (mode === '纯色') {
|
|
setColor(props.value)
|
|
} else if (mode === '渐变') {
|
|
if (gradients.value.length === 0) {
|
|
props.value.match(/[^,]+/g).forEach((item, index) => {
|
|
if (index === 0) {
|
|
angle.value = Number(item.match(/\d+/)[0])
|
|
return
|
|
}
|
|
|
|
let [color, offset] = item.trim().split(' ')
|
|
if (!color.startsWith('#')) color = RGBA2HexA(color)
|
|
|
|
offset = offset.match(/\d+/)[0] / 100
|
|
gradients.value.push({ color, offset })
|
|
activeGradient.value = gradients.value[0]
|
|
})
|
|
} else {
|
|
setColor(activeGradient.value.color)
|
|
}
|
|
}
|
|
|
|
// TODO: 图案
|
|
}
|
|
|
|
function updateColorData(hexA) {
|
|
paletteBackground.value = `hsl(${hsla.h}, 100%, 50%)`
|
|
hex.value = hexA.slice(0, 7)
|
|
backendHex = hex.value
|
|
alpha.value = Math.round((hsla.a ?? 1) * 100)
|
|
}
|
|
|
|
function setColor(color) {
|
|
// 通过 palette sliderHux sliderAlpha 交互改变 pointer 位置
|
|
// 已经改变 hsla 的值并触发 update:value
|
|
// watch props.value 再调用当前方法时无需再更新 hsla
|
|
if (canChangeHSLAPointerPos) {
|
|
const _hsla = hexA2HSLA(color)
|
|
hsla.h = _hsla[0]
|
|
hsla.s = _hsla[1]
|
|
hsla.l = _hsla[2]
|
|
hsla.a = _hsla[3]
|
|
|
|
updateColorData(color)
|
|
|
|
let x = hsla.s
|
|
const y = Math.round(100 - hsla.l)
|
|
elPalettePointer.value.style.left = `${x}%`
|
|
elPalettePointer.value.style.top = `${y}%`
|
|
|
|
x = hsla.h / 360
|
|
elSliderHuxPointer.value.style.left = `${x * 100}%`
|
|
|
|
elSliderAlphaPointer.value.style.left = `${hsla.a * 100}%`
|
|
}
|
|
}
|
|
|
|
function onMousedownGradientPointer(stop) {
|
|
mousedownGradientPointer = true
|
|
activeGradient.value = stop
|
|
}
|
|
|
|
function onKeyupGradientPointer(event) {
|
|
event.stopPropagation()
|
|
event.preventDefault()
|
|
if (!['Backspace', 'Delete'].includes(event.key)) return
|
|
if (gradients.value.length === 2) return
|
|
|
|
const index = gradients.value.indexOf(activeGradient.value)
|
|
gradients.value.splice(index, 1)
|
|
activeGradient.value = gradients.value[0]
|
|
}
|
|
|
|
function onChangeHex(value) {
|
|
if (/^#(?:[0-9a-f]{3}){1,2}$/i.test(value)) {
|
|
const rgb = hex2RGB(value)
|
|
const [h, s, l] = RGB2HSL(...rgb)
|
|
hsla.h = h
|
|
hsla.s = s
|
|
hsla.l = l
|
|
|
|
elPalettePointer.value.style.left = `${hsla.s}%`
|
|
elPalettePointer.value.style.top = `${100 - hsla.l}%`
|
|
elSliderHuxPointer.value.style.left = `${(hsla.h / 360) * 100}%`
|
|
|
|
hex.value = value
|
|
} else {
|
|
// hex.value = backendHex
|
|
}
|
|
}
|
|
|
|
function onChangeAlpha(value) {
|
|
hsla.a = value / 100
|
|
elSliderAlphaPointer.value.style.left = `${value}%`
|
|
}
|
|
|
|
function disableChangeHSLA() {
|
|
canChangeHSLAPointerPos = false
|
|
|
|
if (canChangeHSLAPointerPosTimer) clearTimeout(canChangeHSLAPointerPosTimer)
|
|
canChangeHSLAPointerPosTimer = setTimeout(() => {
|
|
canChangeHSLAPointerPos = true
|
|
}, 16)
|
|
}
|
|
|
|
async function onClickStraw(val) {
|
|
let result = ''
|
|
if (val && val.target.value) {
|
|
const color = val.target.value
|
|
result = color + (color.length === 7 ? 'ff' : '')
|
|
} else {
|
|
const eyeDropper = new window.EyeDropper() // 初始化一个EyeDropper对象
|
|
toolTip('按Esc可退出')
|
|
try {
|
|
const drop = await eyeDropper.open() // 开始拾取颜色
|
|
const colorHexValue = drop.sRGBHex
|
|
result = colorHexValue + 'ff'
|
|
} catch (e) {
|
|
console.log('用户取消了取色')
|
|
}
|
|
}
|
|
if (mode.value === '渐变') {
|
|
activeGradient.value.color = result
|
|
activeGradient.value = { ...activeGradient.value }
|
|
} else {
|
|
emit('update:value', result)
|
|
}
|
|
emit('native-pick', result)
|
|
}
|
|
|
|
const onInputBlur = (e) => {
|
|
const fixColor = patchHexColor(e.target.value)
|
|
emit('blur', fixColor)
|
|
emit('update:value', fixColor)
|
|
}
|
|
|
|
function patchHexColor(str) {
|
|
let hex = str.replace(/\s/g, '') // 移除空格
|
|
if (!str.startsWith('#')) {
|
|
hex = '#' + hex
|
|
}
|
|
if (hex.length < 9) {
|
|
hex = hex.padEnd(9, 'f')
|
|
}
|
|
return hex
|
|
}
|
|
|
|
function angleChange() {
|
|
updateValue(toGradientString(angle.value, gradients.value))
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
*,
|
|
::before,
|
|
::after {
|
|
box-sizing: border-box;
|
|
border-width: 0;
|
|
border-style: solid;
|
|
border-color: #e5e7eb;
|
|
}
|
|
.flex-center {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
.title {
|
|
margin-bottom: 0.75rem;
|
|
font-size: 15px;
|
|
font-weight: 600;
|
|
}
|
|
.color-picker {
|
|
-webkit-user-select: none;
|
|
user-select: none;
|
|
min-width: 220px;
|
|
}
|
|
|
|
.cp__gradient {
|
|
&-bar {
|
|
display: flex;
|
|
justify-content: center;
|
|
height: 16px;
|
|
width: 100%;
|
|
padding: 0 8px;
|
|
}
|
|
}
|
|
|
|
.cpgb__track {
|
|
position: relative;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.cpgb__pointer {
|
|
cursor: grab;
|
|
position: absolute;
|
|
top: -0px;
|
|
top: -0.125rem;
|
|
height: 1.25rem;
|
|
--tw-translate-x: -50%;
|
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
border-width: 2px;
|
|
border-style: solid;
|
|
--tw-border-opacity: 1;
|
|
border-color: rgb(255 255 255 / var(--tw-border-opacity));
|
|
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
|
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
|
outline: 2px solid transparent;
|
|
outline-offset: 2px;
|
|
width: 18px;
|
|
|
|
&--active {
|
|
z-index: 1;
|
|
border-radius: 3px;
|
|
box-shadow: 0 0 4px 0 rgb(0 0 0 / 20%), 0 0 0 1.2px #2254f4;
|
|
}
|
|
}
|
|
|
|
.cp__palette {
|
|
height: 140px;
|
|
position: relative;
|
|
margin-top: 0.75rem;
|
|
margin-top: 0.875rem;
|
|
cursor: pointer;
|
|
overflow: hidden;
|
|
border-radius: 0.25rem;
|
|
.cpp__color-saturation,
|
|
.cpp__color-value {
|
|
position: absolute;
|
|
bottom: 0px;
|
|
right: 0px;
|
|
top: 0px;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.cpp__color-saturation {
|
|
background-image: linear-gradient(to right, var(--tw-gradient-stops));
|
|
--tw-gradient-from: #fff var(--tw-gradient-from-position);
|
|
--tw-gradient-to: rgb(255 255 255 / 0) var(--tw-gradient-to-position);
|
|
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
|
}
|
|
|
|
.cpp__color-value {
|
|
background-image: linear-gradient(to top, var(--tw-gradient-stops));
|
|
--tw-gradient-from: #000 var(--tw-gradient-from-position);
|
|
--tw-gradient-to: rgb(0 0 0 / 0) var(--tw-gradient-to-position);
|
|
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);
|
|
}
|
|
|
|
.cpp__pointer {
|
|
position: absolute;
|
|
height: 0.75rem;
|
|
width: 0.75rem;
|
|
--tw-translate-x: -0.25rem;
|
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
--tw-translate-x: -0.375rem;
|
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
--tw-translate-y: -0.25rem;
|
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
border-radius: 9999px;
|
|
border-width: 2px;
|
|
--tw-border-opacity: 1;
|
|
border-color: rgb(255 255 255 / var(--tw-border-opacity));
|
|
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
|
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
|
}
|
|
}
|
|
|
|
.cp__slider {
|
|
position: relative;
|
|
margin-top: 0.75rem;
|
|
margin-top: 0.875rem;
|
|
height: 0.5rem;
|
|
border-radius: 0.25rem;
|
|
&-hux {
|
|
background: linear-gradient(90deg, red 0, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, red);
|
|
}
|
|
|
|
&-alpha {
|
|
background: linear-gradient(to top right, hsla(0, 0%, 80%, 0.4) 25%, transparent 0, transparent 75%, hsla(0, 0%, 80%, 0.4) 0, hsla(0, 0%, 80%, 0.4)), linear-gradient(to top right, hsla(0, 0%, 80%, 0.4) 25%, transparent 0, transparent 75%, hsla(0, 0%, 80%, 0.4) 0, hsla(0, 0%, 80%, 0.4));
|
|
background-size: 6px 6px;
|
|
background-position: 0 0, 3px 3px;
|
|
}
|
|
|
|
.cpsa__background {
|
|
box-shadow: inset 0 0 0 1px rgb(0 0 0 / 6%);
|
|
height: 100%;
|
|
border-radius: 0.25rem;
|
|
}
|
|
}
|
|
.cp__box {
|
|
margin-top: 0.75rem;
|
|
margin-top: 0.875rem;
|
|
display: flex;
|
|
.item {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
cursor: pointer;
|
|
margin-left: 6px;
|
|
width: 24px;
|
|
height: 24px;
|
|
box-sizing: border-box;
|
|
border-radius: 4px;
|
|
}
|
|
.item-color {
|
|
box-shadow: inset 0 0 0 1px rgb(0 0 0 / 6%);
|
|
}
|
|
.item:first-of-type {
|
|
margin: 0;
|
|
}
|
|
.item:hover {
|
|
transform: scale(1.08);
|
|
}
|
|
.input {
|
|
width: 4.7rem;
|
|
margin-left: 2px;
|
|
}
|
|
.native {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
.cps__track {
|
|
position: absolute;
|
|
left: 0.25rem;
|
|
right: 0.25rem;
|
|
top: 0px;
|
|
}
|
|
|
|
.cpst__pointer {
|
|
cursor: pointer;
|
|
box-shadow: 0 0 2px rgb(0 0 0 / 60%);
|
|
position: absolute;
|
|
top: 0px;
|
|
box-sizing: content-box;
|
|
height: 0.5rem;
|
|
width: 0.5rem;
|
|
--tw-translate-x: -0.5rem;
|
|
--tw-translate-y: -0.25rem;
|
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
border-radius: 9999px;
|
|
border-width: 4px;
|
|
--tw-border-opacity: 1;
|
|
border-color: rgb(255 255 255 / var(--tw-border-opacity));
|
|
}
|
|
</style>
|