Como construir um componente slider de intervalo no React a partir do zero usando apenas <div> e <span>

Neste artigo, construiremos um componente slider da faixa React passo a passo usando apenas <div>. Vamos ativá-lo com suporte ao toque.

O que você pode fazer com um pedaço de cerca de 50 div?

Construa um controle deslizante a partir do zero. Se isso parece interessante, siga em frente.

A saída final será semelhante à animação abaixo.

Por favor, note que eu desenvolvi este componente como um exercício de ensino para os meus alunos do curso ReactJS – Beyond the Basics no Udemy , por isso pode ter alguns casos de limites (que eu vou corrigir como e quando encontrados).

Você pode usar um controle de intervalo HTML5 e personalizá-lo. Mas eu queria ter uma abordagem diferente e construir algo do zero. E o resultado é o que você vê aqui.

Nosso componente slider será composto pelos três elementos abaixo:

  • Uma faixa de controle deslizante
  • Os controles reais do controle deslizante
  • O intervalo de seleção atual

Definindo o estado para nosso componente

Vamos começar definindo nosso estado. Estou mostrando apenas a parte importante do código. Para o código-fonte completo, por favor, consulte o link no final do artigo.

 state = { 
slots: 24,
começar: 0,
fim: 10,
labelMode: "mid", // mid, long
}

O estado contém as seguintes propriedades.

  • slots: Total de slots a serem sorteados (neste caso eu estou usando como um seletor de tempo, então ele terá slots de 24 horas)
  • start: o valor inicial da seleção
  • end: o valor final da seleção
  • labelMode: atualmente não utilizado. Mas pode ser usado para personalizar a renderização do rótulo de escala.

A parte de retorno do método render

Vamos agora dar uma olhada na parte de retorno do método render. O método render () será composto lentamente de pequenos pedaços de funcionalidade.

 Retorna ( 
<div>
<h2> Reagir Slider </ h2>
<div className = "example-1">
<div className = "slider-container">
<div className = "escala do controle deslizante">
{escala}
</ div>
<div className = "slider">
{slider}
</ div>
<div className = "slider-selected-scale">
{currentScale}
</ div>
</ div>
</ div>
</ div>
);

Para quem lê no celular, a imagem abaixo pode ser útil, pois às vezes o Medium quebra a formatação do código.

Se você der uma olhada no código, existem apenas três partes importantes:

  • variável de escala
  • variável deslizante
  • variável currentScale

As três variáveis ??acima serão responsáveis ??por renderizar as partes corretas do controle deslizante geral.

Dissecando o método render ()

Vamos inicializar algumas variáveis. A scale , o slider e o currentScale JSX serão criados dentro do loop for definido abaixo.

 render () { 
let scale = [];
let slider = [];
let currentScale = [];
let minThumb = null;
deixe maxThumb = null
 ..... // resto do código 
}

Crie o JSX para a variável 'scale'

Criar o JSX para a variável de escala é bem simples. Nós apenas percorremos o valor dos slots no estado e enviamos um <div> para a matriz de escala com a classe CSS necessária para estilização.

