原生JS封装拖动验证滑块的实现代码示例


Posted in Javascript onJune 01, 2020

前言

星期六闲着没事,就想着写写原生js玩玩,在网上看了几个效果后决定做这个效果,并且使用了prototype和eventEmitter封装成了库。

最终效果

原生JS封装拖动验证滑块的实现代码示例 

分析

看到这个效果我们首先应该想到和拖动有关的api: onmousedown, onmousemove, onmouseup

其次要支持用户传入放置这个组件的dom元素和完成的回调事件。

最终如何使用?

我们先来看下使用方式,再来决定我们怎么编写这个库

原生JS封装拖动验证滑块的实现代码示例

具体使用就是这样的,我们还想用户能通过import等方式使用,所以我们就要支持esMoudule的导入方式。

编写库的整体初始框架

(function () {
 // =================代码块1=========================================
 var root = (typeof self == 'object' && self.self == self && self) ||
  (typeof global == 'object' && global.global == global && global) ||
  this || {}; 
 var util = {
  extend: function (target) {
   for (var i = 1, len = arguments.length; i < len; i++) {
    for (var prop in arguments[i]) {
     if (arguments[i].hasOwnProperty(prop)) {
      target[prop] = arguments[i][prop]
     }
    }
   }
   return target
  },
  isValidListener: function (listener) {
   if (typeof listener === 'function') {
    return true
   } else if (listener && typeof listener === 'object') {
    return util.isValidListener(listener.listener)
   } else {
    return false
   }
  },
  addCSS: function (cssText) {
   var style = document.createElement('style'), //创建一个style元素
    head = document.head || document.getElementsByTagName('head')[0]; //获取head元素
   style.type = 'text/css'; //这里必须显示设置style元素的type属性为text/css,否则在ie中不起作用
   if (style.styleSheet) { //IE
    var func = function () {
     try { //防止IE中stylesheet数量超过限制而发生错误
      style.styleSheet.cssText = cssText;
     } catch (e) {

     }
    }
    //如果当前styleSheet还不能用,则放到异步中则行
    if (style.styleSheet.disabled) {
     setTimeout(func, 10);
    } else {
     func();
    }
   } else { //w3c
    //w3c浏览器中只要创建文本节点插入到style元素中就行了
    var textNode = document.createTextNode(cssText);
    style.appendChild(textNode);
   }
   head.appendChild(style); //把创建的style元素插入到head中
  },
  indexOf: function (array, item) {
   if (array.indexOf) {
    return array.indexOf(item);
   } else {
    var result = -1;
    for (var i = 0, len = array.length; i < len; i++) {
     if (array[i] === item) {
      result = i;
      break;
     }
    }
    return result;
   }
  }
 }
 
 function EventEmitter() {
  this._events = {}
 }

 EventEmitter.prototype.on = function (eventName, listener) {
  if (!eventName || !listener) return;
  if (!util.isValidListener(listener)) {
   throw new TypeError('listener must be a function');
  }
  var events = this._events;
  var listeners = events[eventName] = events[eventName] || [];
  var listenerIsWrapped = typeof listener === 'object';
  // 不重复添加事件
  if (util.indexOf(listeners, listener) === -1) {
   listeners.push(listenerIsWrapped ? listener : {
    listener: listener,
    once: false
   });
  }
  return this;
 };
 EventEmitter.prototype.once = function (eventName, listener) {
  return this.on(eventName, {
   listener: listener,
   once: true
  })
 };
 EventEmitter.prototype.off = function (eventName, listener) {
  var listeners = this._events[eventName];
  if (!listeners) return;
  var index;
  for (var i = 0, len = listeners.length; i < len; i++) {
   if (listeners[i] && listeners[i].listener === listener) {
    index = i;
    break;
   }
  }
  if (typeof index !== 'undefined') {
   listeners.splice(index, 1, null)
  }
  return this;
 };
 EventEmitter.prototype.emit = function (eventName, args) {
  var listeners = this._events[eventName];
  if (!listeners) return;
  for (var i = 0; i < listeners.length; i++) {
   var listener = listeners[i];
   if (listener) {
    listener.listener.apply(this, args || []);
    if (listener.once) {
     this.off(eventName, listener.listener)
    }
   }
  }
  return this;
 };
 
 // =================代码块2=========================================
 function SliderTools(options) {
  this.options = util.extend({}, this.constructor.defaultOptions, options)
  this.init();
  this.bindEvents();
  this.diffX = 0;
  this.flag = false;//是否拖动到最右侧
 }

 SliderTools.defaultOptions = {
  el: document.body //默认放到body里
 };
 
 var proto = SliderTools.prototype = new EventEmitter();//SliderTools继承emitter
 
 proto.constructor = SliderTools;//修正构造器

 proto.init = function () {
  this.createSlider();//创建插件所需要的dom元素
  this.getElements();//获取创建好的元素
 }
 
 // =================代码块3=========================================
 if (typeof exports != 'undefined' && !exports.nodeType) {
  if (typeof module != 'undefined' && !module.nodeType && module.exports) {
   exports = module.exports = SliderTools;
  }
  exports.SliderTools = SliderTools;
 } else {
  root.SliderTools = SliderTools;
 }
}());

