可拖拽组件slider.js使用方法详解

基于 mithril.js ,javascript ,scss写一个可拖动的滑块组件,供大家参考,具体内容如下

问题描述:

需求需要实现一个可拖动的滑块组件,但是又不能用UI框架,只好自己动手写一个了。 废话不多说,直接上代码。

技术要求:

需要有mithril.js,javascript,scss技术基础。

js及页面代码。

var m = require("mithril");
require('./slider.scss');
import slider from './slider';

let obj = {
 colorWidth: 0,  // 已拖拽长度
 clickOpen: false,  // 是否开启拖拽
 sliderDom: '',  // 绑定的灰条dom
 colorDom: '',  // 绑定的有色条dom
 radiusDom: '',  // 绑定的圆点dom
 moveEmentRect: null, // 获取灰条dom参数
 Percentage: 0,  // 百分比

 minWidth: 0, // 拖动区间下限
 maxWidth: 0, // 拖动区间上限
 sliderCallback: null, // 参数回调
 node: [0, 25, 50, 75, 100], // 节点数及占比

 // 初始化数据
 initslider:function(){
 obj.sliderDom = document.getElementsByClassName('slider-body')[0];  // 允许进行开始拖拽的元素
 obj.colorDom = document.getElementsByClassName('slider-section')[0];  // 允许进行开始拖拽的元素
 obj.radiusDom = document.getElementsByClassName('slider-radius-body')[0]; // 允许进行开始拖拽的元素
 obj.moveEmentRect = obj.sliderDom.getBoundingClientRect();   // 获取拖拽父元素的宽度
 obj.maxWidth = obj.moveEmentRect.width;
 },
 // 处理宽度值域
 handleWidth:function(EV){
 if (EV <= obj.minWidth) {
  return obj.minWidth;
 } else if (EV >= obj.maxWidth) {
  return obj.maxWidth;
 } else {
  return EV;
 }
 },
 // 鼠标点击 拖动开始
 getMousedown:function(e){
 if (e.target === obj.sliderDom || e.target === obj.colorDom || e.target === obj.radiusDom) { // 判断是否是可点击拖拽的元素
  obj.clickOpen = true;         // 打开拖拽状态
  let Width = e.clientX - obj.moveEmentRect.left;      // 计算拖拽距离
  obj.colorWidth = this.handleWidth(Width);      // 处理拖拽距离转化为长度
  console.log(obj.colorWidth, '拖动开始')
  this.sliderCallback && this.sliderCallback({
  colorWidth : this.getPercentage(),       // 将数据回传页面
  })
 }
 },
 // 拖动中
 getMoveWidth:function(e){
 if (obj.clickOpen) {
  let moveX = e.clientX - obj.moveEmentRect.left;
  obj.colorWidth = this.handleWidth(moveX);
  console.log(obj.colorWidth, '拖动中')
  this.sliderCallback && this.sliderCallback({
  colorWidth : this.getPercentage(),       // 将数据回传页面
  })
 }
 },
 // 鼠标松开 拖动结束
 getmouseUp:function(){
 obj.clickOpen = false;
 console.log('拖动结束')
 },
 // 绑定到body上,实现在组件外面可以拖拽
 getBodyMouse: function(){
 let body = document.querySelector('body');
 body.onmousemove = function(e){
  obj.getMoveWidth(e); // 在body上拖拽组件
 };
 body.onmouseup = function(e){
  obj.getmouseUp(e);  // 在body上拖拽结束时关闭可拖拽状态
  obj.onmouseout();  // 在body上结束拖拽时隐藏百分比
 }
 },
 // 计算拖动的百分比
 getPercentage: function () {
 let _P = (Number(obj.colorWidth) / Number(obj.maxWidth)).toFixed(2);
 this.Percentage = Math.floor((Number(_P || 0) * 100));
 return Number(_P);
 },
 // 鼠标移入显示百分比
 onmouseover:function(){
 let _S = document.getElementsByClassName('slider-percentage')[0];
 _S.style.display = 'block';
 },
 // 鼠标移除隐藏百分比
 onmouseout:function(){
 let _S = document.getElementsByClassName('slider-percentage')[0];
 _S.style.display = 'none';
 },
 // 清除数据
 closemode: function () {
 obj.colorWidth = 0;  // 已拖拽长度
 obj.clickOpen = false;  // 是否开启拖拽
 obj.sliderDom = '';  // 绑定的灰条dom
 obj.colorDom = '';  // 绑定的有色条dom
 obj.radiusDom = '';  // 绑定的圆点dom
 obj.moveEmentRect = null; // 获取灰条dom参数
 obj.Percentage = 0;  // 百分比

 obj.minWidth = 0;
 obj.maxWidth = 0;
 obj.sliderCallback = null; // 参数回调
 },
 // 百分比选择
 getNodePer:function () {
 return obj.node.map((item) => {
  return m('div',{class:'slider-node', style: `left: ${item}%`, onclick: function(){
  obj.getNodeData(item);
  }},[

  ])
 })
 },
 getNodeData:function(item){
 obj.colorWidth = Number(obj.maxWidth) * (item / 100);
 this.sliderCallback && this.sliderCallback({
  colorWidth : this.getPercentage(), // 将数据回传页面
 });
 },
}

