當前位置:
首頁 > 知識 > 基於vue的顏色選擇器vue-color-picker

基於vue的顏色選擇器vue-color-picker

項目中有用到顏色選擇器的童鞋們可以看過來了

關於color-picker的jquery的插件是有蠻多,不過vue組件沒有吧,反正我沒有找到,

雖然element-ui裡面有這個,但是你願意為了一個小功能去引入這麼大的依賴庫嗎?

適用於:想寫基於vue的單個color-picker功能的童鞋

甩github地址啦:https://github.com/alexzaolin/vue-color-picker

(麻煩覺得有用的童鞋幫我點個star,謝謝謝謝謝~~)

湊個字數貼一下代碼(部分演算法來自網路):

<template lang="html">
<div>
<div class="color-picker-container" :id="containerId" :class="{"active":isShowPicker}">
<div class="color"></div>
<div class="wheel"></div>
<div class="overlay"></div>
<div class="h-marker marker"></div>
<div class="sl-marker marker"></div>
</div>
</div>
</template>

<script>
/**
* author : alex
* email : 961163829@qq.com
*/
export default {
props:{
/*由父組件傳遞的默認顏色*/
defaultColor:{
type:String,
default:"#000000"
},
/*目標元素,可以是input框或者按鈕等*/
targetElem:null
},
data{
return {
isShowPicker:false,
wheel:document.querySelector(".wheel"),
color:this.defaultColor,
containerId:"color-picker-container",
dom:{
hMarker:null,
slMarker:null,
color:null,
targetElem:null,
container:null
},
radius:84,
square:100,
width:194
}
},
mounted{

this.dom.container=document.querySelector("#"+this.containerId);
this.dom.hMarker=document.querySelector(".h-marker");
this.dom.slMarker=document.querySelector(".sl-marker");
this.dom.color=document.querySelector(".color");
this.dom.targetElem=document.querySelector(this.targetElem);

this.init;
},
methods:{
init:function{
var self = this;
self.posInit;
self.eventBind;

// Init color
self.setColor(self.color);
},
openPicker:function{
var self = this;
this.isShowPicker = true;
this.wheel=document.querySelector(".wheel");
/*色盤打開的時候綁定點擊事件*/
document.addEventListener("click",self.documentClick);
},
closePicker:function{
this.isShowPicker = false;
/*色盤關閉的時候解綁事件*/
document.removeEventListener("click",this.documentClick);
},
eventBind:function{
var self = this;
self.dom.container.addEventListener("mousedown",self.mousedown);
},
documentClick:function(e){
/*你可能不需要關閉色盤,那這個方法也是可以不需要的*/
var parents1 = this.getParents(e,this.dom.container,true);;
var parents2 = this.getParents(e,this.dom.targetElem,true);
if(parents1.length===0&&parents2.length===0){
this.closePicker;
}
},
posInit:function{
/*色盤的位置計算*/
var target = this.dom.targetElem;

var top = this.getElementViewTop(target);
var left = this.getElementViewLeft(target);

this.dom.container.style.position = "fixed";
this.dom.container.style.top = (top)+"px";

this.dom.container.style.left = (left + this.dom.targetElem.offsetWidth)+"px";

},
getElementViewLeft:function(element){
/*獲取元素距離視窗左部距離*/
    var actualLeft = element.offsetLeft;
    var current = element.offsetParent;

    while (current !== null){
actualLeft += current.offsetLeft;
current = current.offsetParent;
    }

    if (document.compatMode == "BackCompat"){
var elementScrollLeft=document.body.scrollLeft;
    } else {
var elementScrollLeft=document.documentElement.scrollLeft;
    }

    return actualLeft-elementScrollLeft;
  },
getElementViewTop:function(element){
/*獲取元素距離視窗頂部距離*/
    var actualTop = element.offsetTop;
    var current = element.offsetParent;

    while (current !== null){
actualTop += current. offsetTop;
current = current.offsetParent;
    }

    if (document.compatMode == "BackCompat"){
var elementScrollTop=document.body.scrollTop;
    } else {
var elementScrollTop=document.documentElement.scrollTop;
    }

    return actualTop-elementScrollTop;
  },
getParents:function(e,parent,andSelf){
/*獲取祖先節點,返回一個數組*/
var target = e.target;
var parent = typeof parent==="string"?document.querySelector(parent):parent;

var curTarget = target;

var arr = typeof andSelf === "undefined"?[curTarget]:;
var result = ;

while(true){
if((typeof parent !== "undefined"&&curTarget == parent)||
typeof parent === "undefined"&&curTarget.nodeType===9){
arr.push(curTarget);
break;
}
if(!!curTarget){arr.push(curTarget)}

if(!!curTarget.parentNode){
curTarget = curTarget.parentNode
}else{
break;
}
}
if(!!parent){
return arr.indexOf(parent)>-1?arr:;
}else{
return arr;
}
},
getParent:function(e){
/*獲取父節點*/
return e.target.nodeType!==9&&e.target.parentNode;
},
/**
* 以下為組件內部函數
* 演算法來自網路
*/
updateValue:function (event) {
var self = this;

var that = event.target;
if (that.value && that.value != self.color) {
self.setColor(that.value);
}
},
/**
* Change color with HTML syntax #123456
*/
setColor:function (color) {
var self = this;
var unpack = self.unpack(color);
if (self.color != color && unpack) {

self.color = color;
self.rgb = unpack;
self.hsl = self.RGBToHSL(self.rgb);
self.updateDisplay;
}
},
/**
* Change color with HSL triplet [0..1, 0..1, 0..1]
*/
setHSL:function (hsl) {
var self = this;
self.hsl = hsl;
self.rgb = self.HSLToRGB(hsl);
self.color = self.pack(self.rgb);
self.updateDisplay;
},
/**
* Retrieve the coordinates of the given event relative to the center
* of the widget.
*/
widgetCoords:function (event) {
var self = this;
var x, y;
var el = event.target || event.srcElement;
var reference = self.wheel;

if (typeof event.offsetX != "undefined") {
// Use offset coordinates and find common offsetParent
var pos = { x: event.offsetX, y: event.offsetY };

// Send the coordinates upwards through the offsetParent chain.
var e = el;
while (e) {
e.mouseX = pos.x;
e.mouseY = pos.y;
pos.x += e.offsetLeft;
pos.y += e.offsetTop;
e = e.offsetParent;
}

// Look for the coordinates starting from the wheel widget.
var e = reference;
var offset = { x: 0, y: 0 }
while (e) {
if (typeof e.mouseX != "undefined") {
x = e.mouseX - offset.x;
y = e.mouseY - offset.y;
break;
}
offset.x += e.offsetLeft;
offset.y += e.offsetTop;
e = e.offsetParent;
}

// Reset stored coordinates
e = el;
while (e) {
e.mouseX = undefined;
e.mouseY = undefined;
e = e.offsetParent;
}
}
else {
// Use absolute coordinates
var pos = self.absolutePosition(reference);
x = (event.pageX || 0*(event.clientX + document.documentElement.scrollLeft)) - pos.x;
y = (event.pageY || 0*(event.clientY + document.documentElement.scrollTop)) - pos.y;
}
// Subtract distance to middle
return { x: x - self.width / 2, y: y - self.width / 2 };
},
/**
* Mousedown handler
*/
mousedown:function (event) {
var self = this;
if (!document.dragging) {
document.documentElement.addEventListener("mousemove", self.mousemove);
document.documentElement.addEventListener("mouseup", self.mouseup);
document.dragging = true;
}

// Check which area is being dragged
var pos = self.widgetCoords(event);
self.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > self.square;

// Process
self.mousemove(event);
return false;
},
/**
* Mousemove handler
*/
mousemove:function (event) {
var self = this;
// Get coordinates relative to color picker center
var pos = self.widgetCoords(event);

// Set new HSL parameters
if (self.circleDrag) {
var hue = Math.atan2(pos.x, -pos.y) / 6.28;
if (hue < 0) hue += 1;
self.setHSL([hue, self.hsl[1], self.hsl[2]]);
}
else {
var sat = Math.max(0, Math.min(1, -(pos.x / self.square) + .5));
var lum = Math.max(0, Math.min(1, -(pos.y / self.square) + .5));
self.setHSL([self.hsl[0], sat, lum]);
}
return false;
},
/**
* Mouseup handler
*/
mouseup:function {
var self = this;
// Uncapture mouse
document.documentElement.removeEventListener("mousemove", self.mousemove);
document.documentElement.removeEventListener("mouseup", self.mouseup);
document.dragging = false;
},
/**
* Update the markers and styles
*/
updateDisplay:function {
var self = this;
// Markers
var angle = self.hsl[0] * 6.28;

self.dom.hMarker.style.left = Math.round(Math.sin(angle) * self.radius + self.width / 2) + "px";
self.dom.hMarker.style.top = Math.round(-Math.cos(angle) * self.radius + self.width / 2) + "px";

self.dom.slMarker.style.left = Math.round(self.square * (.5 - self.hsl[1]) + self.width / 2) + "px";
self.dom.slMarker.style.top = Math.round(self.square * (.5 - self.hsl[2]) + self.width / 2) + "px";

// Saturation/Luminance gradient
self.dom.color.style.backgroundColor = self.pack(self.HSLToRGB([self.hsl[0], 1, 0.5]));

// important
// 將獲取到的最新的color值emit出去
self.$emit("onChange",self.color);
//self.dom.targetElem.style.backgroundColor = self.color;
//self.dom.targetElem.style.color = self.hsl[2] > 0.5 ? "#000" : "#fff";

// Change linked value
// if (self.dom.targetElem.value && self.dom.targetElem.value != self.color) {
// self.dom.targetElem.value = self.color;
// }
},
/**
* Get absolute position of element
*/
absolutePosition:function (el) {
var self = this;
var r = { x: el.offsetLeft, y: el.offsetTop };
// Resolve relative to offsetParent
if (el.offsetParent) {
var tmp = self.absolutePosition(el.offsetParent);
r.x += tmp.x;
r.y += tmp.y;
}
return r;
},
/* Various color utility functions */
pack:function (rgb) {
var r = Math.round(rgb[0] * 255);
var g = Math.round(rgb[1] * 255);
var b = Math.round(rgb[2] * 255);
return "#" + (r < 16 ? "0" : "") + r.toString(16) +
(g < 16 ? "0" : "") + g.toString(16) +
(b < 16 ? "0" : "") + b.toString(16);
},
unpack:function (color) {
if (color.length == 7) {
return [parseInt("0x" + color.substring(1, 3)) / 255,
parseInt("0x" + color.substring(3, 5)) / 255,
parseInt("0x" + color.substring(5, 7)) / 255];
}
else if (color.length == 4) {
return [parseInt("0x" + color.substring(1, 2)) / 15,
parseInt("0x" + color.substring(2, 3)) / 15,
parseInt("0x" + color.substring(3, 4)) / 15];
}
},
HSLToRGB:function (hsl) {
var m1, m2, r, g, b;
var h = hsl[0], s = hsl[1], l = hsl[2];
m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s;
m1 = l * 2 - m2;
return [this.hueToRGB(m1, m2, h+0.33333),
this.hueToRGB(m1, m2, h),
this.hueToRGB(m1, m2, h-0.33333)];
},
hueToRGB:function (m1, m2, h) {
h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h);
if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
if (h * 2 < 1) return m2;
if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
return m1;
},
RGBToHSL:function (rgb) {
var min, max, delta, h, s, l;
var r = rgb[0], g = rgb[1], b = rgb[2];
min = Math.min(r, Math.min(g, b));
max = Math.max(r, Math.max(g, b));
delta = max - min;
l = (min + max) / 2;
s = 0;
if (l > 0 && l < 1) {
s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
}
h = 0;
if (delta > 0) {
if (max == r && max != g) h += (g - b) / delta;
if (max == g && max != b) h += (2 + (b - r) / delta);
if (max == b && max != r) h += (4 + (r - g) / delta);
h /= 6;
}
return [h, s, l];
}
}
}
</script>