代码块1是在判断是在浏览器环境还是nodeJS环境,方便代码三后期使用, 代码块2声明了一个对象 SliderTools ,将用户传进来的 option 和默认的 defaultOption 进行合并

编写核心函数1(创建dom和css)

proto.createSlider = function () {
 this.options.el.innerHTML = '<div id="slider"><div class="drag_bg"></div><div class="drag_text" onselectstart="return false;" unselectable="on">拖动滑块验证</div><div class="handler handler_bg"></div></div>';//像指定元素中放置插件的dom元素
 util.addCSS('ul,li {list-style: none;} a {text-decoration: none;} .wrap {width: 300px;height: 350px;text-align: center;margin: 150px auto;}.inner {padding: 15px;} .clearfix {overflow: hidden;_zoom: 1;} .none {display: none;} #slider {position:relative;background-color: #e8e8e8;width: 300px;height: 34px;line-height: 34px;text-align: center;} #slider .handler {position: absolute;top: 0px;left: 0px;width: 40px;height: 32px;border: 1px solid #ccc;cursor: move;} .handler_bg {background: #fff url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTEyNTVEMURGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTEyNTVEMUNGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MTc5NzNmZS02OTQxLTQyOTYtYTIwNi02NDI2YTNkOWU5YmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+YiRG4AAAALFJREFUeNpi/P//PwMlgImBQkA9A+bOnfsIiBOxKcInh+yCaCDuByoswaIOpxwjciACFegBqZ1AvBSIS5OTk/8TkmNEjwWgQiUgtQuIjwAxUF3yX3xyGIEIFLwHpKyAWB+I1xGSwxULIGf9A7mQkBwTlhBXAFLHgPgqEAcTkmNCU6AL9d8WII4HOvk3ITkWJAXWUMlOoGQHmsE45ViQ2KuBuASoYC4Wf+OUYxz6mQkgwAAN9mIrUReCXgAAAABJRU5ErkJggg==") no-repeat center;} .handler_ok_bg {background: #fff url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDlBRDI3NjVGMkQ2MTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDlBRDI3NjRGMkQ2MTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDphNWEzMWNhMC1hYmViLTQxNWEtYTEwZS04Y2U5NzRlN2Q4YTEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+k+sHwwAAASZJREFUeNpi/P//PwMyKD8uZw+kUoDYEYgloMIvgHg/EM/ptHx0EFk9I8wAoEZ+IDUPiIMY8IN1QJwENOgj3ACo5gNAbMBAHLgAxA4gQ5igAnNJ0MwAVTsX7IKyY7L2UNuJAf+AmAmJ78AEDTBiwGYg5gbifCSxFCZoaBMCy4A4GOjnH0D6DpK4IxNSVIHAfSDOAeLraJrjgJp/AwPbHMhejiQnwYRmUzNQ4VQgDQqXK0ia/0I17wJiPmQNTNBEAgMlQIWiQA2vgWw7QppBekGxsAjIiEUSBNnsBDWEAY9mEFgMMgBk00E0iZtA7AHEctDQ58MRuA6wlLgGFMoMpIG1QFeGwAIxGZo8GUhIysmwQGSAZgwHaEZhICIzOaBkJkqyM0CAAQDGx279Jf50AAAAAABJRU5ErkJggg==") no-repeat center;}#slider .drag_bg {background-color: #7ac23c; height: 34px;width: 0px;} #slider .drag_text {position: absolute; top: 0px;width: 300px;-moz-user-select: none;-webkit-user-select: none;user-select: none;-o-user-select: none;-ms-user-select: none; }.unselect {-moz-user-select: none;-webkit-user-select: none; -ms-user-select: none;}.slide_ok {color: #fff;}')//像页面里add新的样式
}
proto.getElements = function () {
 this.slider = document.querySelector('#slider');
 this.drag_bg = document.querySelector('.drag_bg');
 this.handler = document.querySelector('.handler');
}

