vue實(shí)現(xiàn)自定義顏色選擇器
vue自定義顏色選擇器
效果圖:

step0: 默認(rèn)寫法 調(diào)用系統(tǒng)自帶的顏色選擇器
<input type="color">
step1:C:\Users\wangrusheng\PycharmProjects\untitled18\src\views\Home.vue
<template>
<div class="container">
<!-- 顏色選擇器組件 -->
<ColorPicker v-model="selectedColor" />
<!-- 新增的動(dòng)態(tài)背景按鈕 -->
<div>
<button
class="dynamic-button"
:style="{ backgroundColor: selectedColor }"
>
我的背景色會(huì)變化!
</button>
<input type="color">
<p>當(dāng)前選中顏色: {{ selectedColor }}</p>
</div>
</div>
</template>
<script>
import ColorPicker from './ColorPicker.vue'
export default {
components: { ColorPicker },
data() {
return {
selectedColor: '#ff0000' // 默認(rèn)顏色
}
}
}
</script>
step2:C:\Users\wangrusheng\PycharmProjects\untitled18\src\views\ColorPicker.vue
<template>
<div class="color-picker">
<!-- 飽和度/明度選擇區(qū)域 -->
<div
class="saturation"
:style="{ backgroundColor: `hsl(${hsv.h}, 100%, 50%)` }"
@mousedown="startDrag"
>
<div
class="selector"
:style="{
left: `${hsv.s * 100}%`,
top: `${(1 - hsv.v) * 100}%`,
backgroundColor: currentColor
}"
></div>
</div>
<!-- 色相滑塊 -->
<div class="hue-slider" @mousedown="startHueDrag">
<div
class="hue-pointer"
:style="{ left: `${(hsv.h / 360) * 100}%` }"
></div>
</div>
<!-- 顏色顯示和輸入 -->
<div class="color-preview" :style="{ backgroundColor: currentColor }"></div>
<input
v-model="hexColor"
class="hex-input"
placeholder="#FFFFFF"
@input="handleHexInput"
>
</div>
</template>
<script>
export default {
props: {
modelValue: String
},
emits: ['update:modelValue'],
data() {
return {
hsv: { h: 0, s: 1, v: 1 },
hexColor: '#ff0000',
isDragging: false,
isHueDragging: false
}
},
computed: {
currentColor() {
return this.hsvToHex(this.hsv)
}
},
methods: {
startDrag(e) {
this.isDragging = true
this.handleDrag(e)
window.addEventListener('mousemove', this.handleDrag)
window.addEventListener('mouseup', this.stopDrag)
},
startHueDrag(e) {
this.isHueDragging = true
this.handleHueDrag(e)
window.addEventListener('mousemove', this.handleHueDrag)
window.addEventListener('mouseup', this.stopHueDrag)
},
handleDrag(e) {
if (!this.isDragging) return
const rect = e.target.getBoundingClientRect()
const x = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width))
const y = Math.max(0, Math.min(1, (e.clientY - rect.top) / rect.height))
this.hsv.s = x
this.hsv.v = 1 - y
this.updateHex()
},
handleHueDrag(e) {
if (!this.isHueDragging) return
const rect = e.target.getBoundingClientRect()
const x = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width))
this.hsv.h = x * 360
this.updateHex()
},
stopDrag() {
this.isDragging = false
window.removeEventListener('mousemove', this.handleDrag)
window.removeEventListener('mouseup', this.stopDrag)
},
stopHueDrag() {
this.isHueDragging = false
window.removeEventListener('mousemove', this.handleHueDrag)
window.removeEventListener('mouseup', this.stopHueDrag)
},
updateHex() {
this.hexColor = this.hsvToHex(this.hsv)
this.$emit('update:modelValue', this.hexColor)
},
handleHexInput() {
if (/^#([0-9A-F]{3}){1,2}$/i.test(this.hexColor)) {
this.hsv = this.hexToHsv(this.hexColor)
}
},
// 顏色轉(zhuǎn)換函數(shù)
hsvToHex(hsv) {
const h = hsv.h / 360
let r, g, b
const i = Math.floor(h * 6)
const f = h * 6 - i
const p = hsv.v * (1 - hsv.s)
const q = hsv.v * (1 - f * hsv.s)
const t = hsv.v * (1 - (1 - f) * hsv.s)
switch (i % 6) {
case 0: r = hsv.v, g = t, b = p; break
case 1: r = q, g = hsv.v, b = p; break
case 2: r = p, g = hsv.v, b = t; break
case 3: r = p, g = q, b = hsv.v; break
case 4: r = t, g = p, b = hsv.v; break
case 5: r = hsv.v, g = p, b = q; break
}
return `#${[r, g, b]
.map(x => Math.round(x * 255)
.toString(16)
.padStart(2, '0'))
.join('')}`
},
hexToHsv(hex) {
// 轉(zhuǎn)換邏輯(此處省略具體實(shí)現(xiàn))
// 返回類似 {h: 0, s: 1, v: 1} 的HSV對(duì)象
}
}
}
</script>
<style>
.color-picker {
width: 300px;
padding: 20px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.saturation {
position: relative;
width: 100%;
height: 200px;
border-radius: 4px;
background: linear-gradient(to top, #000, transparent),
linear-gradient(to right, #fff, transparent);
}
.selector {
position: absolute;
width: 16px;
height: 16px;
border: 2px solid white;
border-radius: 50%;
transform: translate(-8px, -8px);
box-shadow: 0 1px 3px rgba(0,0,0,0.3);
}
.hue-slider {
position: relative;
height: 12px;
margin: 15px 0;
background: linear-gradient(to right,
#ff0000 0%,
#ffff00 17%,
#00ff00 33%,
#00ffff 50%,
#0000ff 67%,
#ff00ff 83%,
#ff0000 100%);
border-radius: 6px;
}
.hue-pointer {
position: absolute;
width: 16px;
height: 16px;
background: white;
border-radius: 50%;
transform: translate(-8px, -2px);
box-shadow: 0 1px 3px rgba(0,0,0,0.3);
}
.color-preview {
width: 40px;
height: 40px;
border-radius: 4px;
border: 1px solid #ddd;
}
.hex-input {
margin-left: 10px;
padding: 8px;
width: 100px;
border: 1px solid #ddd;
border-radius: 4px;
}
</style>
到此這篇關(guān)于vue實(shí)現(xiàn)自定義顏色選擇器的文章就介紹到這了,更多相關(guān)vue顏色選擇器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue實(shí)現(xiàn)數(shù)字動(dòng)畫的幾種方案
本文介紹了三種使用Vue實(shí)現(xiàn)動(dòng)態(tài)數(shù)字動(dòng)畫的方案:使用Vue的響應(yīng)式數(shù)據(jù)與`setInterval`逐步更新數(shù)字,通過(guò)Vue的動(dòng)畫API和CSS動(dòng)畫效果為數(shù)字增加過(guò)渡效果,以及使用更高效的`requestAnimationFrame`來(lái)提供更加流暢的動(dòng)畫表現(xiàn),每種方案都詳細(xì)說(shuō)明了原理、實(shí)現(xiàn)步驟和代碼示例2025-02-02
vue前端實(shí)現(xiàn)表格數(shù)據(jù)增查改刪功能
增刪改查是我們寫項(xiàng)目百分之七十會(huì)遇到的代碼,下面這篇文章主要給大家介紹了關(guān)于vue前端實(shí)現(xiàn)表格數(shù)據(jù)增查改刪功能的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-05-05
Vue頁(yè)面跳轉(zhuǎn)傳遞參數(shù)及接收方式
這篇文章主要介紹了Vue頁(yè)面跳轉(zhuǎn)傳遞參數(shù)及接收方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
vue性能優(yōu)化之cdn引入vue-Router的問(wèn)題
這篇文章主要介紹了vue性能優(yōu)化之cdn引入vue-Router的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
詳解vue2.0 使用動(dòng)態(tài)組件實(shí)現(xiàn) Tab 標(biāo)簽頁(yè)切換效果(vue-cli)
本篇文章主要介紹了詳解vue2.0 使用動(dòng)態(tài)組件實(shí)現(xiàn) Tab 標(biāo)簽頁(yè)切換效果(vue-cli),具有一定的參考價(jià)值,有需要的可以了解下2017-08-08
vue3使用element-plus搭建后臺(tái)管理系統(tǒng)之菜單管理功能
這篇文章主要介紹了vue3使用element-plus搭建后臺(tái)管理系統(tǒng)之菜單管理,使用element-plus el-tree組件快速開發(fā)樹形菜單結(jié)構(gòu),el-tree組件中filter-node-method事件便可以實(shí)現(xiàn)樹形菜單篩選過(guò)濾功能,需要的朋友可以參考下2022-04-04
vue draggable resizable gorkys與v-chart使用與總結(jié)
這篇文章主要介紹了vue draggable resizable gorkys與v-chart使用與總結(jié),本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09

