Entrada nativa de intervalo duplo
(muffinman.io)@stanko/dual-range-inputcombina dois inputs range HTML nativos para criar um slider de intervalo duplo, aproveitando as interações padrão e a acessibilidade do navegador- A implementação se concentra em cerca de 50 linhas de JavaScript para sincronizar os valores de entrada e em CSS, tornando-a mais simples do que abordagens tradicionais que recriam manualmente o arraste e a acessibilidade
- Os dois inputs têm
min,maxe largura atualizados de acordo com o ponto médio dos valores selecionados; ao clicar na trilha, o thumb mais próximo se move para esse valor - Como a trilha do input range é mais curta que a largura real do input, a largura do thumb é adicionada ao cálculo, e o padding do wrapper absorve a largura excedente
- O tema pode ser ajustado com variáveis CSS e gradient, permitindo sobrescrever a cor do intervalo selecionado, o tamanho do thumb, a cor da track etc.
Slider duplo feito com input range nativo
@stanko/dual-range-inputimplementa uma entrada de intervalo duplo colocando dois inputs range HTML lado a lado- Aqui, “nativo” não significa um único controle do navegador, mas sim que dois inputs range são usados para preservar as interações padrão e os recursos de acessibilidade do navegador
- A implementação consiste em cerca de 50 linhas de JavaScript para sincronizar os inputs e CSS para o acabamento visual
- O ponto de partida foi a necessidade de uma UI para ajustar os valores mínimo e máximo de parâmetros em uma ferramenta de desenho generativo
- Havia dois requisitos
- Usar input range HTML nativo
- Ao clicar na trilha, o thumb mais próximo entre os dois deve se mover para aquele valor
Sincronização de valores e tratamento de cliques
- Quando um dos dois inputs muda, a biblioteca calcula o ponto médio entre os dois valores selecionados
- Define os atributos
minemaxde cada input de acordo com o ponto médio - Também atualiza a largura dos dois inputs com base no ponto médio
- Define os atributos
- Como os inputs são redimensionados para se encontrarem no ponto médio, ao clicar entre os dois thumbs, o thumb mais próximo da posição do clique se move
- Se o número de steps entre os dois thumbs for ímpar, o input usado por último tem prioridade
Cálculos de CSS e estilização
- A trilha de um input range é mais curta que a largura total do input, e o navegador deixa espaço nas laterais para que o thumb não ultrapasse os limites
- Se a largura dos inputs for simplesmente dividida como 25% e 75%, a proporção real da trilha não fica correta
- A implementação adiciona
--dri-thumb-widthà largura de cada input e adiciona padding ao wrapper para acomodar a largura excedente
- A estilização usa os recursos de CSS do navegador para estilizar inputs range
- A track e o thumb são estilizados, e a parte central onde as duas tracks se encontram é tratada para não ter border radius
- Temas podem ser criados por meio de sobrescrita de variáveis CSS
- As principais variáveis incluem
--dri-height,--dri-thumb-width,--dri-thumb-color,--dri-track-color,--dri-track-filled-color,--dri-track-border-radiusetc.
- As principais variáveis incluem
- O intervalo selecionado é preenchido com CSS gradient
- A posição do gradient é definida pela variável
--dri-gradient-position - Quando a largura do input é atualizada no código, essa variável também é atualizada
- A posição do gradient é definida pela variável
- Essa implementação adota uma abordagem de primeiro aproveitar ao máximo os elementos nativos, em vez de recriar arraste e acessibilidade com uma biblioteca customizada
1 comentários
Comentários no Hacker News
Acho que esse tipo de slider deveria sempre permitir arrastar também a área central. Ou seja, ao pegar no meio, os dois manipuladores deveriam se mover juntos
Para referência, é assim que o Unity trata isso: https://docs.unity3d.com/StaticFiles/ScriptRefImages/EditorG...
“Sempre” talvez seja uma palavra um pouco forte demais
Sou o autor. Fico feliz de ver isso no HN
Vi que começaram a deixar issues e relatórios de bugs por aqui; já está tarde onde estou, então pretendo dar uma olhada amanhã
Criei isso porque precisava para trabalhos com imagens generativas, e prefiro arrastar o slider e ver como a imagem muda a digitar números
Tentei mantê-lo o mais minimalista possível
Hoje estou usando SwiftUI, onde é quase fácil demais criar componentes próprios. Mas, como o autor explicou, isso nem sempre é o melhor, e componentes nativos muitas vezes já são bem completos
Também testei o artigo no Firefox para iOS, que é um navegador meio peculiar, e funcionou bem. Muito bem feito
Fui testar e encontrei um bug na hora. Depois de arrastar o slider para 100 - 100, não dá para deixá-lo em 99 - 99
Também não dá para chegar lá a partir de 99 - 100, nem de 98 - 99. A única forma de chegar a 99 - 99 é puxar o limite inferior para menos de 98
Se, a partir de 98 - 99, você baixar para 97 - 99, aí dá para ir para 99 - 99
Esse bug pode acontecer em qualquer lugar; 99 - 99 só é o mais fácil de reproduzir por estar perto do fim do slider. Em geral, se você está em algum estado X - X e move uma das extremidades em 1 passo, não consegue arrastar a outra extremidade para dentro desse vão. Para fechar o intervalo, primeiro precisa arrastar a outra extremidade para mais longe
Obrigado pelo relatório, vou corrigir com certeza
Mas há outro bug visual. Se você começa em 23-25 e arrasta para 24-25, o manipulador direito em 25 se move alguns pixels. Quando você leva o manipulador esquerdo de volta para 23, o direito também volta
Legal! Sempre achei que inputs HTML precisavam de uma implementação de entrada de intervalo com dois valores, porque faz bastante sentido
Por exemplo, há casos de uso como “quero filtrar produtos que tenham no mínimo X e no máximo Y widgets”
Mas encontrei um bug no Firefox que gostaria de destacar. Toda vez que clico no manipulador de mínimo ou máximo, o valor muda um passo para cima ou para baixo
Se eu tento clicar exatamente no centro do manipulador, o valor não muda, mas se clico um pouco à esquerda a seleção diminui um passo, e se clico um pouco à direita ela aumenta
O comportamento esperado é que o valor só mude quando houver uma ação explícita de alteração, mantendo o botão pressionado e realmente movendo o ponteiro do mouse
O Firefox interpreta esse clique como se fosse um clique direto na trilha. Esta biblioteca não interfere nisso; é simplesmente o modo como o Firefox se comporta
É excelente que funcione pelo teclado. Funciona corretamente, então também dá para voltar mantendo Shift-Tab pressionado
Ficou muito bem feito, e agradeço por terem implementado corretamente essa interação, por menor que seja o detalhe
No design system da nossa empresa, um estagiário também criou uma prova de conceito com inputs lado a lado desse tipo, mas sempre havia pixels de um input pulando um pouco, e no fim não conseguimos deixar direito
Então um segundo estagiário propôs uma solução usando 2 inputs range sobrepostos
Toda vez que eu precisava de um input de intervalo, usava o slider do jQuery UI, e precisava adicionar jQuery e jQuery UI à página só por causa de um slider. Isso é muito bom
Edit: haveria possibilidade de fornecer previamente um arquivo JS comum pronto para uso, em vez de um módulo ESM?
"export default"no finalhttps://cdn.jsdelivr.net/npm/@stanko/dual-range-input@0.9.8/...
Não esqueça o CSS
https://cdn.jsdelivr.net/npm/@stanko/dual-range-input@0.9.8/...
Não sei se posso relatar bugs por aqui. Os manipuladores dos dois primeiros exemplos interceptam a interação por toque e impedem a rolagem. Os três exemplos seguintes não fazem isso
Como efeito colateral, não dá para arrastar para cima para ver o rótulo sob o dedo; a página rola e o rótulo continua debaixo do dedo
Fiquei curioso para saber qual navegador e sistema operacional você usa. Esta biblioteca usa inputs nativos, então não faz nada relacionado a bloquear rolagem
No meu celular iOS, a rolagem é bloqueada em todos os elementos
input[type=range], com ou sem estilo aplicado[1] https://github.com/Stanko/dual-range-input/issues
A parte de “nativo” é discutível. Dizem que a biblioteca usa dois inputs range nativos de HTML, preservando interações nativas e recursos de acessibilidade, mas meu critério é claro
Se precisa de JavaScript para funcionar como pretendido, então já não é nativo
Ainda assim, entendo a intenção do autor. Como ele combinou sliders comuns em vez de implementar um monte de divs movidas por JS, ficou muito mais próximo de uma solução nativa. Se não der para substituir o JavaScript por CSS inteligente, talvez seja o mais perto possível
Independentemente de ser nativo ou não, esse tipo de widget é muito útil quando disponível, e havia poucas implementações nessa área
Antes do atributo
popover, nem dava para abrir sem JavaScriptTambém há métodos nativos em JavaScript vanilla que vale diferenciar de bibliotecas que não usam nenhuma das ferramentas internas de validação do navegador, como validação de formulários
Eu estava procurando algo assim quando criei https://spodj.intermer.net/
Tive que usar React de um jeito meio desajeitado para obter a funcionalidade de que precisava, porque não sou bom em desenvolvimento frontend