Fillimi

Ne në thelb përdorim Zgjedhuesit e ngjyrave çdo ditë, pavarësisht nëse punojmë si dizajnerë duke krijuar logo dhe modele ose zhvillues softuerësh kur na duhet të zgjedhim një temë ngjyrash për projektin tonë të ri ose edhe thjesht kur përpiqemi të modifikojmë foton tuaj selfie në për t'u lëshuar në Instagram, kështu që gjithçka lidhet me përdorimin e një Zgjedhësi të ngjyrave, prandaj është shumë e rëndësishme të kuptoni se si të krijoni zgjedhësin tuaj të ngjyrave nga e para duke përdorur javascript-in vendas pa biblioteka të nevojshme.

Ne do të përdorim Codepen si redaktuesin e kodit në internet për ta bërë të mundur këtë tutorial pasi është i aksesueshëm nga të gjithë dhe shumë i lehtë për t'u përdorur.

Gjithashtu, të gjithë duhet të dinë një njohuri bazë të javascript, Html & CSS së bashku me klasat ES6 pasi ne do të përdorim sintaksën e klasës për të ndërtuar zgjedhësin e ngjyrave, ju mund t'i hidhni një sy tutorialit nga Këtu.

redaktori i kodit: Codepen.io

Ne gjithashtu do të zbatojmë një zvarritje dhe lëshim kur bëjmë zgjedhësin e ngjyrave, pasi tashmë e kam mbuluar atë në një tutorial të veçantë, mund ta shikoni "Këtu".

Tani, gjëja e parë që duhet marrë parasysh është struktura e elementeve HTML dhe stili CSS, pasi ne do të përdorim kanavacën për të dhënë zgjedhësin e ngjyrave, kështu që pjesa kryesore e rëndësishme për t'u fokusuar në këtë tutorial është ana e Javascript.

Struktura e projektit HTML:

<h2>Let's Create a Color Picker</h2>
<div class="container">
  <canvas id="color-picker"></canvas>
  <div class="info">
    <h3>Selected Color</h3> 
    <div class="selected"></div>
  </div>
</div>

Dhe stili CSS:

html, body {
  width: 100%;
  height: 100%;
  font-family: Oxygen, sans-serif;
  text-align: center;
}

.container {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

#color-picker {
  border: 3px solid rgba(15, 15, 15, 0.2);
}

.info {
  width: 12em;
  display: flex;
  margin-left: 4em;
  flex-direction: row;
  justify-content: space-between;
}

.selected {
  width: 50px;
  height: 50px;
  border-radius: 100%;
  border: 2px solid rgba(15, 15, 15, 0.2);
}

Për stilimin CSS ne në thelb po përdorim flexbox për të rreshtuar kanavacën e zgjedhësit të ngjyrave dhe ndarjen e informacionit në qendër të faqes së internetit dhe për t'i dhënë kanavacës një kufi, kështu që kur të japim zgjedhësin, të mund të shohim lehtësisht kufijtë se ku përfundojnë ngjyrat.

Sigurohuni që të zgjidhni Babel si opsion përpilues në Codepen javascript.

Vizatoni Zgjedhësin e ngjyrave

Për procesin e paraqitjes së gradientit të ngjyrave në mënyrë që të formojmë përfundimisht zgjedhësin e ngjyrave, ne duhet të përdorim WebGL Canvas API për vizatimin e ngjyrave 2d në kanavacë, me gjasë mund të përdorim API-në e kontekstit 2D për të dhënë lehtësisht gradientin e ngjyrave dhe të formojmë zgjedhësin e ngjyrave paleta.

Së pari, le të krijojmë Klasën Zgjedhëse që do të jetë përgjegjëse për vizatimin dhe dëgjimin e ngjarjeve.

