拖拽新增、拖拽移动、拖拽缩放主要就是这几个功能。下面是实现代码。欢迎指正! <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Demo</title> <!--<link rel="stylesheet" type="text/css" href="css/style.css">--> <link rel="stylesheet" type="text/css" href="css/demo.css"> </head> <body> <div class="dr-float-layout"> <div class="dr-icon-group dr-icon-group-aid"> <ul class="clearfix "> <li class="dr-button-group"> <i class="dr-icon-button icon-pie" data-type="pie" data-id="1" title="饼状图"></i> </dl> </li> <li class="dr-button-group"> <i class="dr-icon-button icon-donut" data-type="donut" data-id="2" title="环形图"></i> </li> <li class="dr-button-group"> <i class="dr-icon-button icon-axis" data-type="bar" data-id="3" title="柱状图"></i> </li> <li class="dr-button-group"> <i class="dr-icon-button icon-line" data-type="line" data-id="4" title="折线图"></i> </li> <li class="dr-button-group"> <i class="dr-icon-button icon-group" data-type="table" data-id="5" title="表格图"></i> </li> </ul> </div> <div class="dr-v-add-layout"></div> </div> <script src="js/2.1.4.jquery.min.js"></script> <script src="js/echarts.js"></script> <script src="js/newDemo.js"></script> <script> $(function () { var table = '<div class="dr-fit-list">\n' + ' <div class="dr-absolute-layout">\n' + ' <div class="dr-absolute-title">\n' + ' <div class="dr-drag-bar"></div>\n' + ' <h4>统计组件</h4>\n' + ' </div>\n' + ' <div class="dr-fit-main">\n' + ' <div class="table-responsive">\n' + ' <table class="table table-bordered table-hover">\n' + ' <thead>\n' + ' <tr>\n' + ' <th></th>\n' + ' <th>First Name</th>\n' + ' <th>Last Name</th>\n' + ' <th>Username</th>\n' + ' </tr>\n' + ' </thead>\n' + ' <tbody>\n' + ' <tr>\n' + ' <th scope="row">1</th>\n' + ' <td>Mark</td>\n' + ' <td>Otto</td>\n' + ' <td>@mdo</td>\n' + ' </tr>\n' + ' <tr>\n' + ' <th scope="row">2</th>\n' + ' <td>Jacob</td>\n' + ' <td>Thornton</td>\n' + ' <td>@fat</td>\n' + ' </tr>\n' + ' <tr>\n' + ' <th scope="row">3</th>\n' + ' <td>Larry</td>\n' + ' <td>the Bird</td>\n' + ' <td>@twitter</td>\n' + ' </tr>\n' + ' </tbody>\n' + ' </table>\n' + ' </div>\n' + ' </div>\n' + ' <div class="dr-absolute-resize">\n' + ' <div data-type="TL" class="dr-resize-top-left"></div>\n' + ' <div data-type="T" class="dr-resize-top"></div>\n' + ' <div data-type="TR" class="dr-resize-top-right"></div>\n' + ' <div data-type="L" class="dr-resize-left"></div>\n' + ' <div data-type="R" class="dr-resize-right"></div>\n' + ' <div data-type="BL" class="dr-resize-bottom-left"></div>\n' + ' <div data-type="B" class="dr-resize-bottom"></div>\n' + ' <div data-type="BR" class="dr-resize-bottom-right"></div>\n' + ' </div>\n' + ' </div>\n' + ' </div>'; var echertsNode = '<div class="dr-fit-list">\n' + ' <div class="dr-absolute-layout">\n' + ' <div class="dr-absolute-title">\n' + ' <div class="dr-drag-bar"></div>\n' + ' <h4>统计组件</h4>\n' + ' </div>\n' + ' <div class="dr-fit-main">\n' + ' </div>\n' + ' <div class="dr-absolute-resize">\n' + ' <div data-type="TL" class="dr-resize-top-left"></div>\n' + ' <div data-type="T" class="dr-resize-top"></div>\n' + ' <div data-type="TR" class="dr-resize-top-right"></div>\n' + ' <div data-type="L" class="dr-resize-left"></div>\n' + ' <div data-type="R" class="dr-resize-right"></div>\n' + ' <div data-type="BL" class="dr-resize-bottom-left"></div>\n' + ' <div data-type="B" class="dr-resize-bottom"></div>\n' + ' <div data-type="BR" class="dr-resize-bottom-right"></div>\n' + ' </div>\n' + ' </div>\n' + ' </div>'; $.get('data/package.json',function (res) { $('.dr-v-add-layout').Drag({ "dragNode": ".dr-icon-button", "targetNode": '.dr-v-add-layout', "moveNode": ".dr-drag-bar", "echertsTypeArr": [ { 'type': 'table', 'node': table }, { 'type': 'pie', 'node': echertsNode }, { 'type': 'line', 'node': echertsNode }, { 'type': 'bar', 'node': echertsNode }, { 'type': 'donut', 'node': echertsNode } ], "data": res }); }); }) </script> </body> </html>
;(function($,window,document,undefined){ "use strict"; var privateVar = { "echartsOBJ":[], "map_sort_index_max":0, "cur": { "x": 0, "y": 0, "z": 0, "h": 0, "w": 0, "l": 0, "t": 0, "type": null }, "eleIndexs": [], "mapSortIndex": [], "mouseDIndex": 0 }; var Drag = function (option) { this.defaults = { 'width': option.width || '200px', 'height': option.height || '200px', "echertsTypeArr": option.echertsTypeArr || [], 'data': option.data || {} }; this.actionState = false; this.cache = {}; this.options = $.extend({}, this.defaults, option); }; Drag.prototype = { constructor: Drag, init: function () { var that = this, dragNodeOBJ = null; if(that.options.echertsTypeArr.length > 0){ for(var i = 0,item; item = that.options.echertsTypeArr[i++];){ that.add(item); } } $(that.options.dragNode).on('dragstart', function (e) { var data = [$(this).attr('data-type'), $(this).attr('data-id')]; e.originalEvent.dataTransfer.setData('text/plain', data); }); $(that.options.dragNode).on('drag', function () { return false; }); $(that.options.dragNode).on('mousedown', function (e) { dragNodeOBJ = this; $(dragNodeOBJ).attr('draggable', true); that.options.actionState = true; }); $(document).on('mousemove', function (e) { }); $(document).on('mouseup', function (e) { $(dragNodeOBJ).attr('draggable', false); that.options.actionState = false; dragNodeOBJ = null; return false; }); //进入目标元素 $(that.options.targetNode).on('dragenter', function (e) { return false; }); //在目标元素上移动 $(that.options.targetNode).on('dragover', function (e) { return false; }); //移出目标元素 $(that.options.targetNode).on('dragleave', function () { return false; }); $(that.options.targetNode).on('drop', function (e) { if (!that.options.actionState){ return; } var data = e.originalEvent.dataTransfer.getData('text/plain').split(','); var option = { title : { text: '某站点用户访问来源', x:'center' }, tooltip : { trigger: 'item' }, series : [ { name: '访问来源', type: 'pie', radius : '55%', center: ['50%', '60%'], data:[ {value:335, name:'直接访问'}, {value:310, name:'邮件营销'}, {value:234, name:'联盟广告'}, {value:135, name:'视频广告'}, {value:1548, name:'搜索引擎'} ], itemStyle: { emphasis: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } } } ] }; var item = { "map_id":data[1], "map_type":data[0], "map_position_x":"500px", "map_position_y":"500px", "map_position_z":"1000", "map_width":"280px", "map_height":"230px", "map_sort_index": privateVar.map_sort_index_max + 1, "map_messages":option }; var nodes = $(that.cache[data[0]].node).css({ "top": item.map_position_y, "left": item.map_position_x, "z-index": item.map_position_z, "width": item.map_width, "height": item.map_height }).attr('data-sort',item.map_sort_index); $(this).append(nodes); if(data[0] && data[0] != 'table'){ var len = $(this).find('.dr-fit-list').length; var ele = $(this).find('.dr-fit-list').eq( len - 1).find('.dr-fit-main')[0]; privateVar.echartsOBJ.push( that.echartsInit(ele,item)); } privateVar.map_sort_index_max ++; $(dragNodeOBJ).attr('draggable',false); that.options.actionState = false; return false; }); if(that.options.data.map_lists.length > 0){ $.each(that.options.data.map_lists,function (i,item) { var nodes = $(that.cache[item.map_type].node).css({ "top": item.map_position_y, "left": item.map_position_x, "z-index": item.map_position_z, "width": item.map_width, "height": item.map_height }).attr('data-sort',item.map_sort_index); $(that.options.targetNode).append(nodes); if(item.map_messages.series){ $(that.options.targetNode).find('.dr-fit-list').each(function (i, ele) { if(item.map_sort_index === parseInt($(ele).attr('data-sort'))){ privateVar.echartsOBJ.push( that.echartsInit($(ele).find('.dr-fit-main')[0],item)); } }); } }); } if($('.dr-fit-list').length > 0){ $('.dr-fit-list').each(function (i, ele) { privateVar.eleIndexs.push(parseInt($(ele).css('z-index').replace('px',''))) privateVar.mapSortIndex.push(parseInt($(ele).attr('data-sort'))) }); privateVar.mouseDIndex =Math.max.apply(null, privateVar.eleIndexs); privateVar.map_sort_index_max =Math.max.apply(null, privateVar.mapSortIndex); } $('body').on("mousedown",that.options.moveNode,function(e){ dragNodeOBJ = this; that.mouseDown(dragNodeOBJ,e); return false; }); $('body').on('mousedown','.dr-resize-top-left,.dr-resize-top,.dr-resize-top-right,.dr-resize-left,.dr-resize-right,.dr-resize-bottom-left,.dr-resize-bottom,.dr-resize-bottom-right',function (e) { dragNodeOBJ = this; that.mouseDownZoom(dragNodeOBJ,e); }); $('body').on("mousemove",function(e){ if (!that.options.actionState){ return } if(dragNodeOBJ && !$(dragNodeOBJ).attr('data-type')){ that.mouseMove(dragNodeOBJ,e); } else { that.mouseMoveZoom(dragNodeOBJ,privateVar.cur.type,e); for(var i = 0, item; item = privateVar.echartsOBJ[i++];){ item.resize() } } }); $('body').on("mouseup",function(e){ if(dragNodeOBJ && ! $(dragNodeOBJ).attr('data-type')){ that.mouseUp(e); } else { that.mouseUpZoom(); } }); }, "add": function (rules) { this.cache[rules.type] = { 'type': rules.type, 'node': rules.node } }, "echartsInit": function (ele, option) { var initChart = echarts.init(ele); initChart.setOption(option.map_messages); return initChart; }, mouseDown: function (t,e) { this.options.actionState = true; //关闭选中功能 document.body.onselectstart=function(){ return false;}; var left = $(t).parents('.dr-fit-list').css('left').replace('px',''); var top = $(t).parents('.dr-fit-list').css('top').replace('px',''); privateVar.cur.x = e.pageX - parseInt(left); privateVar.cur.y = e.pageY - parseInt(top); $(t).parents('.dr-fit-list').siblings().removeClass('active'); if(!$(t).parents('.dr-fit-list').hasClass('active')){ $(t).parents('.dr-fit-list').addClass('active'); privateVar.mouseDIndex ++; $(t).parents('.dr-fit-list').css('z-index',privateVar.mouseDIndex); } if(typeof this.options.mouseD === 'function' ){ this.options.mouseD(); } }, mouseMove: function (t,e) { if( this.options.actionState){ $(t).parents('.dr-fit-list').stop(); var _x = e.pageX - privateVar.cur.x; var _y = e.pageY - privateVar.cur.y; if(_x<0){ _x=0; } if(_y<0){ _y=0; } if(_x> parseInt($(t).parents('.dr-v-add-layout').css('width').replace('px','')) - parseInt($(t).parents('.dr-fit-list').css('width').replace('px',''))){ _x = parseInt($(t).parents('.dr-v-add-layout').css('width').replace('px','')) - parseInt($(t).parents('.dr-fit-list').css('width').replace('px','')); } if( _y > parseInt($(t).parents('.dr-v-add-layout').css('height').replace('px','')) - parseInt($(t).parents('.dr-fit-list').css('height').replace('px',''))){ _y = parseInt($(t).parents('.dr-v-add-layout').css('height').replace('px','')) - parseInt($(t).parents('.dr-fit-list').css('height').replace('px','')); } $(t).parents('.dr-fit-list').animate({left:_x+"px",top:_y+"px"},10); } if(typeof this.options.mouseM === 'function' ){ this.options.mouseM(); } return false; }, mouseUp: function () { this.options.actionState = false; //开启选中功能 document.body.onselectstart=function(){ }; if(typeof this.options.mouseU === 'function' ){ this.options.mouseU(); } }, mouseDownZoom: function (ele,e) { this.options.actionState = true; console.log(2) //关闭选中功能 document.body.onselectstart=function(){ return false;}; privateVar.cur.l = parseInt($(ele).parents('.dr-fit-list').css('left').replace('px','')); privateVar.cur.t = parseInt($(ele).parents('.dr-fit-list').css('top').replace('px','')); privateVar.cur.x = e.pageX; privateVar.cur.y = e.pageY; privateVar.cur.h = parseInt($(ele).parents('.dr-fit-list').css('height').replace('px','')); privateVar.cur.w = parseInt($(ele).parents('.dr-fit-list').css('width').replace('px','')); privateVar.cur.type = $(ele).attr('data-type'); return false; }, mouseMoveZoom: function (ele, type,e) { if (this.options.actionState){ $(ele).parents('.dr-fit-list').stop(); var _x = e.pageX - privateVar.cur.x; var _y = e.pageY - privateVar.cur.y; switch(type) { case 'TL': $(ele).parents('.dr-fit-list').animate({ width: privateVar.cur.w - _x + 'px', height: privateVar.cur.h - _y +'px', left: privateVar.cur.l + _x + 'px', top: privateVar.cur.t + _y + 'px' },10); break; case 'T': $(ele).parents('.dr-fit-list').animate({ height: privateVar.cur.h - _y +'px', top: privateVar.cur.t + _y + 'px' },10); break; case 'TR': $(ele).parents('.dr-fit-list').animate({ width: privateVar.cur.w + _x + 'px', height: privateVar.cur.h - _y +'px', top: privateVar.cur.t + _y + 'px' },10); break; case 'L': $(ele).parents('.dr-fit-list').animate({ width: privateVar.cur.w - _x + 'px', left: privateVar.cur.l + _x + 'px', },10); break; case 'R': $(ele).parents('.dr-fit-list').animate({ width: _x + privateVar.cur.w + 'px' },10); break; case 'BL': $(ele).parents('.dr-fit-list').animate({ width: privateVar.cur.w - _x + 'px', height: privateVar.cur.h + _y +'px', left:privateVar.cur.l + _x + 'px' },10); break; case 'B': $(ele).parents('.dr-fit-list').animate({ height: privateVar.cur.h + _y +'px' },10); break; case 'BR': $(ele).parents('.dr-fit-list').animate({ width:_x + privateVar.cur.w + 'px', height: _y + privateVar.cur.h +'px' },10); break; default: } } return false; }, mouseUpZoom: function () { this.options.actionState = false; //关闭选中功能 document.body.onselectstart=function(){} } }; $.fn.Drag = function (options) { return this.each(function() { var drag = new Drag(options); drag.init(); }); }; })(jQuery,window,document);
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; outline: 0; font-size: 100%; vertical-align: baseline; background: transparent; } h1, h2, h3, h4, h5, h6, em, i { font-weight: 100; font-style: normal } ul, ol, li { list-style-type: none } a { color: #666; text-decoration: none; outline: 0 } a:hover { text-decoration: none } [class^="icon-"], [class*=" icon-"] { display: inline-block; width: 48px; height: 48px; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; line-height: 1; /* Better Font Rendering =========== */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .icon-group { background: url("../images/icon_group.png") no-repeat center; } .icon-cross { background: url("../images/icon_cross.png") no-repeat center; } .icon-area { background: url("../images/icon_area.png") no-repeat center; } .icon-axis { background: url("../images/icon_axis.png") no-repeat center; } .icon-bar { background: url("../images/icon_bar.png") no-repeat center; } .icon-combine { background: url("../images/icon_combine.png") no-repeat center; } .icon-complex { background: url("../images/icon_complex.png") no-repeat center; } .icon-donut { background: url("../images/icon_donut.png") no-repeat center; } .icon-dot { background: url("../images/icon_dot.png") no-repeat center; } .icon-pie { background: url("../images/icon_pie.png") no-repeat center; } .icon-line { background: url("../images/icon_line.png") no-repeat center; } .icon-home:before { content: "\e900"; } .clearfix, .clearfix:before, .clearfix:after { content: " "; display: block; } .dr-icon-group-aid { -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); -webkit-border-radius: 2px 2px 2px 2px; -moz-border-radius: 2px 2px 2px 2px; border-radius: 2px 2px 2px 2px; } .dr-float-layout { position: absolute; left: 0; top: 0; right: 0; bottom: 0; width: 100%; height: 100%; background-color: #eee; } .dr-flex-center-layout { display: box; display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-box-orient: horizontal; -webkit-flex-direction: row; -moz-flex-direction: row; -ms-flex-direction: row; -o-flex-direction: row; flex-direction: row; -webkit-box-pack: center; -webkit-justify-content: center; -moz-justify-content: center; -ms-justify-content: center; -o-justify-content: center; justify-content: center; -webkit-box-align: center; -webkit-align-items: center; -moz-align-items: center; -ms-align-items: center; -o-align-items: center; align-items: center } .dr-icon-group, .dr-v-add-layout { display: inline-block; } .dr-button-group { position: relative; float: left; width: 48px; height: 48px; } .dr-icon-group { position: absolute; left: 20px; top: 10px; bottom: 10px; width: 100px; height: auto; background-color: #fff; } .dr-icon-group ul { position: relative; width: 96px; height: auto; margin: 0 auto 10px; } .dr-icon-group ul li { margin-top: 15px; text-align: center; } .dr-icon-group ul li dl { position: relative; } .dr-icon-group ul li dd { flex-shrink: 0; position: absolute; left: 35px; top:0; z-index: 66; display: none; width: 36px; padding: 10px; cursor: pointer; background-color: white; border: 1px solid#ccc; } .dr-button-group i { font-size: 24px; } .dr-v-add-layout{ position: absolute; left: 140px; right: 10px; top: 10px; bottom: 0px; } .dr-fit-lists { position: relative; width: inherit; height:inherit; } .move-sk { position: fixed; left: 0; top: 0; z-index: 100; width: 10px; height: 10px; background-color: #5BBCB9; } .dr-fit-list { position: absolute; left:0; top:0; padding: 10px; } .dr-fit-main { width: 100%; height: 80%; margin-top: 15px; } .dr-absolute-layout { position: relative; width: 100%; height:100%; } .dr-fit-list:hover .dr-drag-bar, .dr-fit-list:hover .dr-fit-widget, .dr-fit-list:hover .dr-absolute-resize{ visibility:visible; } .dr-drag-bar { visibility:visible; width: 100%; height: 10px; background-color: #cccccc; } .dr-fit-widget { position: absolute; right: 0; top:11px; z-index:11; visibility:visible; float: right; } .dr-absolute-resize { /*position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 12;*/ visibility:hidden; width: 100%; height: 100%; } .dr-absolute-resize div { width: 10px; height: 10px; background-color:#666666; } .dr-resize-top-left { position: absolute; left: -10px; top:-10px; z-index: 11; } .dr-resize-top { position: absolute; left: 50%; top:-10px; z-index: 11; margin-left: -5px; } .dr-resize-top-right { position: absolute; right: -10px; top:-10px; z-index: 11; } .dr-resize-left { position: absolute; left: -10px; top:50%; z-index: 11; margin-top: -5px; } .dr-resize-right { position: absolute; right: -10px; top:50%; z-index: 11; margin-top: -5px; } .dr-resize-bottom-left { position: absolute; left: -10px; bottom:-10px; z-index: 11; } .dr-resize-bottom { position: absolute; left: 50%; bottom:-10px; z-index: 11; margin-top: -5px; margin-left: -5px; } .dr-resize-bottom-right { position: absolute; right: -10px; bottom:-10px; z-index: 11; } .dr-fit-list:hover .dr-resize-top-left, .dr-fit-list:hover .dr-resize-bottom-right{ cursor: nw-resize; } .dr-fit-list:hover .dr-resize-top, .dr-fit-list:hover .dr-resize-bottom{ cursor: n-resize; } .dr-fit-list:hover .dr-resize-top-right, .dr-fit-list:hover .dr-resize-bottom-left{ cursor: ne-resize; } .dr-fit-list:hover .dr-resize-left, .dr-fit-list:hover .dr-resize-right{ cursor: w-resize; } /*表格*/ .table-responsive { min-height: .01%; overflow-x: auto; } .table { width: 100%; max-width: 100%; margin-bottom: 20px; background-color: white; } .table-bordered { border: 1px solid #ddd; } .table-bordered { border: 1px solid #ddd; } .table-bordered > thead > tr > th, .table-bordered > tbody > tr > th, .table-bordered > tfoot > tr > th, .table-bordered > thead > tr > td, .table-bordered > tbody > tr > td, .table-bordered > tfoot > tr > td { border: 1px solid #ddd; } .table-bordered > thead > tr > th, .table-bordered > thead > tr > td { border-bottom-width: 2px; } .table-bordered > thead > tr > th, .table-bordered > thead > tr > td { border-left: none; border-top: none; } .table-hover > tbody > tr:hover { background-color: #f5f5f5; } table { border-collapse:collapse; background-color: transparent; } caption { padding-top: 8px; padding-bottom: 8px; color: #777; text-align: left; } th { text-align: left; } .table { width: 100%; max-width: 100%; margin-bottom: 20px; } .table > thead > tr > th, .table > tbody > tr > th, .table > tfoot > tr > th, .table > thead > tr > td, .table > tbody > tr > td, .table > tfoot > tr > td { padding: 8px; line-height: 1.42857143; vertical-align: top; border-top: 1px solid #ddd; } .table > thead > tr > th { vertical-align: bottom; border-bottom: 2px solid #ddd; } .table > thead:first-child > tr:first-child > th, .table > thead:first-child > tr:first-child > td { border-top: 0; } .table > tbody + tbody { border-top: 2px solid #ddd; } .table .table { background-color: #fff; }