e.pageX位置绝对

时间:2015-12-21 21:18:37

标签: javascript html css

我正在使用this custom JavaScript range slider。我将包装器(position:absolute; left: 60px; )设置为以下内容:

dragger

然后,当我拖动dragger's时,它与光标的位置不同。 dragger位置有点偏离。

我怎样才能让updateDragger() function跟随光标,无论父母在哪里?

我认为相关代码位于e = e || window.event; var pos = !isVertical ? e.pageX : e.pageY; if (!pos) { pos = !isVertical ? e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft : e.clientY + document.body.scrollTop + document.documentElement.scrollTop; } if (down && pos >= rangeOffset && pos <= (rangeOffset + rangeWidth)) { dragger.style[!isVertical ? 'left' : 'top'] = (pos - rangeOffset - (draggerWidth / 2)) + 'px'; cachePosition = Math.round(((pos - rangeOffset) / rangeWidth) * 100); config.drag(cachePosition); }

function rangeSlider(elem, config) {

  var html = document.documentElement,
    range = document.createElement('div'),
    dragger = document.createElement('span'),
    down = false,
    rangeWidth, rangeOffset, draggerWidth, cachePosition;

  var defaults = {
    value: 0, // set default value on initiation from `0` to `100` (percentage based)
    vertical: false, // vertical or horizontal?
    rangeClass: "", // add extra custom class for the range slider track
    draggerClass: "", // add extra custom class for the range slider dragger
    drag: function(v) { /* console.log(v); */ } // function to return the range slider value into something
  };

  for (var i in defaults) {
    if (typeof config[i] == "undefined") config[i] = defaults[i];
  }

  function addEventTo(el, ev, fn) {
    if (el.addEventListener) {
      el.addEventListener(ev, fn, false);
    } else if (el.attachEvent) {
      el.attachEvent('on' + ev, fn);
    } else {
      el['on' + ev] = fn;
    }
  }

  var isVertical = config.vertical;

  elem.className = (elem.className + ' range-slider ' + (isVertical ? 'range-slider-vertical' : 'range-slider-horizontal')).replace(/^ +/, "");
  range.className = ('range-slider-track ' + config.rangeClass).replace(/ +$/, "");
  dragger.className = ('dragger ' + config.draggerClass).replace(/ +$/, "");

  addEventTo(range, "mousedown", function(e) {
    html.className = (html.className + ' no-select').replace(/^ +/, "");
    rangeWidth = range[!isVertical ? 'offsetWidth' : 'offsetHeight'];
    rangeOffset = range[!isVertical ? 'offsetLeft' : 'offsetTop'];
    draggerWidth = dragger[!isVertical ? 'offsetWidth' : 'offsetHeight'];
    down = true;
    updateDragger(e);
    return false;
  });

  addEventTo(document, "mousemove", function(e) {
    updateDragger(e);
  });

  addEventTo(document, "mouseup", function(e) {
    html.className = html.className.replace(/(^| )no-select( |$)/g, "");
    down = false;
  });

  addEventTo(window, "resize", function(e) {
    var woh = dragger[!isVertical ? 'offsetWidth' : 'offsetHeight'];
    dragger.style[!isVertical ? 'left' : 'top'] = (((cachePosition / 100) * range[!isVertical ? 'offsetWidth' : 'offsetHeight']) - (woh / 2)) + 'px';
    down = false;
  });

  function updateDragger(e) {
    e = e || window.event;
    var pos = !isVertical ? e.pageX : e.pageY;
    if (!pos) {
      pos = !isVertical ? e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft : e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
    }
    if (down && pos >= rangeOffset && pos <= (rangeOffset + rangeWidth)) {
      dragger.style[!isVertical ? 'left' : 'top'] = (pos - rangeOffset - (draggerWidth / 2)) + 'px';
      cachePosition = Math.round(((pos - rangeOffset) / rangeWidth) * 100);
      config.drag(cachePosition);
    }
  }

  function initDragger() {
    var woh = dragger[!isVertical ? 'offsetWidth' : 'offsetHeight'];
    cachePosition = ((config.value / 100) * range[!isVertical ? 'offsetWidth' : 'offsetHeight']);
    dragger.style[!isVertical ? 'left' : 'top'] = (cachePosition - (woh / 2)) + 'px';
    config.drag(config.value);
  }

  range.appendChild(dragger);
  elem.appendChild(range);

  initDragger();

}