export default {
 oninit: function (vnode) {

 },
 oncreate: function (vnode) {
 obj.sliderCallback = vnode.attrs.cb;
 obj.initslider();
 obj.onmouseout();
 obj.getBodyMouse();
 },
 view: function (vnode) {
 return m('div', {class: 'slider'}, [
  m('div',{class:"slider-body",onmousedown:function(e){
  obj.getMousedown(e);
  },onmousemove:function(e){
  obj.getMoveWidth(e);
  },onmouseup:function(e){
  obj.getmouseUp(e);
  }},[
  m('div',{class:"slider-section", style:`width: ${obj.colorWidth}px`},[
   m('div',{class:"slider-radius",onmouseover:function(){
   obj.onmouseover();
   },onmouseout:function(){
   obj.onmouseout();
   }},[
   m('div',{class:"slider-radius-body"},[])
   ]),
   m('div',{class:"slider-percentage" , style: `left: ${obj.colorWidth - 25}px`},[
   obj.Percentage + '%'
   ]),
  ]),
  obj.getNodePer(),
  ]),
 ])
 },
 onremove: function (vnode) {
 obj.closemode();
 },
 }

scss样式代码。

// 用的是scss预处理样式
// $arrowsSize scss变量
// var(--primary-lighten)用的是全局颜色,可以直接用颜色值代替
// $dark #ligth 为黑夜白天样式,可以不用。
$arrowsSize: 6px; // 三角形 大小
.slider{
 width: 100%;

 .slider-body{
 width: 100%;
 height: 6px;
 margin: 16px 0;
 border-radius: 5px;
 position: relative;
 cursor: pointer;

 .slider-section{
  height: 6px;
  background-color: var(--primary-lighten);
  // width: 30%;
  position: absolute;
  left: 0;
  border-radius: 5px;

  .slider-radius{
  height: 16px;
  width: 16px;
  position: absolute;
  left: 100%;
  z-index: 999;
  top: -5px;
  transform: translateX(-50%);
  background-color: transparent;
  text-align: center;
  user-select: none;
  line-height: normal;

  .slider-radius-body{
   width: 16px;
   height: 16px;
   border: 2px solid var(--primary-lighten);
   background-color: var(--fontwhite-base);
   border-radius: 50%;
   transition: .2s;
   user-select: none;

   &::after {
   content: '';
   height: 100%;
   display: inline-block;
   vertical-align: middle;
   }
  }
  }

  .slider-percentage{
  // display: none;
  height: 25px;
  width: 50px;
  line-height: 25px;
  border-radius: 5px;
  background-color: var(--mode-darken);
  text-align: center;
  font-size: 14px;
  color: var(--font-darken);
  position: absolute;
  top: -40px;
  // left: 100%;

  &::after {
   content: '';
   display: inline-block;
   vertical-align: middle;
   width: 0;
   height: 0;
   position: absolute;
   border-top: solid $arrowsSize;
   border-left: solid $arrowsSize transparent !important;
   border-right: solid $arrowsSize transparent !important;
   border-bottom: solid $arrowsSize transparent !important;
   top: 25px;
   left: 35%;
   color: var(--mode-darken);
  }
  }
 }

 .slider-node{
  position: absolute;
  height: 8px;
  width: 8px;
  border-radius: 100%;
  background-color: var(--fontwhite-base);
  border: 2px solid var(--primary-lighten);
  transform: translateX(-50%);
  top: -1px;
 }
 }
}

#dark .slider-body{
 background-color: var(--line-darken3);
}
#light .slider-body{
 background-color: var(--line-lighten3);
}

调用

getSlider: function () {
  return m(slider, {
  cb : function(arg){
   console.log(arg,22222)
  },
 });
 },

obj.getSlider(),

说明一下

因为公司项目涉及保密条例,电脑都加了安全限制,无法录制视频或者gif图片,所有只能截图展示了。

效果

可以点击圆点拖动,也可以直接点击灰条进行点选然后拖动,也可以点击灰条上的百分比圆点进行拖动,因为单独又把事件绑定到了body上,所以可以在灰条上拖动开始并且在组件外也可以进行拖动,类似Element UI的slider组件效果。


拖动参数的打印


