Javascript emulate CSS snap scroll with pointer-events

I have the following code which can swipe child element left and right. This works well.

Is there a way I could implement snap effect with this somehow with pointermove? So it behaves like CSS snap scroll (you drag slightly and you can see next / previous item entering, before swipe actually happens).

I dont want to use CSS snap scroll because I cannot detect scrollend event (on Safari for start) so I cannot detect on which child I am currenty (I need this so I can show / hide previous / next buttons, numbering etc)

var wrap = document.querySelector('.wrap'),
  touchstartX,
  touchendX


wrap.addEventListener('pointerdown', startHorizSwipeDirection);
document.addEventListener('pointerup', endHorizSwipeDirection);

function startHorizSwipeDirection(e) {
  touchstartX = e.clientX;
}

function endHorizSwipeDirection(e) {
  touchendX = e.clientX;
  checkHorizSwipeDirection()
}

function checkHorizSwipeDirection() {

  if (touchendX < touchstartX - 100) {
    //left
    nextHorizMedia();
  }
  if (touchendX > touchstartX + 100) {
    //right
    previousHorizMedia();
  }
}

function nextHorizMedia() {

  var active_id = parseInt(wrap.getAttribute('data-active-id'), 10),
    len = wrap.querySelectorAll('.child').length

  if (active_id >= len - 1) {
    console.log('end')
    return false;
  }

  var width = wrap.querySelector('.child').offsetWidth

  var transform = wrap.style.transform.replace(/[^-?d.]/g, '')
  var value
  if (transform) value = parseInt(transform, 10)
  else value = 0;

  value -= width;
  active_id++;

  wrap.setAttribute('data-active-id', active_id)

  wrap.style.transform = "translateX(" + value + "px)";



}

function previousHorizMedia() {

  var active_id = parseInt(wrap.getAttribute('data-active-id'), 10),
    len = wrap.querySelectorAll('.child').length
 
  if (active_id <= 0) {
    return false;
  }

  var width = wrap.querySelector('.child').offsetWidth

  var transform = wrap.style.transform.replace(/[^-?d.]/g, '')
  var value
  if (transform) value = parseInt(transform, 10)
  else value = 0;

  value += width;
  active_id--;

  wrap.setAttribute('data-active-id', active_id)

  wrap.style.transform = "translateX(" + value + "px)";


}
.parent {
  width: 300px;
  height: 100px;
  overflow: hidden;
}

.wrap {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  transition: transform 0.3s;
}

.child {
  width: 300px;
  height: 100px;
  font-size: 30px;
  color: #fff;
  background: #ccc;
  flex-shrink: 0;
  text-align: center;
  user-select: none;
}

.child[data-id="0"] {
  background: red;
}

.child[data-id="1"] {
  background: blue;
}

.child[data-id="2"] {
  background: green;
}

.child[data-id="3"] {
  background: #ccc;
}
<div class="parent">
  <div class="wrap" data-active-id="0">
    <div class="child" data-id="0">0</div>
    <div class="child" data-id="1">1</div>
    <div class="child" data-id="2">2</div>
    <div class="child" data-id="3">3</div>
  </div>
</div>