动态布局 - 拖拽调整宽度
项目中出现需求,要求动态调整各个分块的大小,方便缩放查看信息,以下实现了宽度的动态调整(高度的后续会补上)
<!DOCTYPE html> <html lang="en" dir="ltr"> <head> <meta charset="utf-8"> <title></title> <style media="screen"> html,body { height: 100%; margin: 0; padding: 0; } .flex-dragable { display: flex; } .flex-row { height: 80%; display: flex; flex-direction: column; } .flex-item { flex: 1 1 100%; padding: 15px; margin: 5px; border: 1px solid #a3a3a3; overflow: auto; } .flex-row-item { flex: 1 1 100%; } </style> </head> <body> <div class="flex-row"> <div class="flex-dragable flex-row-item"> <div class="flex-item"> content 1 ... </div> <div class="flex-item"> content 2 ... </div> <div class="flex-item"> content - ... </div> </div> <div class="flex-dragable flex-row-item"> <div class="flex-item"> content 3 ... </div> <div class="flex-item"> content 4 ... </div> </div> </div> </body> <script type="text/javascript"> var items = document.querySelectorAll('.flex-dragable'); Array.from(items).map(function(item){ dragablize(item); }); /** * 初始化拖拽 **/ function dragablize(ctn) { var items = ctn.querySelectorAll('.flex-item'), lastX; Array.from(items).map(function(item){ item.onmousedown = function(event) { var target = getTarget(event), prevItem = target.previousElementSibling, suffItem = target.nextElementSibling; lastX = event.clientX; if (suffItem && (event.offsetX > this.offsetWidth - 10)) { item.mouseDown = true; item.oldX = event.x; item.oldWidth = item.offsetWidth; }else if(prevItem && (event.offsetX < 10)) {// 左边拖拽时,实际设置前置元素的宽度 var evt = newMouseEvent(event,'mousedown'); prevItem.dispatchEvent(evt); } }; item.onmouseup = function(event) { var target = getTarget(event), prevItem = target.previousElementSibling; item.mouseDown = false; item.style.cursor = ''; lastX = null; if(prevItem) {// 左边拖拽时触发前置元素mouseup,避免响应异常 var evt = newMouseEvent(event,'mouseup'); prevItem.dispatchEvent(evt); } }; }); ctn.onmousemove = function(event) { var target = getTarget(event); if(Array.from(items).includes(target)) { var prevItem = target.previousElementSibling, suffItem = target.nextElementSibling, direction = event.clientX - lastX; /** * 改变鼠标样式 * 1:中间的元素左右边都可拖拽样式(左边拖拽时,实际设置前置元素宽度) * 2:没有前置元素的只能有右边拖拽样式 * 3:没有后置元素的只能有左边拖拽样式 **/ if (suffItem && (event.offsetX > target.offsetWidth - 10) || prevItem && (event.offsetX < 10)) { target.style.cursor = 'col-resize'; }else { target.style.cursor = ''; } //调整宽度 var item = getClickedTarget(items); if(item && item.mouseDown && direction) { setWidth(item,direction); lastX = event.clientX; } } }; function setWidth(item,offset) { var style = getComputedStyle(item), width = style.width.replace('px','')-0; // maxWidth、minWidth 防止flex布局对宽度计算的影响 item.style.width = width + offset + 'px'; item.style.maxWidth = width + offset + 'px'; item.style.minWidth = width + offset + 'px'; } } function addListener(element,type,listener,useCapture){ element.addEventListener?element.addEventListener(type,listener,useCapture):element.attachEvent("on" + type,listener); } function getTarget(evt){ return evt.target || evt.srcElement; } function getClickedTarget(items){ var t; Array.from(items).map(function(item){ if(item.mouseDown == true) t = item; }); return t; } /** * 创建鼠标事件 **/ function newMouseEvent(event,eventType){ var clientX = event.clientX,clientY=event.clientY,screenX=event.screenX,screenY=event.screenY; var simEvent = new MouseEvent(eventType,{clientX:clientX,clientY:clientY,screenX:screenX,screenY:screenY}); return simEvent; } </script> </html>