表头固定的表格组件

UI原型

表头固定的表格组件_第1张图片

HTML代码


序号 品名 材质 规格 计划量 未执行量 备注
超发{{-d.batchUndoWeight}}
合计:
序号
合计:

CSS代码

*{
	-webkit-box-sizing: border-box;
	-moz-box-sizing: border-box;
	box-sizing: border-box;
}
input {
		outline: none;
		-webkit-border-radius: 5px;
		-moz-border-radius: 5px;
		border-radius: 5px;
		text-indent: 8px;
}
[v-cloak]{display: none;}
.hide{display: none !important;}
.scroll-table-box {
	position: relative;
}
.scroll-table-head {
	width: 100%;
	overflow: hidden;
}
.scroll-table-body {
	max-height: calc(100vh - 271px);
  overflow: hidden;
}
.no_border_top{
	border-top: none !important;
}
.w_60 {
	width: 60px !important;
}
.scroll-table-box .v-shadow {
	position: absolute;
	left: 129px;
	top: 0;
	width: 0px;
	height: 100%;
	z-index: -1;
	-webkit-box-shadow: -1px 3px 10px 1px #000000;
	-moz-box-shadow: -1px 3px 10px 1px #000000;
	box-shadow: -1px 3px 10px 1px #000000;
}
.scroll-table-fixed-left {
	width: 43px;
	height: 100%;
  position: absolute;
  left: 0;
  top: 0;
  overflow: hidden;
}
.scroll-table-fixed-left .scroll-table-fixed-left-head {
	position: relative;
}
.scroll-table-fixed-left .scroll-table-fixed-left-body {
	position: relative;
	max-height: calc(100% - 39px);
  overflow: hidden;
}
.scroll-table-box .tb1{
	width: 100%; 
	table-layout: fixed;
  border-top: 1px solid #ccc;
  border-right: 1px solid #ccc;
}
.scroll-table-box .tb1 th,.scroll-table-box .tb1 td{
	padding: 8px 4px;
	border-bottom: 1px solid #ccc;
	width: 100px;
	text-align: center;
	font-size: 14px;
}
.scroll-table-box .tb1 th {
	background-color: #edf6fd;
  color: #333;
  border-left: 1px solid #ccc;
}
.scroll-table-box .tb1 td{
	background-color: #fff;
	color: black;
	border-left: 1px solid #ccc;
}
.scroll-table-box .tb1 td .td_div{
  line-height: 20px;
	text-align: center;
	white-space: pre-wrap;
  word-wrap: break-word;
  word-break: break-word;
}
.scroll-table-box .tb1 td .td-input {
	width: 60px;
	color: red;
	text-align:center;
	text-indent: 0px;
	border: 1px solid #A5A5A5;
}
.td-grey {
	background-color: #f8f8f8 !important;
}

 js代码

move.js

(function(){
	window.requestAnimationFrame = window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame;
	window.cancelAnimationFrame = window.cancelAnimationFrame|| window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame||window.cancelRequestAnimationFrame||window.webkitCancelRequestAnimationFrame||window.mozCancelRequestAnimationFrame; 
	if(!requestAnimationFrame){
		var lastTime = Date.now();
		window.requestAnimationFrame = function(callback){
			var id;
			var nowTime = Date.now();
			var delay = Math.max(16.7-(nowTime-lastTime),0);
			id = setTimeout(callback,delay);
			lastTime = nowTime + delay;
			return id;
		};
	}
	if(!cancelAnimationFrame){
		window.cancelAnimationFrame = function(index){
			clearTimeout(index);
		};
	}
})();

/*
	startMove(init)
	init:{
		el: 要动画的元素,
		type: 动画的类型,
		target: {//目标值
			left: 100,
			translateX: 100
		},
		time: //动画时长ms,
		callBack: fn //动画执行完成之后 要执行的函数
		callIn: fn//动画执行中
	}
*/

function transform(el,attr,val){
	if(!el.transform){
		el.transform = {
		};
	}
	if(val === undefined){
		return el.transform[attr];
	}
	el.transform[attr] = val;
	var str = "";
	for(var s in el.transform){
		switch(s){
			case "rotate":
			case "rotateX":
			case "rotateY":
			case "rotateZ":
			case "skewX":
			case "skewY":
				str += s +"("+el.transform[s]+"deg) ";
				break;
			case "scale":
			case "scaleX":
			case "scaleY":
				str += s +"("+el.transform[s]+") ";
				break;
			case "translateX":
			case "translateY":
			case "translateZ":
				str += s +"("+el.transform[s]+"px) ";
				break;	
		}
	}
	el.style.WebkitTransform = el.style.transform = str;
}

