<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>custom GUI: slider</title> </head> <body> <style> body { overscroll-behavior: none; } .handle{ touch-action: none; } </style> <button id="togglevh1">vertical or horizontal toggle</button> <br><br> <input type="range" id="islider1" value="0"> <br><br> <div class="slider" id="slider1"></div> <br> <input type="range" id="islider2" value="0"> <br><br> <div class="slider" id="slider2"></div> <style> .slider { background-color: grey; } .slider > .handle { position: relative; background-color: lightgrey; } </style> <script> slider1.vertical_or_horizontal = false setup_slider(slider1) islider1.max=slider1.max slider2.vertical_or_horizontal = true setup_slider(slider2) islider2.max=slider2.max togglevh1.onclick = function(){ slider1.vertical_or_horizontal = !slider1.vertical_or_horizontal; setup_slider(slider1) } islider1.oninput = function(){ slider1.value_set( this.value ) } islider2.oninput = function(){ slider2.value_set( this.value ) } slider1.input_event = function(slider){ islider1.value = slider.value_get } slider2.input_event = function(slider){ islider2.value = slider.value_get } function setup_slider(slider){ let value_initial=0 if(slider.value_get!=undefined) value_initial=slider.value_get slider.value_set = set slider.innerHTML = '<div class="handle"></div>' let handle = slider.handle = slider.querySelector('.handle') let vertical_or_horizontal = slider.vertical_or_horizontal // related let top_or_left = slider.top_or_left = vertical_or_horizontal?'top':'left' let left_or_top = slider.left_or_top = vertical_or_horizontal?'left':'top' let height_or_width = vertical_or_horizontal?'height':'width' let width_or_height = vertical_or_horizontal?'width':'height' // setup slider DOM let height=200 let size=height/10 slider.style[height_or_width]=height+'px' slider.style[width_or_height]='50px' //size+'px' handle.style[height_or_width]='40px' //size+'px' handle.style[width_or_height]='100%' slider.max=height-40//slider.style.height-handle.style.height//height-size handle.style[left_or_top]='0px' // setup "drag&drop" / "grab-move" /* adapted from: https://plnkr.co/edit/nfeuFthe9CWbPVoe?p=preview&preview https://javascript.info/pointer-events */ let clientY_or_clientX = vertical_or_horizontal?'clientY':'clientX' let offsetHeight_or_offsetWidth = vertical_or_horizontal?'offsetHeight':'offsetWidth' let shiftY handle.onpointerdown = function(event) { event.preventDefault() shiftY = event[clientY_or_clientX] - handle.getBoundingClientRect()[top_or_left] // events handle.setPointerCapture(event.pointerId) handle.onpointermove = handle_move_event handle.onpointerup = function(event){ handle.onpointermove = null } } function handle_move_event(event){ // get let value = event[clientY_or_clientX] - shiftY - slider.getBoundingClientRect()[top_or_left] set(value) } function set(value){ // clamp if (value < 0) { value = 0 } let value_max = slider[offsetHeight_or_offsetWidth] - handle[offsetHeight_or_offsetWidth] if (value > value_max) { value = value_max } // set handle.style[top_or_left]=value+'px' slider.value_get=value if(slider.input_event)slider.input_event(slider) } set(value_initial) } </script> <script src="/web/show-source.js"></script> </body> </html>