class Picker {
  constructor(target, width, height) {
    this.target = target;
    this.width = width;
    this.height = height;
    this.target.width = width;
    this.target.height = height;
    //Get context 
    this.context = this.target.getContext("2d");
    //Circle (Color Selector Circle)
    this.pickerCircle = { x: 10, y: 10, width: 7, height: 7 };

    draw() {
      //Drawing Here
    }
}

Për colorPicker, na duhen aty parametra elementi synues i kanavacës, gjerësia e kanavacës dhe lartësia e tij në mënyrë që të mund të krijojmë dhe të japim në kanavacë, ne thjesht i ruajmë ato vlera në klasën Picker si variabla lokale në konstruktor, marrim konteksti i paraqitjes nga kanavacja duke e kaluar atë parametrin 2d dhe krijoni objektin zgjedhësRrethi pozicionin dhe dimensionin e tij (x, y, gjerësia, lartësia) ku rrethit i duhet vetëm një rreze në vend të gjerësisë dhe lartësisë, por ne do ta përdorim në atë mënyrë për ta bërë atë është më e lehtë për ne të punojmë më vonë.

Tani krijoni një metodë ndërtimi e cila do të kujdeset për kthimine gradientit të ngjyrave të qiellzës ColorPicker dhe rrethit zgjedhës (përzgjedhës ngjyrash).

...
build() {
//Create a Gradient Color (colors change on the width)
let gradient = this.context.createLinearGradient(0, 0, this.width, 0);
//Add Color Stops to the Gradient (from 0 to 1)
gradient.addColorStop(0, "rgb(255, 0, 0)");
gradient.addColorStop(0.15, "rgb(255, 0, 255)");
gradient.addColorStop(0.33, "rgb(0, 0, 255)");
gradient.addColorStop(0.49, "rgb(0, 255, 255)");
gradient.addColorStop(0.67, "rgb(0, 255, 0)");
gradient.addColorStop(0.84, "rgb(255, 255, 0)");
gradient.addColorStop(1, "rgb(255, 0, 0)");
//Add color picker colors (red, green, blue, yellow...)
//Render the Color Gradient from the 0's position to the full width and height
this.context.fillStyle = gradient; ///, set it's style to be the color gradient
this.context.fillRect(0, 0, this.width, this.height); ///< render it
}
...

Krijojmë një gradient në gjerësi (që do të thotë se ngjyrat do të ndryshojnë në dimensionin e gjerësisë), pastaj i shtojmë ngjyra të ndryshme sepse një gradient merr një vlerë nga 0 në 1, së fundi vendosim stilin e mbushjes në gradientin e krijuar dhe ne paraqiteni atë në kanavacë duke filluar nga 0x, 0y dhe gjerësia dhe lartësia e plotë.

Gradientët e mësipërm nuk janë të mjaftueshëm sepse i mungojnë ngjyrat e bardha dhe të zeza në qiellzën e ngjyrave, kështu që në këtë rast, ne duhet të shtojmë një gradient të ri në lartësi që përfaqëson ngjyrat e bardha dhe të zeza.

...
build() {
...
//Apply black and white (on the height dimension instead of the width)
gradient = this.context.createLinearGradient(0, 0, 0, this.height);
//We have two colors so 0, 0.5 and 1 needs to be used.
gradient.addColorStop(0, "rgba(255, 255, 255, 1)");
gradient.addColorStop(0.5, "rgba(255, 255, 255, 0)");
gradient.addColorStop(0.5, "rgba(0, 0, 0, 0)");
gradient.addColorStop(1, "rgba(0, 0, 0, 1)");
//set style and render it.
this.context.fillStyle = gradient;
this.context.fillRect(0, 0, this.width, this.height);
...

Ne gjithashtu duhet ta përshkruajmë përzgjedhësin e rrethit zgjedhës si një rreth të vogël në zgjedhësin e ngjyrave, sigurohuni që ta përshkruajmë atë të fundit, në mënyrë që të shkojë mbi gradientin e ngjyrës, pasi kanavacë jepet nga poshtë lart (nga e para në të fundit).

...
build() { 
...
//Circle 
this.context.beginPath();
//Arc renders a circle depending on the position, radius and arc
this.context.arc(this.pickerCircle.x, this.pickerCircle.y, this.pickerCircle.width, 0, Math.PI * 2);
//Render it in black but not fill (only stroke)
this.context.strokeStyle = "black";
//Render the circle stroke and close the rendering path
this.context.stroke();
this.context.closePath();
}

Rrethi ka nevojë për tre parametra kryesorë pozicionin x, y të rrethit dhe rreze të cilat në këtë rast përdorim gjerësinë që e kemi regjistruar më herët dhe harkun e fillojmë nga 0 deri në PI * 2 që do të thotë një rreth i plotë, nëse e dini bazat e matematikës kjo duhet të jetë shumë e lehtë për ju.

Le ta japim atë, të thërrasim metodën e ndërtimit në tërheqje dhe të krijojmë një shembull të klasës zgjedhëse.

//Create an instance passing it the canvas, width and height
let picker = new Picker(document.getElementById("color-picker"), 250, 220);

//Draw 
picker.draw();

Hidhni një sy në skedën e shikimit paraprak dhe duhet të shihni që qiellza e zgjedhësit të ngjyrave jepet për ju dhe të gjitha vlerat e mundshme të ngjyrave me rrethin zgjedhës të ulur në këndin e sipërm majtas, tani duhet të shtojmë dëgjuesit e ngjarjeve për të dëgjuar për zvarritje dhe lëshim të rrethoni dhe më pas klikoni për të zgjedhur një ngjyrë.

Zgjedhësi i ngjyrave

Pra, për zgjedhjen e ngjyrave, ne do të shtojmë dy mënyra të ndryshme për zgjedhësin e ngjyrave, ose tërhiqni dhe lëshoni rrethin zgjedhës në një pjesë specifike të ngjyrave ose klikoni në qiellzën e ngjyrave dhe rrethi duhet të ndryshojë pozicionin e tij në pozicionin e synuar.

Le të shtojmë një metodë të re përgjegjëse për dëgjimin e ngjarjeve që do të kemi tre ngjarje kryesore (onMouseDown, onMouseMovedhe onMouseUp).

...
listenForEvents() {
    let isMouseDown = false;
    const onMouseDown = (e) => {
      let currentX = e.clientX - this.target.offsetLeft;
      let currentY = e.clientY - this.target.offsetTop;
      if(currentY > this.pickerCircle.y && currentY < this.pickerCircle.y + this.pickerCircle.width && currentX > this.pickerCircle.x && currentX < this.pickerCircle.x + this.pickerCircle.width) {
        isMouseDown = true;
      } else {
        this.pickerCircle.x = currentX;
        this.pickerCircle.y = currentY;
      }
    }
    const onMouseMove = (e) => {
      if(isMouseDown) {
       let currentX = e.clientX - this.target.offsetLeft;
       let currentY = e.clientY - this.target.offsetTop;
        this.pickerCircle.x = currentX;
        this.pickerCircle.y = currentY;
      }
    }
    const onMouseUp = () => {
      isMouseDown = false;
    }
    //Register 
    this.target.addEventListener("mousedown", onMouseDown);
    this.target.addEventListener("mousemove", onMouseMove);
    //Mouse up on the Document     
    document.addEventListener("mouseup", onMouseUp);
  }

Dëgjuesi OnMouseDown ne fillimisht marrim pozicionin aktual të mausit x dhe y në lidhje me kanavacën duke zbritur zhvendosjen e elementit të kanavacës, më pas kontrollojmë se miu po klikon në rrethin zgjedhës duke përdorur pozicionin e tij x, y dhe rrezen e tij (gjerësia ose lartësia). Deklarata e kontrollit është mjaft e drejtpërdrejtë, përndryshe, nëse miu është duke klikuar diku tjetër në vend të rrethit, kështu që thjesht ndryshoni pozicionin e rrethit zgjedhës në pozicionin e klikuar.

OnMouseMove ne kontrollojmë nëse miu është poshtë në elementin e djathtë duke përdorur variablin isMouseDown që kemi aktivizuar në dëgjuesin onMouseDown, atëherë thjesht bëjmë që pozicioni i rrethit të ndjekë pozicionin relativ të miut.

OnMouseUp, i cili regjistrohet në dokument si dëgjues i ngjarjeve për ngjarjen e miut Up, ndryshe nga të tjerët që janë regjistruar në kanavacë (elementi i synuar), ne e vendosëm isMouseDown në false pasi nuk është më poshtë.

Tani na duhet vetëm të regjistrojmë ngjarjet në konstruktor në mënyrë që ai të regjistrohet dhe të lidhet me elementët e duhur sa herë që krijojmë shembullin zgjedhës.

...
constructor() {
...
this.listenForEvents();
...
}
...

Tani përpiquni të klikoni mbi kanavacë ose tërhiqni rrethin e zgjedhësit rreth tij që duhet t'ju ndjekë dhe të arrini kudo që t'i thoni, shumë bukur!

Rrethi zgjedhës po lëviz, por nuk përdoret siç duhet, prandaj le të shtojmë pamjen paraprake të ngjyrave për të përputhur ngjyrën e zgjedhur aktualisht.

Ngjyra e zgjedhur

Duke harruar ngjyrën e zgjedhur, duhet t'i tregojmë kontekstit të kanavacës për të na dhënë të dhënat e pikselit të treguara nga rrethi në qiellzën e zgjedhësit, le të shtojmë një metodë për këtë në klasën Picker.

...
getPickedColor() {
    //Get the Image Data (pixel value) pointed by the circle by using it's current position
    //getImageData returns an object that has the pixel data (1, 1) is for getting only one pixel.
	let imageData = this.context.getImageData(this.pickerCircle.x, this.pickerCircle.y, 1, 1);
    //Return back an object has the RGB color value of the pointed pixel.
    //The data is an array holds the red, green, blue and alpha values of the current pixel 
	return { r: imageData.data[0], g: imageData.data[1], b: imageData.data[2] };
}
...

metoda e mësipërme është përgjegjëse për dhënien e vlerës së ngjyrës RGB të treguar nga rrethi në kanavacë duke përdorur metodën e kontekstit getImageData (mund të dhënat e pikselave sa të duash, por ne duhet të marrim vetëm vlerën RGB me një piksel).

Kur zgjedhësi i rrethit lëviz (ndryshon pozicionin e tij) vetëm klasa e zgjedhësit e di për të, por ne duhet ta eksportojmë atë si një ngjarje, në mënyrë që të mund të kryejmë një kthim kthimi (funksioni ynë specifik) sa herë që rrethi ndryshon pozicionin e tij duke e kaluar atë aktualen e zgjedhur ngjyra, kështu që ne duhet të përdorim një ngjarje të kthimit të thirrjes.

onChange(callback) {
  //Save Callback function reference on the class
  this.onChangeCallback = callback;
}
//And add it as an event listener on the mouseMove (when ever it moves the callback gets executed)
listenForEvents() {
...
  //Mouse move event on the canvas, call callback passing it the current color 
  this.target.addEventListener("mousemove", () => this.onChangeCallback(this.getPickedColor()));
...

Tani mund ta quajmë metodën onChange duke i kaluar asaj një thirrje mbrapa e cila do të marrë ngjyrën e zgjedhur sa herë që ndryshon pozicioni i rrethit.

Le të dëgjojmë për onChange dhe të ndryshojmë ngjyrën e paraafishimit të sfondit të synuar në ngjyrën e zgjedhur aktualisht.

//On Circle position change 
picker.onChange((color) => {
  //Get the preview DOM element
  let selected = document.getElementsByClassName("selected")[0];
  //Change it's backagroundColor to the current color (rgb CSS function)
  selected.style.backgroundColor = `rgb(${color.r}, ${color.g}, ${color.b})`;
});
//NOTE: Remeber we are return a color object that has a three properties(Red, Green and Blue)

Testi Përfundimtar, tani duhet të jeni në gjendje të përdorni zgjedhësin e ngjyrave sipas dëshirës duke zvarritur/lëshuar dhe zgjedhur një ngjyrë specifike nga Canvas dhe do të merrni ngjyrën që ju tregohet në rrethin Preview.

Zgjedhësi i fundit i ngjyrës:



Ç'pritet më tej

Nga këtu, pasi i dini bazat e mënyrës se si funksionojnë në të vërtetë zgjedhësit e ngjyrave, mund të krijoni kombinime të ndryshme të ngjyrave dhe të shtoni më shumë veçori te zgjedhësi, si p.sh. futja e vlerës së ngjyrës në Hexose HSLose formate të tjera ngjyrash të disponueshme.

Mos ngurroni të ndani shembujt tuaj me ne.