只为分享写代码过程中的一些心得体会,感谢平台!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 可拖拽组件slider.js使用方法详解

    基于 mithril.js ,javascript ,scss写一个可拖动的滑块组件,供大家参考,具体内容如下 问题描述: 需求需要实现一个可拖动的滑块组件,但是又不能用UI框架,只好自己动手写一个了. 废话不多说,直接上代码. 技术要求: 需要有mithril.js,javascript,scss技术基础. js及页面代码. var m = require("mithril"); require('./slider.scss'); import slider from './slid

  • vue拖拽排序插件vuedraggable使用方法详解

    大家好,最近做的项目要用到拖拽排序,我现在的项目是vue项目,所以我就屁颠屁颠的去百度有木有这样功能的插件,我就知道一定会有,那就是vuedraggable,这是一款很棒的拖拽插件,下面我来说一下怎么引入 首先在vue项目中,用npm包下载下来 npm install vuedraggable -S 下载下来后,引入插件,在你的vue文件的script标签里面这样引入 import draggable from 'vuedraggable' 别忘了下面要注册组件 components: { dr

  • jquery拖拽自动排序插件使用方法详解

    本文为大家分享了jquery拖拽自动排序插件,供大家参考,具体内容如下 该插件并不是原生js写的,是基于jquery的,想看原生的话,请绕道而行. html: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script type="text/javas

  • Vue官方推荐AJAX组件axios.js使用方法详解与API

    Axios.js作为Vue官方插件的AJAX组件其主要有以下几个特点: 1.比Jquery轻量,但处理请求不多的时候,可以使用 2.基于Promise语法标准 3.支持nodejs 4.自动转换JSON数据 Axios.js用法 axios提供了一下几种请求方式 axios.request(config) axios.get(url[, config]) axios.delete(url[, config]) axios.head(url[, config]) axios.post(url[,

  • Bootstrap滚动监听组件scrollspy.js使用方法详解

    其实滚动监听使用的情况还是很多的,比如导航居于右侧,当主题内容滚动某一块的时候,右侧导航对应的要高亮. 实现功能 1.当滚动区域内设置的hashkey距离顶点到有效位置时,就关联设置其导航上的指定项 2.导航必须是 .nav > li > a 结构,并且a上href或data-target要绑定hashkey 3.菜单上必须有.nav样式 4.滚动区域的data-target与导航父级Id(一定是父级)要一致. <div id="selector" class=&qu

  • 在Vue2中注册全局组件的两种方法详解

    第一种:在main.js中直接注册 //引入 import FixedTop from '@/components/FixedTop //注册为全局组件 Vue.componet('FixedTop',FixedTop) //页面直接使用 <FixedTop /> 缺点:如果我们需要注册的全局组件非常多,那么需要一个一个引入,然后分别调用Vue.componet方法,main.js文件会变得很大很臃肿,不好维护,所以当需要注册的全局组件非常多的时候可以采用插件的形式注册 第二种:使用插件的形式

  • jQuery Json数据格式排版高亮插件json-viewer.js使用方法详解

    jQuery Json数据格式排版高亮插件json-viewer.js使用方法详解 1.插件介绍: jquery.json-viewer.js是一款查看json格式数据的jquery插件.它可以将混乱的json数据漂亮的方式展示在页面中,并支持节点的伸展和收缩和语法高亮等功能. 2.代码演示: 1).首先引入jquery和json.viewer.js插件 <script src="http://www.jq22.com/jquery/jquery-1.10.2.js">&l

  • vuejs动态组件给子组件传递数据的方法详解

    通过子组件定义时候的props可以支持父组件给子组件传递数据,这些定义的props在子组件的标签中使用绑定属性即可,但是如果使用的是<component>动态组件,这个时候就没有显式的子组件标签,要给子组件传递数据需要在<component> 中进行绑定 <div class="app" id="deviceready"> <component :is="currentView" :user_name.s

  • 文本溢出插件jquery.dotdotdot.js使用方法详解

    插件下载地址:https://github.com/FrDH/jQuery.dotdotdot 引入jQuery.js和jquery.dotdotdot.js <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="jquery.dotdotdot.js"><

  • vue 父组件通过$refs获取子组件的值和方法详解

    前言 在vue项目中组件之间的通讯是很常见的问题,同时也是很重要的问题,我们大致可以将其分为三种情况: 父传子:在父组件中绑定值,在子组件中用props接收 子传父:在父组件中监听一个事件,在子组件中利用$emit触发这个事件并带上数据作为第二个参数,这时父组件中监听事件的回调函数就会被调用,回调函数的参数就是子组件带上来的数据,这样就可以在父组件中使用子组件的数据了, 兄弟之间的传递:我们可以使用事件总线(eventBus)来轻松的解决,其实就是发布订阅者模式 今天我们要看的是父组件如何直接调

随机推荐