function css(el,attr,val){
	var transformAttr = ["rotate","rotateX","rotateY","rotateZ","skewX","skewY","scale","scaleX","scaleY","translateX","translateY","translateZ"];
	for(var i = 0; i < transformAttr.length; i++){
		if(attr == transformAttr[i]){ //如果 attr 等transform其中一个值就代表用用户想要操作的是 transform
			return transform(el,attr,val);
		}
	}
	if(val === undefined){
		val = getComputedStyle(el)[attr];
//		console.log(val);
		val = parseFloat(val);
		return val;
	}
	if(attr == "opacity"){
		el.style[attr] = val;
	} else {
		el.style[attr] = val + "px";
	}
}

function startMove(init){
	var t = 0;
	var b = {};//样式的初始值
	var c = {};//样式的差值	
	var d = Math.ceil(init.time/16.7);
	cancelAnimationFrame(init.el.timer);
	for(var s in init.target) {
		b[s] = css(init.el,s);
		c[s] = init.target[s] - b[s];
	}
	init.el.timer = requestAnimationFrame(move);
	function move(){
		if(t > d || d == 0){
			cancelAnimationFrame(init.el.timer);
			init.callBack&&init.callBack.call(init.el);
		} else {
			t++;
			for(var s in init.target){
				var val = Tween[init.type](t,b[s],c[s],d);
				css(init.el,s,val);
			}
			init.callIn&&init.callIn.call(init.el);
			init.el.timer = requestAnimationFrame(move);
		}
	}
}	

tween.js