rangeSlider(document.getElementById('range-slider-1'), {
  value: 30,
  drag: function(v) {
    document.getElementById('result-area').innerHTML = v + '%';
  }
});

JSFiddle

.range-slider {
  width: 50%;
  position: absolute;
  top: 50px;
  left: 60px;
}
.range-slider-track {
  width: auto;
  height: 20px;
  margin: 0 auto;
  position: relative;
}
.range-slider-track:before {
  content: "";
  display: block;
  position: absolute;
  top: 9px;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: black;
}
.range-slider-track .dragger {
  display: block;
  width: 10px;
  height: inherit;
  position: relative;
  z-index: 2;
  background-color: red;
  cursor: inherit;
  /* opacity:.6; */
}
.range-slider-vertical {
  display: inline-block;
  vertical-align: middle;
  margin: 0 1em 1em 0;
}
.range-slider-vertical .range-slider-track {
  cursor: n-resize;
  width: 20px;
  height: 100px;
}
.range-slider-vertical .range-slider-track:before {
  top: 0;
  right: auto;
  left: 9px;
  width: 2px;
  height: 100%;
}
.range-slider-vertical .range-slider-track .dragger {
  width: inherit;
  height: 10px;
}
.no-select {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
<div id="range-slider-1"></div>
<p id="result-area"></p>
{{1}}

2 个答案:

答案 0 :(得分:0)

问题出在你的css代码中。

left属性/值正在抛弃dragger元素。的 See here 即可。删除后,拖动器将按预期运行。

也许这是一个错误,我会report it to the repo(似乎你已经拥有)并避免使用position: absoluteleftright属性直到解决。

答案 1 :(得分:0)

您只需要获取容器元素#range-slider-1的位置,即传递给底部rangeSlider函数的元素。如果你有,你可以从pos函数中的updateDragger变量中减去位置偏移量。

我已添加getElemPos以获取元素位置。 现在,您可以将position left更改为您想要的内容。

这是一个例子,这只适用于水平滑块而不适用于垂直滑块,但我相信你现在可以轻松地自己解决这个问题了。 ;)

// This will help to get an elements position.
function getElemPos (elem) {
  var xPos = 0,
      yPos = 0;

  while (elem) {
    xPos += (elem.offsetLeft - elem.scrollLeft + elem.clientLeft);
    yPos += (elem.offsetTop - elem.scrollTop + elem.clientTop);
    elem = elem.offsetParent;
  }

  return { x: xPos, y: yPos };
}