<style lang="css" scoped>
.color-picker-container {
position: fixed;
display: none;

}
.color-picker-container.active{
display: block;
}
.color-picker-container * {
position: absolute;
cursor: crosshair;
}
.color-picker-container, .color-picker-container .wheel {
width: 195px;
height: 195px;
}
.color-picker-container .color, .color-picker-container .overlay {
top: 47px;
left: 47px;
width: 101px;
height: 101px;
}
.color-picker-container .wheel {
width: 195px;
height: 195px;
background: url(./images/wheel.png) no-repeat;
-webkit-background-size: 100%;
background-size: 100%;
}
.color-picker-container .overlay {
background: url(./images/mask.png) no-repeat;
-webkit-background-size: 100%;
background-size: 100%;
}
.color-picker-container .marker {
width: 17px;
height: 17px;
margin: -8px 0 0 -8px;
overflow: hidden;
background: url(./images/marker.png) no-repeat;
-webkit-background-size: 100%;
background-size: 100%;
}
</style>

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 達人科技 的精彩文章:

SpringBoot上傳任意文件功能的實現
Android與NativeC傳遞數據不正確問題
ArrayList的實現細節
Kotlin + Spring Boot 請求參數驗證

TAG:達人科技 |

您可能感興趣

顏色酷!Vetements x Reebok 全新聯名 Instapump Fury 曝光
讓男生羨慕的顏色?VaporMax 97 全新 「Metallic Cashmere」 配色
Deborah Brown 顏色的遊戲
顏色反轉,Virgil Abloh x Nike Air Max 90 「The Ten」 黑色版本曝光
New Balance 574 『Legacy of Grey』 灰色不是一個顏色
狂野顏色碰撞!Air Max Deluxe 「Enamel Green」 即將發售
給你顏色丨by Marc Majewski
ionic 顏色
iPhone 8plus什麼顏色好看?
大海有多少種顏色?Fifty Shades of Blue
蘋果新款iPhone 或有多種顏色 微軟取消發布Surface Phone
iPhone又要出新顏色,iPhone 6s Plus印度生產
Supreme和Nike 做了三個顏色的 AF1
Federico Pouso,用顏色展示美麗的的藝術家
給白丹寧來點顏色!Levi』s x Air Jordan 4「Gators」客制款有點帥!
你的口紅顏色暴露了什麼? | Beauty Tutorial
「python」colorama 模塊-改變控制台輸出文本的顏色
mac口紅314號是什麼顏色 mull it over適合黃皮嗎
「插畫」給你顏色,by Olga Shtonda!
光和顏色:與Daniel Dorsa交談