var Tween = {
	linear: function (t, b, c, d){
		return c*t/d + b;
	},
	easeIn: function(t, b, c, d){
		return c*(t/=d)*t + b;
	},
	easeOut: function(t, b, c, d){
		return -c *(t/=d)*(t-2) + b;
	},
	easeBoth: function(t, b, c, d){
		if ((t/=d/2) < 1) {
			return c/2*t*t + b;
		}
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInStrong: function(t, b, c, d){
		return c*(t/=d)*t*t*t + b;
	},
	easeOutStrong: function(t, b, c, d){
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeBothStrong: function(t, b, c, d){
		if ((t/=d/2) < 1) {
			return c/2*t*t*t*t + b;
		}
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	elasticIn: function(t, b, c, d, a, p){
		if (t === 0) { 
			return b; 
		}
		if ( (t /= d) == 1 ) {
			return b+c; 
		}
		if (!p) {
			p=d*0.3; 
		}
		if (!a || a < Math.abs(c)) {
			a = c; 
			var s = p/4;
		} else {
			var s = p/(2*Math.PI) * Math.asin (c/a);
		}
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	elasticOut: function(t, b, c, d, a, p){
		if (t === 0) {
			return b;
		}
		if ( (t /= d) == 1 ) {
			return b+c;
		}
		if (!p) {
			p=d*0.3;
		}
		if (!a || a < Math.abs(c)) {
			a = c;
			var s = p / 4;
		} else {
			var s = p/(2*Math.PI) * Math.asin (c/a);
		}
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},    
	elasticBoth: function(t, b, c, d, a, p){
		if (t === 0) {
			return b;
		}
		if ( (t /= d/2) == 2 ) {
			return b+c;
		}
		if (!p) {
			p = d*(0.3*1.5);
		}
		if ( !a || a < Math.abs(c) ) {
			a = c; 
			var s = p/4;
		}
		else {
			var s = p/(2*Math.PI) * Math.asin (c/a);
		}
		if (t < 1) {
			return - 0.5*(a*Math.pow(2,10*(t-=1)) * 
					Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		}
		return a*Math.pow(2,-10*(t-=1)) * 
				Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b;
	},
	backIn: function(t, b, c, d, s){
		if (typeof s == 'undefined') {
		   s = 1.70158;
		}
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	backOut: function(t, b, c, d, s){
		if (typeof s == 'undefined') {
			s = 1.70158;  //回缩的距离
		}
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	}, 
	backBoth: function(t, b, c, d, s){
		if (typeof s == 'undefined') {
			s = 1.70158; 
		}
		if ((t /= d/2 ) < 1) {
			return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		}
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	bounceIn: function(t, b, c, d){
		return c - Tween['bounceOut'](d-t, 0, c, d) + b;
	},       
	bounceOut: function(t, b, c, d){
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + 0.75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b;
		}
		return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b;
	},      
	bounceBoth: function(t, b, c, d){
		if (t < d/2) {
			return Tween['bounceIn'](t*2, 0, c, d) * 0.5 + b;
		}
		return Tween['bounceOut'](t*2-d, 0, c, d) * 0.5 + c*0.5 + b;
	}
};

主要脚本代码(以VUE框架为例)

mounted: function() {
    var self = this;
    this.$nextTick(function () {
        //表格主区域滑动
        self.tableSwiperFunc({
            $scrollTableFixedLeft: $(".scroll-table-fixed-left"),
            wrap: $(".scroll-table-body")[0],
            scroll: $(".scroll-table-body table")[0],
            wrap_one: $(".scroll-table-fixed-left-body")[0],
            scroll_one: $(".scroll-table-fixed-left-body table")[0],
            wrap_two: $(".scroll-table-head")[0],
            scroll_two: $(".scroll-table-head table")[0],
            judgeScroll: $(".scroll-table-body table")[0],
            moveFunc: function (isDir, target, scroll, scroll_one, scroll_two) {
                if (isDir.x) {
                    transform(scroll, 'translateX', target.x);
                    transform(scroll_two, 'translateX', target.x);
                } else if (isDir.y) {
                    transform(scroll, 'translateY', target.y);
                    transform(scroll_one, 'translateY', target.y);
                }
            },
            endFunc: function (isDir, targetX, targetY, time, scroll, scroll_one, scroll_two) {
                if (isDir.x) {
                    startMove({
                        el: scroll,
                        type: "easeOutStrong",
                        time: time.timeX,
                        target: {
                            translateX: targetX
                        }
                    });
                    startMove({
                        el: scroll_two,
                        type: "easeOutStrong",
                        time: time.timeX,
                        target: {
                            translateX: targetX
                        }
                    });
                } else if (isDir.y) {
                    startMove({
                        el: scroll,
                        type: "easeOutStrong",
                        time: time.timeY,
                        target: {
                            translateY: targetY
                        }
                    });
                    startMove({
                        el: scroll_one,
                        type: "easeOutStrong",
                        time: time.timeY,
                        target: {
                            translateY: targetY
                        }
                    });
                }
            }
        });
        //表格左边固定表头区域滑动
        self.tableSwiperFunc({
            $scrollTableFixedLeft: $(".scroll-table-fixed-left"),
            wrap: $(".scroll-table-fixed-left-body")[0],
            scroll: $(".scroll-table-fixed-left-body table")[0],
            wrap_one: $(".scroll-table-body")[0],
            scroll_one: $(".scroll-table-body table")[0],
            wrap_two: $(".scroll-table-head")[0],
            scroll_two: $(".scroll-table-head table")[0],
            judgeScroll: $(".scroll-table-body table")[0],
            wrapIsFixedLeft: true,
            moveFunc: function (isDir, target, scroll, scroll_one, scroll_two) {
                if (isDir.x) {
                    transform(scroll_one, 'translateX', target.x);
                    transform(scroll_two, 'translateX', target.x);
                }
                if (isDir.y) {
                    transform(scroll, 'translateY', target.y);
                    transform(scroll_one, 'translateY', target.y);
                }
            },
            endFunc: function (isDir, targetX, targetY, time, scroll, scroll_one, scroll_two) {
                if (isDir.x) {
                    startMove({
                        el: scroll_one,
                        type: "easeOutStrong",
                        time: time.timeX,
                        target: {
                            translateX: targetX
                        }
                    });
                    startMove({
                        el: scroll_two,
                        type: "easeOutStrong",
                        time: time.timeX,
                        target: {
                            translateX: targetX
                        }
                    });
                }
                if (isDir.y) {
                    startMove({
                        el: scroll,
                        type: "easeOutStrong",
                        time: time.timeY,
                        target: {
                            translateY: targetY
                        }
                    });
                    startMove({
                        el: scroll_one,
                        type: "easeOutStrong",
                        time: time.timeY,
                        target: {
                            translateY: targetY
                        }
                    });
                }
            }
        });
        //表格固定头部表头区域滑动
        self.tableSwiperFunc({
            $scrollTableFixedLeft: $(".scroll-table-fixed-left"),
            wrap: $(".scroll-table-head")[0],
            scroll: $(".scroll-table-head table")[0],
            wrap_one: $(".scroll-table-fixed-left-body")[0],
            scroll_one: $(".scroll-table-fixed-left-body table")[0],
            wrap_two: $(".scroll-table-body")[0],
            scroll_two: $(".scroll-table-body table")[0],
            judgeScroll: $(".scroll-table-body table")[0],
            moveFunc: function (isDir, target, scroll, scroll_one, scroll_two) {
                if (isDir.x) {
                    transform(scroll, 'translateX', target.x);
                    transform(scroll_two, 'translateX', target.x);
                }
            },
            endFunc: function (isDir, targetX, targetY, time, scroll, scroll_one, scroll_two) {
                if (isDir.x) {
                    startMove({
                        el: scroll,
                        type: "easeOutStrong",
                        time: time.timeX,
                        target: {
                            translateX: targetX
                        }
                    });
                    startMove({
                        el: scroll_two,
                        type: "easeOutStrong",
                        time: time.timeX,
                        target: {
                            translateX: targetX
                        }
                    });
                }
            }
        });

        $(".bug-tr").css({
            'line-height': "42px"
        });
        setTimeout(function () {
            $(".bug-tr").css({
                'line-height': "43px"
            });
        }, 1000);
    })
},
updated: function () {
    this.$nextTick(function () {
        $('.scroll-table-fixed-left-body tr').each(function (index, item) {
            var h = $('.scroll-table-body tr').eq(index).height();
            $(item).find('td').outerHeight(h);
        });
    })
},
methods: {
    /**
        * 表格区域滑动
        * init:{
        * 		$scrollTableFixedLeft: 左边固定表头(jq选择器),
        * 		wrap: 主滑动区域(父级),
        * 		scroll: 主滑动区域,
        * 		wrap_one: 副滑动区域1(父级),
        *   	scroll_one: 副滑动区域1,
        * 		wrap_two: 副滑动区域2(父级),
        * 		scroll_two: 副滑动区域2,
        * 		judgeScroll: 某元素控制左侧固定菜单是否显示,
        * 		wrapIsFixedLeft: true||false,//手指是否在左侧固定表头滑动
        * 		moveFunc: function(){},//touchmove的回调
        * 		endFunc: function(){},//touchend的回调
        * }
    */
    tableSwiperFunc: function(init) {
        var self = this;
        var $vShadow = $(".v-shadow");
        var $scrollTableFixedLeft = init.$scrollTableFixedLeft;
        var judgeScroll = init.judgeScroll;
        /*表格主滑动区域*/
        var wrap = init.wrap;
        var scroll = init.scroll;
        var wrap_width = 0;
        var scroll_width = 0;
        var wrap_height = 0;
        var scroll_height = 0;
        /*表格副滑动区域1*/
        var wrap_one = init.wrap_one;
        var scroll_one = init.scroll_one;
        var wrap_width_one = 0;
        var scroll_width_one = 0;
        var wrap_height_one = 0;
        var scroll_height_one = 0;
        /*表格副滑动区域2*/
        var wrap_two = init.wrap_two;
        var scroll_two = init.scroll_two;
        var wrap_width_two = 0;
        var scroll_width_two = 0;
        var wrap_height_two = 0;
        var scroll_height_two = 0;

        var isDir = { // 判断滑动的方向
            x: false,
            y: false
        };
        var isFirst = true;
        var startPonit = {};
        var startEl = {};
        var startTime = 0;
        var dis = {}; // 手指 当前值 和 初始值的一个差值 
        var timeDis = 0; // 时间差值 
        /*设置初始transfrom*/
        transform(scroll, "translateX", 0);
        transform(scroll, "translateY", 0);
        transform(scroll_one, "translateX", 0);
        transform(scroll_one, "translateY", 0);
        transform(scroll_two, "translateX", 0);
        transform(scroll_two, "translateY", 0);

        wrap.addEventListener('touchstart', function (e) {
            var touch = e.changedTouches[0];

            wrap_width = $(wrap).width();
            scroll_width = $(scroll).width();
            wrap_height = $(wrap).height();
            scroll_height = $(scroll).height();

            wrap_width_one = $(wrap_one).width();
            scroll_width_one = $(scroll_one).width();
            wrap_height_one = $(wrap_one).height();
            scroll_height_one = $(scroll_one).height();

            wrap_width_two = $(wrap_two).width();
            scroll_width_two = $(scroll_two).width();
            wrap_height_two = $(wrap_two).height();
            scroll_height_two = $(scroll_two).height();

            scroll.style.transition = "none";
            scroll.style.WebkitTransition = "none";
            scroll_one.style.transition = "none";
            scroll_one.style.WebkitTransition = "none";
            scroll_two.style.transition = "none";
            scroll_two.style.WebkitTransition = "none";

            startPonit = {
                x: touch.pageX,
                y: touch.pageY
            };
            startEl = {
                x: transform(scroll, "translateX"),
                y: transform(scroll, "translateY")
            };
            if (init.wrapIsFixedLeft) {
                startEl = {
                    x: transform(scroll_one, "translateX"),
                    y: transform(scroll, "translateY")
                };
            }
            startTime = Date.now();
        });
        wrap.addEventListener('touchmove', function (e) {
            e.preventDefault();
            var touch = e.changedTouches[0];
            var nowPonit = {
                x: touch.pageX,
                y: touch.pageY
            };
            var nowTime = Date.now();
            /* 手指 当前值 和 初始值的一个差值 */
            dis = {
                x: nowPonit.x - startPonit.x,
                y: nowPonit.y - startPonit.y
            };
            /*确定滑动方向*/
            if (isFirst) {
                if (Math.abs(dis.x) >= Math.abs(dis.y)) {
                    isDir.x = true;
                    isFirst = false;
                } else if (Math.abs(dis.x) < Math.abs(dis.y)) {
                    isDir.y = true;
                    isFirst = false;
                }
            }
            /* 时间差值 */
            timeDis = nowTime - startTime;
            /* 元素应在要在的一个位置 */
            var target = {
                x: Math.round(startEl.x + dis.x),
                y: Math.round(startEl.y + dis.y)
            };
            if (transform(judgeScroll, "translateX") < 0) {
                $scrollTableFixedLeft.removeClass('hide');
            } else if (transform(judgeScroll, "translateX") >= 0) {
                $scrollTableFixedLeft.addClass('hide');
            }
            /* 设置样式 */
            init.moveFunc && init.moveFunc(isDir, target, scroll, scroll_one, scroll_two);
        });
        wrap.addEventListener('touchend', function (e) {
            var x_bottom_back_num = -(scroll_width - wrap_width); // X轴触底值
            var y_bottom_back_num = -(scroll_height - wrap_height); // Y轴触底值
            if (timeDis >= 100) {// 判断 当用户手指抬起时 和 最后一次移动的时候,有比较大的一个时间间隔,就可以认定 用户在抬起手指前有那么一段时间是按着不动的,那么我们也就不执行缓冲
                dis.x = 0;
                dis.y = 0;
            }
            var speedX = dis.x / timeDis; // X轴速度
            var speedY = dis.y / timeDis; // Y轴速度
            speedX = speedX ? speedX : 0;
            speedY = speedY ? speedY : 0;
            //					var s = speed*speed / (2*0.005) * (speed/Math.abs(speed)); // 距离
            var sX = speedX * 170;
            var sY = speedY * 170;
            var nowX = transform(scroll, "translateX");
            var nowY = transform(scroll, "translateY");
            var targetX = Math.round(nowX + sX);
            var targetY = Math.round(nowY + sY);
            //过界处理
            if (targetX > 0) {
                targetX = 0;
            } else if (scroll_width >= wrap_width && targetX < x_bottom_back_num) {
                targetX = x_bottom_back_num;
            }
            if (targetY > 0) {
                targetY = 0;
            } else if (scroll_height >= wrap_height && targetY < y_bottom_back_num) {
                targetY = y_bottom_back_num;
            }
            // time 整个动画的动画时间
            // s - now 移动距离
            // time 移动距离越远 时间就越长
            var timeX = Math.abs(sX) * 1.15;
            var timeY = Math.abs(sY) * 1.15;
            timeX = timeX == 0 ? 200 : timeX;
            timeY = timeY == 0 ? 200 : timeY;
            var time = {
                timeX: timeX,
                timeY: timeY
            };
            if (init.wrapIsFixedLeft) {
                x_bottom_back_num = -(scroll_width_one - wrap_width_one);
                nowX = transform(scroll_one, "translateX");
                targetX = Math.round(nowX + sX);
                if (targetX > 0) {
                    targetX = 0;
                } else if (scroll_width_one >= wrap_width_one && targetX < x_bottom_back_num) {
                    targetX = x_bottom_back_num;
                }
            }
            init.endFunc && init.endFunc(isDir, targetX, targetY, time, scroll, scroll_one, scroll_two);

            isFirst = true;
            isDir = { // 初始化滑动的方向
                x: false,
                y: false
            };
        });
    }
}

 

你可能感兴趣的:(表头固定的表格组件)