A condição if garante que apenas imprimimos o rótulo para i = 0, i = 12 ou i = 24 (tipo de intervalo médio). Por favor, sinta-se livre para personalizar isso.

 para (let i = 0; i <= this.state.slots; i ++) { 
let label = "";

if (i == 0 || i == 12 || i == 24) {
label = i;
}

scale.push (
<div
key = {i}
className = "slot-scale">
{rótulo}
</ div>
);

Aqui está o código em formato de imagem:

Crie o JSX para a variável 'currentScale'

Vamos continuar com o mesmo loop for e criar o JSX 'currentScale'. Ainda estamos dentro do mesmo loop, então cerca de 24 divs serão criados de acordo com o valor no valor this.state.slots.

O currentScale tem uma classe de 'slot-scale-selected'.

 let currentLabel = ""; 

if (i === this.state.start || i === this.state.end) {
currentLabel = i;
}

currentScale.push (
<div
key = {i}
className = "slot-scale-selected">
{currentLabel}
</ div>
);

O código é bem parecido com o JSX 'scale' que criamos.

Crie o JSX para a variável 'slider'

Vamos escrever uma função para renderizar o 'slider' jsx. O controle deslizante precisa de dois polegares, um para min e um para max.

Vamos primeiro inicializar a variável thumb dependendo do valor 'i'. Se 'i' é o mesmo que this.state.start, então definimos a variável minThumb. Senão, se o valor de 'i' for o mesmo que this.state.end, então inicializamos a variável maxThumb.

 if (i === this.state.start) { 
minThumb = <this.MinSlider />
} else if (i === this.state.end) {
maxThumb = <this.MaxSlider />
} outro {
minThumb = null;
maxThumb = null;
}

Crie o JSX para o 'slider'

O código importante aqui é o evento dragover. Isso é necessário para que a queda de HTML funcione corretamente.

 deixe lineClass = "linha"; 

if (i> = this.state.start && i <this.state.end) {
lineClass + = "selecionado na linha";
}
slider.push (
<div
data-slot = {i}
onDragOver = {this.onDragOver}
onTouchMove = {this.onDragOver}
onTouchEnd = {this.onDrop}
onDrop = {this.onDrop}
key = {i}
className = "slot">
<div data-slot = {i} className = {lineClass} />
<span className = "scale-mark"> </ span>
{minThumb}
{maxThumb}
</ div>
);

A variável deslizante precisa de duas partes adicionais de recursos para representar o min e o polegar max no controle deslizante.

O slider JSX possui manipuladores de eventos adicionais para lidar com o evento drop event / touchend. Vamos dar uma olhada nos manipuladores de eventos em breve.

O 'lineClass' estilos / processa a linha no controle deslizante, e a classe 'line-selected' estiliza o intervalo atualmente selecionado.

Vamos agora escrever a função MinSlider e MaxSlider fora do método render.

A função MinSlider () para renderizar o thumb min

Vamos dar uma olhada no código. Os suportes importantes são os eventos relacionados ao arrastar e ao atributo arrastável. O atributo arrastável tornará esse elemento arrastável.

Também estamos adicionando o manipulador de eventos de toque. Consulte o link na parte inferior do artigo para adicionar o polyfill de suporte ao toque para a API do HTML5.

 MinSlider = () => { 
Retorna (
<div data-slider = "min"
onDragStart = {this.onDragStart}
onTouchStart = {this.onDragStart}
class = "slider-thumb slider-thumb-min"> arrastável
</ div>
);
}

A função MaxSlider () para renderizar o thumb min

O MaxSlider é quase o mesmo que o MinSlider, exceto os dados e o className.

 MaxSlider = () => { 
Retorna (
<div data-slider = "max"
onDragStart = {this.onDragStart}
onTouchStart = {this.onDragStart}
class = "slider-thumb slider-thumb-max"> arrastável
</ div>
);
}

A imagem de código é dada abaixo para referência.

Manipulação de eventos

Vamos agora olhar para os manipuladores de eventos de arrastar / tocar definidos dentro de nosso <div> para controlar o movimento do elemento deslizante.

arraste sobre:

O evento dragover é necessário para suportar a zona de recebimento ao usar a API de arrastar / soltar HTML5. A única coisa que precisamos fazer aqui é invocar o preventDefault no objeto de evento.

 onDragOver = (e) => { 
e.preventDefault ();
}

dragstart:

O dragstart nos permite armazenar qual slider está sendo arrastado. Por favor, note que eu não estou usando o objeto dataTransfer aqui, mas simplesmente usando uma variável de instância para armazenar isso.

 onDragStart = (e) => { 
let slider = e.target.dataset.slider;
this.sliderType = controle deslizante;
}

O valor de e.target.dataset.slider é “min” ou “max”, indicando qual slider está sendo arrastado.

ondrop:

O evento ondrop captura onde o polegar está sendo descartado (em qual escala).

Este é o fluxo importante no evento ondrop:

  • Agarre a fonte (se min / max polegar)
  • Pegue o slot (onde a queda acontece)
  • Validações
  • Atualize o slot (no estado)
  • Redefina o sliderType.
 onDrop = (e, target) => { 
deixe source = this.sliderType;
let slot = Number (e.target.dataset.slot);

if (isNaN (slot)) retorna;

if (fonte === "min") {
if (slot> = this.state.end) retorna;
this.setState ({
início: slot
}, () => {
console.log (this.state);
})
} else if (fonte === "max") {
if (slot <= this.state.start) retorna;
this.setState ({
end: slot
}, () => {
console.log (this.state);
})
}
this.sliderType = nulo;
}

O código-fonte completo e a demonstração podem ser vistos aqui http://jsbin.com/remodat/edit?output

Como estou usando recursos de arrastar e soltar HTML5 para adicionar suporte ao toque, adicione essa referência de polyfill ao arquivo html.

Bernardo-Castilho / dragdroptouch
dragdroptouch – Polyfill que permite o suporte a arrastar e soltar HTML5 em dispositivos móveis (touch). github.com

Todos

  • Extraia a lógica para uma classe Component separada
  • Teste e adicione customização.

História

  • 21 de maio de 2018 – Primeiro lançamento

PS: Esse componente é resultado de uma tentativa de codificação muito rápida. Isso será refatorado.

Promoção : Se você gostaria de apoiar nosso currículo de código aberto em 12 a 20 semanas, então aqui está um cupom especial de 10 dólares para leitores médios para o meu próximo curso ao vivo ReactJS-Beyond no udemy (MEDIUM_500 é o código de cupom , que já está marcado no URL acima)