编写核心函数2(绑定事件)

proto.bindEvents = function () {
 var self = this;
 self.handler.onmousedown = function (e) {
  self.diffX = e.clientX - self.handler.offsetLeft;
  util.setClassName(self.slider, 'unselect'); //禁止选择样式
  document.onmousemove = function (e) {
   let deltaX = e.clientX - self.diffX;
   if (deltaX >= self.slider.offsetWidth - self.handler.offsetWidth) { //拖动到了最右侧
    deltaX = self.slider.offsetWidth - self.handler.offsetWidth;
    self.flag = true;
   } else if (deltaX <= 0) {
    deltaX = 0;
    self.flag = false;
   } else {
    self.flag = false;
   }
   util.setInlineStyle([self.handler], 'left', deltaX + 'px');
   util.setInlineStyle([self.drag_bg], 'width', deltaX + 'px');
  }
  document.onmouseup = function (e) {
   util.setClassName(self.slider, '')
   if (self.flag) {
    util.setClassName(self.slider, 'slide_ok') //拖动完成后的样式
    util.addClass(self.handler, 'handler_ok_bg')////拖动完成后的样式
    self.handler.onmousedown = null //防止拖动完成后再次拖动
    self.emit('complete')//emit通知使用者的回调事件
   } else {
    util.setInlineStyle([self.handler], 'left', 0 + 'px');
    util.setInlineStyle([self.drag_bg], 'width', 0 + 'px');
   }
   document.onmousemove = null;
   document.onmouseup = null;
  }
 }
}

添加工具方法(核心函数2中用到的)

var util = {
 // ...初始框架里的那部分
 setClassName(selector, className) {
  selector.className = className;
 },
 addClass(selector, className) {
  selector.classList.add(className);
 },
 setInlineStyle(selector, attr, content) {
  let length = selector.length;
  for (let i = 0; i < length; i++) {
   selector[i].style[attr] = content;
  }
 },
}

最终完整可运行代码