function rangeSlider(elem, config) {

  var html = document.documentElement,
      range = document.createElement('div'),
      dragger = document.createElement('span'),
      down = false,
      rangeWidth, rangeOffset, draggerWidth, cachePosition;

  var defaults = {
    value: 0, // set default value on initiation from `0` to `100` (percentage based)
    vertical: false, // vertical or horizontal?
    rangeClass: "", // add extra custom class for the range slider track
    draggerClass: "", // add extra custom class for the range slider dragger
    drag: function(v) { /* console.log(v); */ } // function to return the range slider value into something
  };

  for (var i in defaults) {
    if (typeof config[i] == "undefined") config[i] = defaults[i];
  }

  function addEventTo(el, ev, fn) {
    if (el.addEventListener) {
      el.addEventListener(ev, fn, false);
    } else if (el.attachEvent) {
      el.attachEvent('on' + ev, fn);
    } else {
      el['on' + ev] = fn;
    }
  }

  var isVertical = config.vertical;

  elem.className = (elem.className + ' range-slider ' + (isVertical ? 'range-slider-vertical' : 'range-slider-horizontal')).replace(/^ +/, "");
  range.className = ('range-slider-track ' + config.rangeClass).replace(/ +$/, "");
  dragger.className = ('dragger ' + config.draggerClass).replace(/ +$/, "");

  addEventTo(range, "mousedown", function(e) {
    html.className = (html.className + ' no-select').replace(/^ +/, "");
    rangeWidth = range[!isVertical ? 'offsetWidth' : 'offsetHeight'];
    rangeOffset = range[!isVertical ? 'offsetLeft' : 'offsetTop'];
    draggerWidth = dragger[!isVertical ? 'offsetWidth' : 'offsetHeight'];
    down = true;
    updateDragger(e);
    return false;
  });

  addEventTo(document, "mousemove", function(e) {
    updateDragger(e);
  });

  addEventTo(document, "mouseup", function(e) {
    html.className = html.className.replace(/(^| )no-select( |$)/g, "");
    down = false;
  });

  addEventTo(window, "resize", function(e) {
    var woh = dragger[!isVertical ? 'offsetWidth' : 'offsetHeight'];
    dragger.style[!isVertical ? 'left' : 'top'] = (((cachePosition / 100) * range[!isVertical ? 'offsetWidth' : 'offsetHeight']) - (woh / 2)) + 'px';
    down = false;
  });

  var elemXY = getElemPos(elem);

  function updateDragger(e) {
    e = e || window.event;
    var pos = !isVertical ? e.pageX : e.pageY;

    if (!pos) {
      pos = !isVertical ? (e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft) : e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
    }

    // Here you can substract the #range-slider-1 x postion from the mouse position.
    pos -= elemXY.x;

    if (down && pos >= rangeOffset && pos <= (rangeOffset + rangeWidth)) {
      dragger.style[!isVertical ? 'left' : 'top'] = (pos - rangeOffset - (draggerWidth / 2)) + 'px';
      cachePosition = Math.round(((pos - rangeOffset) / rangeWidth) * 100);
      config.drag(cachePosition);
    }
  }

  function initDragger() {
    var woh = dragger[!isVertical ? 'offsetWidth' : 'offsetHeight'];
    cachePosition = ((config.value / 100) * range[!isVertical ? 'offsetWidth' : 'offsetHeight']);
    dragger.style[!isVertical ? 'left' : 'top'] = (cachePosition - (woh / 2)) + 'px';
    config.drag(config.value);
  }

  range.appendChild(dragger);
  elem.appendChild(range);

  initDragger();

}

rangeSlider(document.getElementById('range-slider-1'), {
  value: 30,
  drag: function(v) {
    document.getElementById('result-area').innerHTML = v + '%';
  }
});
.range-slider {
  width: 50%;
  position: absolute;
  top: 50px;
  left: 25%;
}

.range-slider-track {
  width: auto;
  height: 20px;
  margin: 0 auto;
  position: relative;
  cursor: pointer;
}

.range-slider-track:before {
  content: "";
  display: block;
  position: absolute;
  top: 9px;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: black;
}

.range-slider-track .dragger {
  display: block;
  width: 10px;
  height: inherit;
  position: relative;
  z-index: 2;
  background-color: red;
  cursor: inherit;
  /* opacity:.6; */
}

.range-slider-vertical {
  display: inline-block;
  vertical-align: middle;
  margin: 0 1em 1em 0;
}

.range-slider-vertical .range-slider-track {
  cursor: n-resize;
  width: 20px;
  height: 100px;
}

.range-slider-vertical .range-slider-track:before {
  top: 0;
  right: auto;
  left: 9px;
  width: 2px;
  height: 100%;
}

.range-slider-vertical .range-slider-track .dragger {
  width: inherit;
  height: 10px;
}

.no-select {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
<div id="range-slider-1"></div>
<p id="result-area"></p>