colorPicker.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. <template>
  2. <!-- 取色器 -->
  3. <div class="color-select">
  4. <div class="saturation-value" ref="saturation_value" @mousedown="mousedownColorPalette">
  5. <div :style="`background-color: hsl(${hue}, 100%, 50%);`">
  6. <div class="point" :style="pointStyle"></div>
  7. </div>
  8. <div class="saturation-value-2"></div>
  9. <div class="saturation-value-3"></div>
  10. </div>
  11. <div class="color-select-middle">
  12. <div class="color-slider">
  13. <div class="hue-slider slider-item" ref="hue_slider" @mousedown="mousedownHue">
  14. <div class="slider" :style="hueSliderStyle"></div>
  15. </div>
  16. <div class="alpha-slider slider-item" ref="alpha_slider" @mousedown="mousedownAlpha" v-if="props.alpha">
  17. <div class="slider" :style="alphaSliderStyle"></div>
  18. <div
  19. :style="`background: linear-gradient(to right, rgba(0,0,0,0), ${colorEnums.rgb});width: 100%;height: 100%`">
  20. </div>
  21. </div>
  22. </div>
  23. <div class="color-diamond">
  24. <div
  25. :style="`background-color: ${colorEnums.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);`">
  26. </div>
  27. </div>
  28. </div>
  29. <div class="color-value">
  30. <div class="hex">
  31. <label>
  32. <input :value="colorEnums.hex8" @input="hexChange" spellcheck="false" />
  33. </label>
  34. <p>Hex</p>
  35. </div>
  36. <div class="rgba-r">
  37. <label>
  38. <input :value="red" @input="redChange" />
  39. </label>
  40. <p>R</p>
  41. </div>
  42. <div class="rgba-g">
  43. <label>
  44. <input :value="green" @input="greenChange" />
  45. </label>
  46. <p>G</p>
  47. </div>
  48. <div class="rgba-b">
  49. <label>
  50. <input :value="blue" @input="blueChange" />
  51. </label>
  52. <p>B</p>
  53. </div>
  54. <div class="rgba-a" v-if="props.alpha">
  55. <label>
  56. <input :value="alpha" @input="alphaChange" />
  57. </label>
  58. <p>A</p>
  59. </div>
  60. </div>
  61. <ul class="predefine">
  62. <li class="predefine-item" v-for="(item, index) in predefine" :key="index" :style="`background-color: ${item}`"
  63. @click="predefineChange(item)"></li>
  64. </ul>
  65. <div class="color-actions">
  66. <span class="cancel" @click="emits('close')">取消</span>
  67. <span class="confirm" @click="handleConfirm">确定</span>
  68. </div>
  69. </div>
  70. </template>
  71. <script setup lang="ts">
  72. import { ref, computed, watch, onMounted } from 'vue'
  73. const props = defineProps({
  74. color: {
  75. type: Object || String,
  76. default() {
  77. return {
  78. r: 217,
  79. g: 128,
  80. b: 95,
  81. a: 1
  82. }
  83. }
  84. },
  85. predefine: {
  86. type: Array,
  87. default() {
  88. return []
  89. }
  90. },
  91. alpha: {
  92. type: Boolean,
  93. default: true
  94. },
  95. mode: {
  96. type: String,
  97. default: 'hex6' // hex6/hex8/rgb/rgba
  98. }
  99. })
  100. const emits = defineEmits(['update:color', 'close', 'handleConfirm'])
  101. const saturation_value: any = ref(null)
  102. const hue_slider: any = ref(null)
  103. const alpha_slider: any = ref(null)
  104. let pointStyle: any = ref('top: 25%;left: 80%;')
  105. let hueSliderStyle: any = ref('left: 0;')
  106. let alphaSliderStyle: any = ref('left: calc(100% - 6px);')
  107. let hue: any = ref(0)
  108. let saturation: any = ref(1)
  109. let value: any = ref(1)
  110. let red: any = ref(255)
  111. let green: any = ref(0)
  112. let blue: any = ref(0)
  113. let alpha: any = ref(1)
  114. onMounted(() => {
  115. // console.log('parseColor(props.color)', parseColor(props.color))
  116. let { r, g, b, a }: any = parseColor(props.color)
  117. red.value = r
  118. green.value = g
  119. blue.value = b
  120. alpha.value = a
  121. })
  122. watch(() => props.color, (newValue) => {
  123. if (newValue) {
  124. let { r, g, b, a }: any = parseColor(newValue)
  125. red.value = r
  126. green.value = g
  127. blue.value = b
  128. alpha.value = a
  129. }
  130. }, { immediate: true, deep: true })
  131. watch([red, green, blue], () => {
  132. let { h, s, v } = rgb2hsv(red.value, green.value, blue.value)
  133. hue.value = h
  134. saturation.value = s
  135. value.value = v
  136. // 移动背景板圆圈
  137. pointStyle.value = `top: ${100 - v * 100}%;left: ${s * 100}%;`
  138. // 移动色调滑块
  139. hueSliderStyle.value = `left: ${(hue.value / 360) * 100}%;`
  140. }, { immediate: true, deep: true })
  141. watch(alpha, () => {
  142. // 移动透明度滑块
  143. alphaSliderStyle.value = `left: ${alpha.value >= 1 ? 'calc(100% - 6px)' : alpha.value * 100 + '%'};`
  144. })
  145. let colorEnums = computed(() => {
  146. let r = red.value
  147. let g = green.value
  148. let b = blue.value
  149. let a = alpha.value
  150. let h = hue.value
  151. let s = saturation.value
  152. let v = value.value
  153. return {
  154. rgb: `rgba(${r},${g},${b})`,
  155. rgba: `rgba(${r}, ${g}, ${b}, ${a})`,
  156. hex6: rgba2hex(r, g, b),
  157. hex8: rgba2hex(r, g, b, a),
  158. hsv: `hsv(${h},${s},${v})`
  159. }
  160. })
  161. // 确认选中的颜色值
  162. const handleConfirm = () => {
  163. // console.log('props.mode', props.mode)
  164. // console.log('handleConfirm', (colorEnums.value as any)[props.mode])
  165. emits('update:color', (colorEnums.value as any)[props.mode])
  166. emits('handleConfirm', (colorEnums.value as any)[props.mode])
  167. }
  168. // 输入框值变化,限制输入的值
  169. function hexChange(e) {
  170. let v = e.target.value
  171. if (/^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(v)) {
  172. let { r, g, b, a }: any = hex2rgba(v)
  173. red.value = r
  174. green.value = g
  175. blue.value = b
  176. alpha.value = a
  177. }
  178. }
  179. function redChange(e) {
  180. let v = e.target.value
  181. if (v !== '') {
  182. v > 255 && (red.value = 255)
  183. v < 0 && (red.value = 0)
  184. v >= 0 && v <= 255 && (red.value = parseInt(v))
  185. }
  186. }
  187. function greenChange(e) {
  188. let v = e.target.value
  189. if (v !== '') {
  190. v > 255 && (green.value = 255)
  191. v < 0 && (green.value = 0)
  192. v >= 0 && v <= 255 && (green.value = parseInt(v))
  193. }
  194. }
  195. function blueChange(e) {
  196. let v = e.target.value
  197. if (v !== '') {
  198. v > 255 && (blue.value = 255)
  199. v < 0 && (blue.value = 0)
  200. v >= 0 && v <= 255 && (blue.value = parseInt(v))
  201. }
  202. }
  203. function alphaChange(e) {
  204. let v = e.target.value
  205. if (v !== '') {
  206. v = parseFloat(v)
  207. alpha.value = v
  208. v > 1 && (alpha.value = 1)
  209. v < 0 && (alpha.value = 0)
  210. v >= 0 && v <= 1 && (alpha.value = v)
  211. }
  212. }
  213. // 点击预设方块事件
  214. function predefineChange(item) {
  215. if (/^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(item)) {
  216. let { r, g, b, a }: any = hex2rgba(item)
  217. red.value = r
  218. green.value = g
  219. blue.value = b
  220. alpha.value = a
  221. }
  222. }
  223. // 计算选中点的颜色值
  224. function handleChangeColorPalette(e) {
  225. let w = saturation_value.value.clientWidth
  226. let h = saturation_value.value.clientHeight
  227. let x = e.pageX - saturation_value.value.getBoundingClientRect().left
  228. let y = e.pageY - saturation_value.value.getBoundingClientRect().top
  229. x = x < w && x > 0 ? x : x > w ? w : 0
  230. y = y < h && y > 0 ? y : y > h ? h : 0
  231. // 计算饱和度和亮度
  232. saturation.value = Math.floor((x / w) * 100 + 0.5) / 100
  233. value.value = Math.floor((1 - y / h) * 100 + 0.5) / 100
  234. // hsv转化为rgb
  235. let { r, g, b } = hsv2rgb(hue.value, saturation.value, value.value)
  236. red.value = r
  237. green.value = g
  238. blue.value = b
  239. // 移动背景板圆圈
  240. pointStyle.value = `top: ${y}px;left: ${x}px;`
  241. }
  242. function mousedownColorPalette(e) {
  243. // 鼠标按下计算饱和度和亮度并添加事件
  244. handleChangeColorPalette(e)
  245. // 添加整个页面的鼠标事件
  246. window.addEventListener('mousemove', handleChangeColorPalette)
  247. window.addEventListener('mouseup', mouseupColorPalette)
  248. }
  249. function mouseupColorPalette() {
  250. // 鼠标松开后移除事件
  251. window.removeEventListener('mousemove', handleChangeColorPalette)
  252. window.removeEventListener('mouseup', mouseupColorPalette)
  253. }
  254. // 色调
  255. function handleChangeHue(e) {
  256. let w = hue_slider.value.clientWidth
  257. let x = e.pageX - saturation_value.value.getBoundingClientRect().left
  258. x = x < w && x > 0 ? x : x > w ? w : 0
  259. // 计算色调
  260. hue.value = Math.floor((x / w) * 360 + 0.5)
  261. // hsv转化为rgb
  262. let { r, g, b } = hsv2rgb(hue.value, saturation.value, value.value)
  263. red.value = r
  264. green.value = g
  265. blue.value = b
  266. // 移动滑块
  267. hueSliderStyle.value = `left: ${x >= w - 6 ? w - 6 : x}px;`
  268. }
  269. function mousedownHue(e) {
  270. handleChangeHue(e)
  271. window.addEventListener('mousemove', handleChangeHue)
  272. window.addEventListener('mouseup', mouseupHue)
  273. }
  274. function mouseupHue() {
  275. window.removeEventListener('mousemove', handleChangeHue)
  276. window.removeEventListener('mouseup', mouseupHue)
  277. }
  278. // 透明度
  279. function handleChangeAlpha(e) {
  280. let w = alpha_slider.value.clientWidth
  281. let x = e.pageX - saturation_value.value.getBoundingClientRect().left
  282. x = x < w && x > 0 ? x : x > w ? w : 0
  283. // 计算透明度
  284. alpha.value = Math.floor((x / w) * 100 + 0.5) / 100
  285. // 移动滑块
  286. alphaSliderStyle.value = `left: ${x >= w - 6 ? w - 6 : x}px;`
  287. }
  288. function mousedownAlpha(e) {
  289. handleChangeAlpha(e)
  290. window.addEventListener('mousemove', handleChangeAlpha)
  291. window.addEventListener('mouseup', mouseupAlpha)
  292. }
  293. function mouseupAlpha() {
  294. window.removeEventListener('mousemove', handleChangeAlpha)
  295. window.removeEventListener('mouseup', mouseupAlpha)
  296. }
  297. /**
  298. * 解析输入的数据,只能解析hex颜色和rgb对象形式的数据
  299. * @param color
  300. */
  301. function parseColor(color) {
  302. if (color) {
  303. let r, g, b, a
  304. if (typeof color === 'string') {
  305. if (/^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{8}|[0-9a-fA-F]{3}|[0-9a-fA-F]{4})$/.test(color)) {
  306. return hex2rgba(color)
  307. } else if (color.includes('linear-gradient')) {
  308. // console.log('111parseColor111', color)
  309. let matchColors = color.match(/#[0-9a-fA-F]{6}/g)
  310. // console.log('matchColors', matchColors)
  311. let avgColor = getAvgColor(matchColors)
  312. // console.log('avgColor', avgColor)
  313. return hex2rgba(avgColor)
  314. }
  315. } else {
  316. r = color.r > 255 ? 255 : color.r < 0 ? 0 : color.r
  317. g = color.g > 255 ? 255 : color.g < 0 ? 0 : color.g
  318. b = color.b > 255 ? 255 : color.b < 0 ? 0 : color.b
  319. a = color.a > 1 ? 1 : color.a < 0 ? 0 : color.a
  320. return { r, g, b, a }
  321. }
  322. } else {
  323. return null
  324. }
  325. }
  326. function hsv2rgb(h, s, v) {
  327. h === 360 && (h = 0)
  328. let i = Math.floor(h / 60) % 6
  329. let f = h / 60 - i
  330. let p = v * (1 - s)
  331. let q = v * (1 - s * f)
  332. let t = v * (1 - s * (1 - f))
  333. let r, g, b
  334. if (i === 0) {
  335. r = v
  336. g = t
  337. b = p
  338. } else if (i === 1) {
  339. r = q
  340. g = v
  341. b = p
  342. } else if (i === 2) {
  343. r = p
  344. g = v
  345. b = t
  346. } else if (i === 3) {
  347. r = p
  348. g = q
  349. b = v
  350. } else if (i === 4) {
  351. r = t
  352. g = p
  353. b = v
  354. } else if (i === 5) {
  355. r = v
  356. g = p
  357. b = q
  358. }
  359. r = Math.floor(r * 255 + 0.5)
  360. g = Math.floor(g * 255 + 0.5)
  361. b = Math.floor(b * 255 + 0.5)
  362. return { r, g, b }
  363. }
  364. function rgb2hsv(r, g, b) {
  365. let r1 = r / 255
  366. let g1 = g / 255
  367. let b1 = b / 255
  368. let cmax = Math.max(r1, g1, b1)
  369. let cmin = Math.min(r1, g1, b1)
  370. let d = cmax - cmin
  371. let h, s, v
  372. if (d === 0) {
  373. h = 0
  374. } else if (cmax === r1) {
  375. h = ((60 * (g1 - b1)) / d + 360) % 360
  376. } else if (cmax === g1) {
  377. h = 60 * ((b1 - r1) / d + 2)
  378. } else if (cmax === b1) {
  379. h = 60 * ((r1 - g1) / d + 4)
  380. }
  381. if (cmax === 0) {
  382. s = 0
  383. } else {
  384. s = d / cmax
  385. }
  386. v = cmax
  387. h = Math.floor(h + 0.5)
  388. s = Math.floor(s * 100 + 0.5) / 100
  389. v = Math.floor(v * 100 + 0.5) / 100
  390. return { h, s, v }
  391. }
  392. function rgba2hex(r, g, b, a: any = 1) {
  393. r = parseInt(r)
  394. let r1 = r.toString(16).length !== 2 ? '0' + r.toString(16) : r.toString(16)
  395. g = parseInt(g)
  396. let g1 = g.toString(16).length !== 2 ? '0' + g.toString(16) : g.toString(16)
  397. b = parseInt(b)
  398. let b1 = b.toString(16).length !== 2 ? '0' + b.toString(16) : b.toString(16)
  399. a = parseFloat(a)
  400. let a1 = ''
  401. if (a !== 1) {
  402. let temp = Math.floor(256 * a)
  403. a1 = temp.toString(16).length !== 2 ? '0' + temp.toString(16) : temp.toString(16)
  404. }
  405. return `#${r1}${g1}${b1}${a1}`.toUpperCase()
  406. }
  407. function hex2rgba(s) {
  408. // console.log('111111', s)
  409. if (/^#?[0-9a-fA-F]{3}$/.test(s)) {
  410. let b = s.substring(s.length - 1, s.length)
  411. let g = s.substring(s.length - 2, s.length - 1)
  412. let r = s.substring(s.length - 3, s.length - 2)
  413. return hex2rgba(`${r + r}${g + g}${b + b}`)
  414. }
  415. if (/^#?[0-9a-fA-F]{4}$/.test(s)) {
  416. let a = s.substring(s.length - 1, s.length)
  417. let b = s.substring(s.length - 2, s.length - 1)
  418. let g = s.substring(s.length - 3, s.length - 2)
  419. let r = s.substring(s.length - 4, s.length - 3)
  420. return hex2rgba(`${r + r}${g + g}${b + b}${a + a}`)
  421. }
  422. if (/^#?[0-9a-fA-F]{6}$/.test(s)) {
  423. let b = parseInt('0x' + s.substring(s.length - 2, s.length))
  424. let g = parseInt('0x' + s.substring(s.length - 4, s.length - 2))
  425. let r = parseInt('0x' + s.substring(s.length - 6, s.length - 4))
  426. return { r, g, b, a: 1 }
  427. }
  428. if (/^#?[0-9a-fA-F]{8}$/.test(s)) {
  429. let a = parseInt('0x' + s.substring(s.length - 2, s.length))
  430. a = a / 255
  431. let b = parseInt('0x' + s.substring(s.length - 4, s.length - 2))
  432. let g = parseInt('0x' + s.substring(s.length - 6, s.length - 4))
  433. let r = parseInt('0x' + s.substring(s.length - 8, s.length - 6))
  434. return { r, g, b, a }
  435. }
  436. }
  437. function getAvgColor(arr) {
  438. try {
  439. let parseColor = function (hexStr) {
  440. return hexStr.length === 4
  441. ? hexStr
  442. .substr(1)
  443. .split('')
  444. .map(function (s) {
  445. return 0x11 * parseInt(s, 16)
  446. })
  447. : [hexStr.substr(1, 2), hexStr.substr(3, 2), hexStr.substr(5, 2)].map(function (s) {
  448. return parseInt(s, 16)
  449. })
  450. }
  451. let pad = function (s) {
  452. return s.length === 1 ? '0' + s : s
  453. }
  454. let gradientColors: any = function (start, end, steps, gamma) {
  455. let i
  456. let j
  457. let ms
  458. let me
  459. let output: any = []
  460. let so: any = []
  461. gamma = gamma || 1
  462. let normalize = function (channel) {
  463. return Math.pow(channel / 255, gamma)
  464. }
  465. start = parseColor(start).map(normalize)
  466. end = parseColor(end).map(normalize)
  467. for (i = 0; i < steps; i++) {
  468. ms = i / (steps - 1)
  469. me = 1 - ms
  470. for (j = 0; j < 3; j++) {
  471. so[j] = pad(Math.round(Math.pow(start[j] * me + end[j] * ms, 1 / gamma) * 255).toString(16))
  472. }
  473. output.push('#' + so.join(''))
  474. }
  475. return output
  476. }
  477. return gradientColors(arr[0], arr[1], 3)[1]
  478. } catch (err) {
  479. return arr[0]
  480. }
  481. }
  482. </script>
  483. <style lang="scss" scoped>
  484. .color-select {
  485. position: relative;
  486. user-select: none;
  487. width: 300px;
  488. background: #fff;
  489. padding: 10px;
  490. /*border: 1px solid #ccc;*/
  491. /*border-radius: 10px;*/
  492. }
  493. /* 饱和度和亮度 */
  494. .saturation-value {
  495. cursor: pointer;
  496. width: 100%;
  497. height: 200px;
  498. position: relative;
  499. margin-bottom: 10px;
  500. box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
  501. }
  502. .saturation-value>div {
  503. position: absolute;
  504. top: 0;
  505. left: 0;
  506. width: 100%;
  507. height: 100%;
  508. }
  509. /* 圆圈 */
  510. .point {
  511. box-sizing: border-box;
  512. width: 6px;
  513. height: 6px;
  514. background-color: transparent;
  515. border: 2px solid #ccc;
  516. border-radius: 50%;
  517. transform: translate(-50%, -50%);
  518. position: absolute;
  519. z-index: 9;
  520. }
  521. .saturation-value-2 {
  522. background: linear-gradient(to right, white, #ffffff00);
  523. }
  524. .saturation-value-3 {
  525. background: linear-gradient(to top, black, #ffffff00);
  526. }
  527. /* 色调 透明度 */
  528. .color-select-middle {
  529. width: 100%;
  530. display: flex;
  531. margin-bottom: 10px;
  532. }
  533. .slider-item+.slider-item {
  534. margin-top: 6px;
  535. }
  536. /* 色调滑块条 */
  537. .hue-slider {
  538. position: relative;
  539. height: 10px;
  540. background: linear-gradient(90deg, red 0, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, red);
  541. box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
  542. width: 100%;
  543. }
  544. /* 透明度滑块条 */
  545. .alpha-slider {
  546. position: relative;
  547. height: 10px;
  548. box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.1);
  549. background: #fff url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAWElEQVRIiWM8fubkfwYygKWJOSM5+mCAhRLNoxaPWjxq8ajFoxbTyeL/DAfJ0Xjs3Cl7Siwmu4Yht1aDgZEYx6MWj1o8avGoxaMWD3qLya5X//4nqx6HAQC7RBGFzolqTAAAAABJRU5ErkJggg==');
  550. background-size: 10px 10px;
  551. width: 100%;
  552. }
  553. /* 滑块 */
  554. .slider {
  555. position: absolute;
  556. box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
  557. box-sizing: border-box;
  558. width: 6px;
  559. height: 100%;
  560. background-color: #fff;
  561. }
  562. .color-slider {
  563. flex: auto;
  564. display: flex;
  565. align-items: center;
  566. flex-wrap: wrap;
  567. }
  568. /* 颜色方块 */
  569. .color-diamond {
  570. position: relative;
  571. margin-left: 5px;
  572. width: 26px;
  573. height: 26px;
  574. border-radius: 3px;
  575. overflow: hidden;
  576. background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAWElEQVRIiWM8fubkfwYygKWJOSM5+mCAhRLNoxaPWjxq8ajFoxbTyeL/DAfJ0Xjs3Cl7Siwmu4Yht1aDgZEYx6MWj1o8avGoxaMWD3qLya5X//4nqx6HAQC7RBGFzolqTAAAAABJRU5ErkJggg==');
  577. background-size: 10px 10px;
  578. }
  579. /* 颜色的值 hex rgba */
  580. .color-value {
  581. width: 100%;
  582. display: flex;
  583. justify-content: space-between;
  584. }
  585. .color-value div {
  586. padding: 0 3px;
  587. text-align: center;
  588. }
  589. .color-value input {
  590. font-size: 12px;
  591. box-sizing: border-box;
  592. width: 34px;
  593. height: 24px;
  594. padding: 0;
  595. margin: 0;
  596. outline: none;
  597. text-align: center;
  598. border-radius: 3px;
  599. border: 1px solid #ccc;
  600. }
  601. .color-value p {
  602. font-size: 12px;
  603. margin: 3px 0 0;
  604. }
  605. .color-value .rgba-a {
  606. padding-right: 0;
  607. }
  608. .color-value .hex {
  609. flex: 1;
  610. padding-left: 0;
  611. }
  612. .color-value .hex input {
  613. width: 100%;
  614. height: 24px;
  615. }
  616. /* 预设颜色 */
  617. .predefine {
  618. width: 100%;
  619. padding: 0;
  620. margin: 10px 0 0;
  621. list-style: none;
  622. display: flex;
  623. flex-wrap: wrap;
  624. justify-content: flex-start;
  625. }
  626. .predefine-item {
  627. width: 20px;
  628. height: 20px;
  629. margin-bottom: 6px;
  630. border: 1px solid #ccc;
  631. border-radius: 6px;
  632. }
  633. .predefine-item+.predefine-item {
  634. margin-left: 6px;
  635. }
  636. .predefine-item:nth-child(12n) {
  637. margin-left: 0;
  638. }
  639. .color-actions {
  640. font-size: 12px;
  641. text-align: right;
  642. }
  643. .color-actions span {
  644. cursor: pointer;
  645. padding: 5px 12px;
  646. line-height: 12px;
  647. display: inline-block;
  648. box-sizing: border-box;
  649. border: 1px solid transparent;
  650. }
  651. .color-actions .cancel:hover {
  652. background-color: #f5f7fa;
  653. }
  654. .color-actions .confirm {
  655. border-color: #dcdfe6;
  656. border-radius: 4px;
  657. margin-left: 10px;
  658. }
  659. .color-actions .confirm:hover {
  660. color: #1677ff;
  661. border-color: #1677ff;
  662. }
  663. </style>