(function () {
 var root = (typeof self == 'object' && self.self == self && self) ||
  (typeof global == 'object' && global.global == global && global) ||
  this || {};
 var util = {
  extend: function (target) {
   for (var i = 1, len = arguments.length; i < len; i++) {
    for (var prop in arguments[i]) {
     if (arguments[i].hasOwnProperty(prop)) {
      target[prop] = arguments[i][prop]
     }
    }
   }
   return target
  },
  setClassName(selector, className) {
   selector.className = className;
  },
  addClass(selector, className) {
   selector.classList.add(className);
  },
  setInlineStyle(selector, attr, content) {
   let length = selector.length;
   for (let i = 0; i < length; i++) {
    selector[i].style[attr] = content;
   }
  },
  isValidListener: function (listener) {
   if (typeof listener === 'function') {
    return true
   } else if (listener && typeof listener === 'object') {
    return util.isValidListener(listener.listener)
   } else {
    return false
   }
  },
  addCSS: function (cssText) {
   var style = document.createElement('style'), //创建一个style元素
    head = document.head || document.getElementsByTagName('head')[0]; //获取head元素
   style.type = 'text/css'; //这里必须显示设置style元素的type属性为text/css,否则在ie中不起作用
   if (style.styleSheet) { //IE
    var func = function () {
     try { //防止IE中stylesheet数量超过限制而发生错误
      style.styleSheet.cssText = cssText;
     } catch (e) {

     }
    }
    //如果当前styleSheet还不能用,则放到异步中则行
    if (style.styleSheet.disabled) {
     setTimeout(func, 10);
    } else {
     func();
    }
   } else { //w3c
    //w3c浏览器中只要创建文本节点插入到style元素中就行了
    var textNode = document.createTextNode(cssText);
    style.appendChild(textNode);
   }
   head.appendChild(style); //把创建的style元素插入到head中
  },
  indexOf: function (array, item) {
   if (array.indexOf) {
    return array.indexOf(item);
   } else {
    var result = -1;
    for (var i = 0, len = array.length; i < len; i++) {
     if (array[i] === item) {
      result = i;
      break;
     }
    }
    return result;
   }
  }
 }

 function EventEmitter() {
  this._events = {}
 }

 EventEmitter.prototype.on = function (eventName, listener) {
  if (!eventName || !listener) return;

  if (!util.isValidListener(listener)) {
   throw new TypeError('listener must be a function');
  }

  var events = this._events;
  var listeners = events[eventName] = events[eventName] || [];
  var listenerIsWrapped = typeof listener === 'object';

  // 不重复添加事件
  if (util.indexOf(listeners, listener) === -1) {
   listeners.push(listenerIsWrapped ? listener : {
    listener: listener,
    once: false
   });
  }

  return this;
 };
 EventEmitter.prototype.once = function (eventName, listener) {
  return this.on(eventName, {
   listener: listener,
   once: true
  })
 };
 EventEmitter.prototype.off = function (eventName, listener) {
  var listeners = this._events[eventName];
  if (!listeners) return;

  var index;
  for (var i = 0, len = listeners.length; i < len; i++) {
   if (listeners[i] && listeners[i].listener === listener) {
    index = i;
    break;
   }
  }

  if (typeof index !== 'undefined') {
   listeners.splice(index, 1, null)
  }

  return this;
 };
 EventEmitter.prototype.emit = function (eventName, args) {
  var listeners = this._events[eventName];
  if (!listeners) return;

  for (var i = 0; i < listeners.length; i++) {
   var listener = listeners[i];
   if (listener) {
    listener.listener.apply(this, args || []);
    if (listener.once) {
     this.off(eventName, listener.listener)
    }
   }
  }
  return this;
 };

 function SliderTools(options) {
  this.options = util.extend({}, this.constructor.defaultOptions, options)
  this.init();
  this.bindEvents();
  this.diffX = 0;
  this.flag = false;
 }

 SliderTools.VERSION = '1.0.0';

 SliderTools.defaultOptions = {
  el: document.body
 };

 var proto = SliderTools.prototype = new EventEmitter();

 proto.constructor = SliderTools;

 proto.init = function () {
  this.createSlider();
  this.getElements();
 }

 proto.createSlider = function () {
  this.options.el.innerHTML = '<div id="slider"><div class="drag_bg"></div><div class="drag_text" onselectstart="return false;" unselectable="on">拖动滑块验证</div><div class="handler handler_bg"></div></div>';
  util.addCSS('ul, li { list-style: none; } a { text-decoration: none; } .wrap { width: 300px; height: 350px; text-align: center; margin: 150px auto; } .inner { padding: 15px; } .clearfix { overflow: hidden; _zoom: 1; } .none { display: none; } #slider { position: relative; background-color: #e8e8e8; width: 300px; height: 34px; line-height: 34px; text-align: center; } #slider .handler { position: absolute; top: 0px; left: 0px; width: 40px; height: 32px; border: 1px solid #ccc; cursor: move;} .handler_bg { background: #fff url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTEyNTVEMURGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTEyNTVEMUNGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MTc5NzNmZS02OTQxLTQyOTYtYTIwNi02NDI2YTNkOWU5YmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+YiRG4AAAALFJREFUeNpi/P//PwMlgImBQkA9A+bOnfsIiBOxKcInh+yCaCDuByoswaIOpxwjciACFegBqZ1AvBSIS5OTk/8TkmNEjwWgQiUgtQuIjwAxUF3yX3xyGIEIFLwHpKyAWB+I1xGSwxULIGf9A7mQkBwTlhBXAFLHgPgqEAcTkmNCU6AL9d8WII4HOvk3ITkWJAXWUMlOoGQHmsE45ViQ2KuBuASoYC4Wf+OUYxz6mQkgwAAN9mIrUReCXgAAAABJRU5ErkJggg==") no-repeat center; } .handler_ok_bg { background: #fff url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDlBRDI3NjVGMkQ2MTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDlBRDI3NjRGMkQ2MTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDphNWEzMWNhMC1hYmViLTQxNWEtYTEwZS04Y2U5NzRlN2Q4YTEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+k+sHwwAAASZJREFUeNpi/P//PwMyKD8uZw+kUoDYEYgloMIvgHg/EM/ptHx0EFk9I8wAoEZ+IDUPiIMY8IN1QJwENOgj3ACo5gNAbMBAHLgAxA4gQ5igAnNJ0MwAVTsX7IKyY7L2UNuJAf+AmAmJ78AEDTBiwGYg5gbifCSxFCZoaBMCy4A4GOjnH0D6DpK4IxNSVIHAfSDOAeLraJrjgJp/AwPbHMhejiQnwYRmUzNQ4VQgDQqXK0ia/0I17wJiPmQNTNBEAgMlQIWiQA2vgWw7QppBekGxsAjIiEUSBNnsBDWEAY9mEFgMMgBk00E0iZtA7AHEctDQ58MRuA6wlLgGFMoMpIG1QFeGwAIxGZo8GUhIysmwQGSAZgwHaEZhICIzOaBkJkqyM0CAAQDGx279Jf50AAAAAABJRU5ErkJggg==") no-repeat center; } #slider .drag_bg { background-color: #7ac23c; height: 34px; width: 0px;  } #slider .drag_text { position: absolute; top: 0px; width: 300px; -moz-user-select: none; -webkit-user-select: none; user-select: none; -o-user-select: none; -ms-user-select: none; } .unselect { -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; } .slide_ok { color: #fff; }')
 }
 proto.getElements = function () {
  this.slider = document.querySelector('#slider');
  this.drag_bg = document.querySelector('.drag_bg');
  this.handler = document.querySelector('.handler');
 }
 proto.bindEvents = function () {
  var self = this;
  self.handler.onmousedown = function (e) {
   self.diffX = e.clientX - self.handler.offsetLeft;
   util.setClassName(self.slider, 'unselect');
   document.onmousemove = function (e) {
    let deltaX = e.clientX - self.diffX;
    if (deltaX >= self.slider.offsetWidth - self.handler.offsetWidth) {
     deltaX = self.slider.offsetWidth - self.handler.offsetWidth;
     self.flag = true;
    } else if (deltaX <= 0) {
     deltaX = 0;
     self.flag = false;
    } else {
     self.flag = false;
    }
    util.setInlineStyle([self.handler], 'left', deltaX + 'px');
    util.setInlineStyle([self.drag_bg], 'width', deltaX + 'px');
   }
   document.onmouseup = function (e) {
    util.setClassName(self.slider, '')
    if (self.flag) {
     util.setClassName(self.slider, 'slide_ok')
     util.addClass(self.handler, 'handler_ok_bg')
     self.handler.onmousedown = null
     self.emit('complete')
    } else {
     util.setInlineStyle([self.handler], 'left', 0 + 'px');
     util.setInlineStyle([self.drag_bg], 'width', 0 + 'px');
    }
    document.onmousemove = null;
    document.onmouseup = null;
   }
  }
 }
 if (typeof exports != 'undefined' && !exports.nodeType) {
  if (typeof module != 'undefined' && !module.nodeType && module.exports) {
   exports = module.exports = SliderTools;
  }
  exports.SliderTools = SliderTools;
 } else {
  root.SliderTools = SliderTools;
 }
}());

let slider = new SliderTools();
slider.on('complete',() => {
 alert('验证完成');
})

结语

参考资料

到此这篇关于原生JS封装拖动验证滑块的实现代码示例的文章就介绍到这了,更多相关JS 拖动验证滑块内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
简单的Jquery遮罩层代码实例
Nov 14 Javascript
浅析JavaScript中的隐式类型转换
Dec 05 Javascript
一个奇葩的最短的 IE 版本判断JS脚本
May 28 Javascript
jQuery ajax serialize() 方法使用示例
Nov 02 Javascript
JS IOS/iPhone的Safari浏览器不兼容Javascript中的Date()问题如何解决
Nov 11 Javascript
jQuery纵向导航菜单效果实现方法
Dec 19 Javascript
js数组去重的hash方法
Dec 22 Javascript
完美实现js选项卡切换效果(二)
Mar 08 Javascript
深入理解AngularJS中的ng-bind-html指令
Mar 27 Javascript
vue动画效果实现方法示例
Mar 18 Javascript
JavaScript实现轮播图效果代码实例
Sep 28 Javascript
微信小程序实现音乐播放器
Nov 20 Javascript
jQuery cookie的公共方法封装和使用示例
Jun 01 #jQuery
webpack安装配置与常见使用过程详解(结合vue)
Jun 01 #Javascript
使用Vue+Django+Ant Design做一个留言评论模块的示例代码
Jun 01 #Javascript
el-table树形表格表单验证(列表生成序号)
May 31 #Javascript
vue如何在用户要关闭当前网页时弹出提示的实现
May 31 #Javascript
使用原生JS实现滚轮翻页效果的示例代码
May 31 #Javascript
24个ES6方法解决JS实际开发问题(小结)
May 31 #Javascript
You might like
php之static静态属性与静态方法实例分析
2015/07/30 PHP
Yii框架实现邮箱激活的方法【数字签名】
2016/10/18 PHP
PHP中的use关键字及文件的加载详解
2016/11/28 PHP
php判断是否为ajax请求的方法
2016/11/29 PHP
PHP开启目录引索+fancyindex漂亮目录浏览带搜索功能
2019/09/23 PHP
CSS中简写属性要注意TRouBLe的顺序问题(避免踩坑)
2021/03/09 HTML / CSS
textarea的value是html文件源代码,存成html文件的代码
2007/04/20 Javascript
js replace替换所有匹配的字符串
2014/02/13 Javascript
jquery中each遍历对象和数组示例
2014/08/05 Javascript
jQuery选择器源码解读(七):elementMatcher函数
2015/03/31 Javascript
教你使用javascript简单写一个页面模板引擎
2015/05/05 Javascript
js实现prototype扩展的方法(字符串,日期,数组扩展)
2016/01/14 Javascript
使用JS批量选中功能实现更改数据库中的status状态值(批量展示)
2016/11/22 Javascript
深入浅出webpack之externals的使用
2017/12/04 Javascript
JS实现在文本指定位置插入内容的简单示例
2017/12/22 Javascript
mpvue中配置vuex并持久化到本地Storage图文教程解析
2018/03/15 Javascript
JavaScript+Canvas实现彩色图片转换成黑白图片的方法分析
2018/07/31 Javascript
浅谈JavaScript 代码简洁之道
2019/01/09 Javascript
vue项目中实现缓存的最佳方案详解
2019/07/11 Javascript
Node.js 在本地生成日志文件的方法
2020/02/07 Javascript
js实现拖拽元素选择和删除
2020/08/25 Javascript
[47:45]DOTA2-DPC中国联赛 正赛 Phoenix vs Dragon BO3 第一场 2月26日
2021/03/11 DOTA
python数据结构树和二叉树简介
2014/04/29 Python
Python中还原JavaScript的escape函数编码后字符串的方法
2014/08/22 Python
基于python的Tkinter实现一个简易计算器
2015/12/31 Python
Django学习笔记之ORM基础教程
2018/03/27 Python
Python基于递归算法实现的汉诺塔与Fibonacci数列示例
2018/04/18 Python
Python协程操作之gevent(yield阻塞,greenlet),协程实现多任务(有规律的交替协作执行)用法详解
2019/10/14 Python
基于virtualenv创建python虚拟环境过程图解
2020/03/30 Python
解决Jupyter notebook中.py与.ipynb文件的import问题
2020/04/21 Python
巧用 CSS3的webkit-box-reflect 倒影实现各类动效
2021/03/05 HTML / CSS
用缩写的指针比较"if(p)" 检查空指针是否可靠?如果空指针的内部表达不是0会怎么样?
2014/01/05 面试题
周年庆典答谢词
2015/01/20 职场文书
劳动者解除劳动合同通知书
2015/04/16 职场文书
《领导干部从政道德启示录》学习心得体会
2016/01/20 职场文书
MySQL数据库 任意ip连接方法
2022/05/20 MySQL