ECharts实现拖拽
1、需求——如何在echarts中实现托拖拽的效果
2、解决方案
1、用Echarts的type为graph类型画图,优点:拖拽不用重新定点划线,有自带的连线关系,缺点:连线的样式及特效不能很好呈现
1//注意this.viewData是从后台获取的数据 mounted () { 2 const that = this 3 this.$nextTick(() => { 4 let myChart = echarts.init(document.getElementById(this.scaleLine_id)) 5 var home = "image:///img/bussiness.png"; //业务 6 var error_home = "image:///img/error-bussiness.png"; //故障业务 7 var windows = "image:///img/windows.png"; //windows主机 8 var error_windows = "image:///img/error-windows"; //故障windows 9 var linux = "image:///img/linux.png"; //linux 10 var error_linux = "image:///img/error-linux.png"; //故障linux 11 var cluster0 = "image:///img/cluster_0.png"; //web服务器 12 var error_cluster0 = "image:///img/error-cluster_0.png"; //故障web服务器 13 var cluster1 = "image:///img/cluster_1.png"; //数据库 14 var error_cluster1 = "image:///img/error-cluster_1.png"; //故障数据库 15 var cluster2 = "image:///img/cluster_2.png"; //消息队列 16 var error_cluster2 = "image:///img/error-cluster_2.png"; //故障消息队列 17 var cluster3 = "image:///img/cluster_3.png"; //缓存 18 var error_cluster3 = "image:///img/error-cluster_3.png"; //故障缓存 19 var cluster4 = "image:///img/cluster_4.png"; //文件系统 20 var error_cluster4 = "image:///img/error-cluster_4.png"; //故障文件系统 21 let labelOne = {//文字1省级市级五区 22 normal: { 23 position: "bottom", 24 distance:0, //离图标多远 25 show: true, 26 textStyle: { 27 fontSize: 15, 28 color:'#00eaff', 29 fontFamily:'microsoftYaHei' 30 }, 31 } 32 }; 33 let lineColorOne = new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ 34 offset: 0, 35 color: '#58B3CC' 36 }, { 37 offset: 1, 38 color: '#F58158' 39 }]) 40 let viewData = this.viewData 41 let data = [] 42 var symbolSize = 20; 43 // console.log(viewData) 44 //处理数据格式 45 for(let i = 0;i<viewData.element.length;i++){ 46 data.push(viewData.element[i].value) 47 if(viewData.element[i].type === 20){ 48 if(viewData.element[i].status === 1){ 49 viewData.element[i].symbol = home 50 viewData.element[i].symbolSize = 40 51 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 52 viewData.element[i].draggable = 'true' 53 viewData.element[i].fixed = 'true' 54 viewData.element[i].label = labelOne 55 }else{ 56 viewData.element[i].symbol = error_home 57 viewData.element[i].symbolSize = 40 58 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 59 viewData.element[i].draggable = 'true' 60 viewData.element[i].fixed = 'true' 61 viewData.element[i].label = labelOne 62 63 } 64 }else if(viewData.element[i].type === 10){ 65 if(viewData.element[i].status === 1){ 66 viewData.element[i].symbol = windows 67 viewData.element[i].symbolSize = 40 68 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 69 viewData.element[i].draggable = 'false' 70 viewData.element[i].fixed = 'true' 71 viewData.element[i].label = labelOne 72 }else{ 73 viewData.element[i].symbol = error_windows 74 viewData.element[i].symbolSize = 40 75 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 76 viewData.element[i].draggable = 'false' 77 viewData.element[i].fixed = 'true' 78 viewData.element[i].label = labelOne 79 80 } 81 82 }else if(viewData.element[i].type === 11){ 83 if(viewData.element[i].status === 1){ 84 viewData.element[i].symbol = linux 85 viewData.element[i].symbolSize = 40 86 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 87 viewData.element[i].draggable = 'false' 88 viewData.element[i].fixed = 'true' 89 viewData.element[i].label = labelOne 90 }else{ 91 viewData.element[i].symbol = error_linux 92 viewData.element[i].symbolSize = 40 93 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 94 viewData.element[i].draggable = 'false' 95 viewData.element[i].fixed = 'true' 96 viewData.element[i].label = labelOne 97 98 } 99 100 }else if(viewData.element[i].type === 0){ 101 if(viewData.element[i].status === 1){ 102 viewData.element[i].symbol = cluster0 103 viewData.element[i].symbolSize = 40 104 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 105 viewData.element[i].draggable = 'false' 106 viewData.element[i].fixed = 'true' 107 viewData.element[i].label = labelOne 108 }else{ 109 viewData.element[i].symbol = error_cluster0 110 viewData.element[i].symbolSize = 40 111 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 112 viewData.element[i].draggable = 'false' 113 viewData.element[i].fixed = 'true' 114 viewData.element[i].label = labelOne 115 116 } 117 118 }else if(viewData.element[i].type === 1) { 119 if(viewData.element[i].status === 1){ 120 viewData.element[i].symbol = cluster1 121 viewData.element[i].symbolSize = 40 122 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 123 viewData.element[i].draggable = 'false' 124 viewData.element[i].fixed = 'true' 125 viewData.element[i].label = labelOne 126 }else{ 127 viewData.element[i].symbol = error_cluster1 128 viewData.element[i].symbolSize = 40 129 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 130 viewData.element[i].draggable = 'false' 131 viewData.element[i].fixed = 'true' 132 viewData.element[i].label = labelOne 133 134 } 135 136 }else if(viewData.element[i].type === 2) { 137 if(viewData.element[i].status === 1){ 138 viewData.element[i].symbol = cluster2 139 viewData.element[i].symbolSize = 40 140 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 141 viewData.element[i].draggable = 'false' 142 viewData.element[i].fixed = 'true' 143 viewData.element[i].label = labelOne 144 }else{ 145 viewData.element[i].symbol = error_cluster2 146 viewData.element[i].symbolSize = 40 147 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 148 viewData.element[i].draggable = 'false' 149 viewData.element[i].fixed = 'true' 150 viewData.element[i].label = labelOne 151 152 } 153 154 }else if(viewData.element[i].type === 3) { 155 if(viewData.element[i].status === 1){ 156 viewData.element[i].symbol = cluster3 157 viewData.element[i].symbolSize = 40 158 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 159 viewData.element[i].draggable = 'false' 160 viewData.element[i].fixed = 'true' 161 viewData.element[i].label = labelOne 162 }else{ 163 viewData.element[i].symbol = error_cluster3 164 viewData.element[i].symbolSize = 40 165 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 166 viewData.element[i].draggable = 'false' 167 viewData.element[i].fixed = 'true' 168 viewData.element[i].label = labelOne 169 170 } 171 172 }else if(viewData.element[i].type === 4){ 173 if(viewData.element[i].status === 1){ 174 viewData.element[i].symbol = cluster4 175 viewData.element[i].symbolSize = 40 176 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 177 viewData.element[i].draggable = 'false' 178 viewData.element[i].fixed = 'true' 179 viewData.element[i].label = labelOne 180 }else{ 181 viewData.element[i].symbol = error_cluster4 182 viewData.element[i].symbolSize = 40 183 viewData.element[i].itemStyle = {"normal":{"color":"#F58158"}} 184 viewData.element[i].draggable = 'false' 185 viewData.element[i].fixed = 'true' 186 viewData.element[i].label = labelOne 187 188 } 189 190 } 191 } 192 var linkss = viewData.line.map((item,i)=>{ 193 return { 194 source:item.fromName.id, 195 target:item.toName.id, 196 197 } 198 }) 199 console.log(linkss) 200 const option = { 201 grid: { 202 left: '6%', 203 top: '1%', 204 bottom:'5%', 205 }, 206 textStyle: { 207 color: '#f00', 208 fontSize: 16, 209 fontWeight: 600, 210 }, 211 // tooltip: { 212 // // 表示不使用默认的『显示』『隐藏』触发规则。 213 // triggerOn: 'none', 214 // formatter: function (params) { 215 // return 'X: ' + params.data[0].toFixed(2) + '<br>Y: ' + params.data[1].toFixed(2); 216 // } 217 // }, 218 backgroundColor:"#013954", 219 // backgroundColor:"#fff", 220 animationDuration: 1500, 221 animationEasingUpdate: 'quinticInOut', 222 xAxis: { 223 show: false, 224 type: 'value', 225 axisLine: {onZero: false} 226 }, 227 yAxis: { 228 show: false, 229 type: 'value', 230 axisLine: {onZero: false} 231 }, 232 series: [ 233 { 234 id:'a', 235 type: 'graph', 236 coordinateSystem: 'cartesian2d', 237 legendHoverLink: false, 238 hoverAnimation: true, 239 nodeScaleRatio: false, 240 roam: false, 241 color: { 242 type: 'linear', 243 x: 0, 244 y: 0, 245 x2: 0, 246 y2: 1, 247 colorStops: [{ 248 offset: 0, color: 'red' // 0% 处的颜色 249 }, { 250 offset: 1, color: 'blue' // 100% 处的颜色 251 }], 252 global: false // 缺省为 false 253 }, 254 edges:linkss, 255 data: viewData.element, 256 }, 257 ] 258 }; 259 //折线点原本并没有拖拽功能,需要我们为它加上:使用 graphic 组件,在每个点上面,覆盖一个隐藏的可拖拽的圆点 260 myChart.setOption(option,true); 261 // onPointDragging(0)//初始化 262 console.log(myChart.getOption()) 263 myChart.setOption({ 264 graphic: echarts.util.map(data, function (dataItem, dataIndex) { 265 return { 266 // 'circle' 表示这个 graphic element 的类型是圆点。 267 type: 'circle', 268 shape: { 269 // 圆点的半径。 270 r: symbolSize 271 }, 272 position: myChart.convertToPixel('grid', dataItem), 273 invisible: true, 274 // 这个属性让圆点可以被拖拽。 275 draggable: true, 276 // 把 z 值设得比较大,表示这个圆点在最上方,能覆盖住已有的折线图的圆点。 277 z: 100, 278 ondrag: echarts.util.curry(onPointDragging, dataIndex), 279 // 在 mouseover 的时候显示,在 mouseout 的时候隐藏。 280 onmousemove: echarts.util.curry(showTooltip, dataIndex), 281 onmouseout: echarts.util.curry(hideTooltip, dataIndex), 282 }; 283 }) 284 }); 285 // 此函数中会根据拖拽后的新位置,改变 data 中的值,并用新的 data 值,重绘折线图,从而使折线图同步于被拖拽的隐藏圆点。 286 function onPointDragging(dataIndex) { 287 // 这里的 data 就是本文最初的代码块中声明的 data,在这里会被更新。 288 // 这里的 this 就是被拖拽的圆点。this.position 就是圆点当前的位置。 289 data[dataIndex] = myChart.convertFromPixel('grid', this.position); 290 let initIndex = that.viewData.element[dataIndex].value 291 viewData.element[dataIndex].value = data[dataIndex] 292 console.log( that, data[dataIndex]) 293 //元素位置改变后重新划线 294 // for(let i = 0;i < viewData.line.length;i ++){ 295 // if(viewData.line[i].fromName === viewData.element[dataIndex].id){ 296 // viewData.line[i].coords[0] = data[dataIndex] 297 // }else if(viewData.line[i].toName === viewData.element[dataIndex].id){ 298 // viewData.line[i].coords[1] = data[dataIndex] 299 // } 300 // } 301 // 用更新后的 data,重绘折线图。 302 myChart.setOption(option); 303 } 304 function showTooltip(dataIndex) { 305 myChart.dispatchAction({ 306 type: 'showTip', 307 seriesIndex: 0, 308 dataIndex: dataIndex 309 }); 310 } 311 function hideTooltip(dataIndex) { 312 myChart.dispatchAction({ 313 type: 'hideTip' 314 }); 315 } 316 // 最后,为了使 dom 尺寸改变时,图中的元素能自适应得变化 317 window.addEventListener('resize', function () { 318 // 对每个拖拽圆点重新计算位置,并用 setOption 更新。 319 myChart.setOption({ 320 graphic: echarts.util.map(data, function (item, dataIndex) { 321 return { 322 position: myChart.convertToPixel('grid', item) 323 }; 324 }) 325 }); 326 }); 327 //监听点击事件 328 myChart.on('click', function (params) { 329 console.log(params) 330 if(params.seriesType === "graph"){ 331 that.$emit('selectAsset',params.data.id) 332 } 333 //TODO 334 335 }); 336 // //添加右件菜单 337 // myChart.on("mousedown",function(e){ 338 // if(e.event.event.button===2){ 339 // //e中有当前节点信息 340 // showMenu(e,[ 341 // { 342 // "name": "菜单1", 343 // "fn": function() { 344 // alert("触发-菜单1" + e.data); 345 // console.log(e); 346 // } 347 // }, { 348 // "name": "菜单2", 349 // "fn": function() { 350 // alert("触发-菜单2" + e.data); 351 // } 352 // } 353 // ]); 354 // } 355 // }) 356 // 357 // var style_ul = "padding:0px;margin:0px;border: 1px solid #ccc;background-color: #fff;position: absolute;left: 0px;top: 0px;z-index: 2;display: none;"; 358 // var style_li = "list-style:none;padding: 5px; cursor: pointer; padding: 5px 20px;margin:0px;"; 359 // var style_li_hover = style_li + "background-color: #00A0E9; color: #fff;"; 360 // 361 // //右键菜单容器 362 // var menubox = $("<div class='echartboxMenu' style='" + style_ul + "'><div style='text-align:center;background:#ccc'></div><ul style='margin:0px;padding:0px;'></ul></div>") 363 // .appendTo($(document.body)); 364 // 365 // //移除浏览器右键菜单 366 // myChart.getDom().oncontextmenu = menubox[0].oncontextmenu = function(){ 367 // return false; 368 // } 369 // 370 // //点击其他位置隐藏菜单 371 // $(document).click(function() { 372 // menubox.hide() 373 // }); 374 // 375 // //显示菜单 376 // var showMenu = function(e,menus){ 377 // $("div", menubox).text(e.name); 378 // var menulistbox = $("ul", menubox).empty(); 379 // $(menus).each(function(i, item) { 380 // var li = $("<li style='" + style_li + "'>" + item.name + "</li>") 381 // .mouseenter(function() { 382 // $(this).attr("style", style_li_hover); 383 // }) 384 // .mouseleave(function() { 385 // $(this).attr("style", style_li); 386 // }) 387 // .click(function() { 388 // item["fn"].call(this); 389 // menubox.hide(); 390 // }); 391 // menulistbox.append(li); 392 // }); 393 // menubox.css({ 394 // "left": event.x, 395 // "top": event.y 396 // }).show(); 397 // } 398 399 /*窗口自适应,关键代码*/ 400 setTimeout(function (){ 401 window.onresize = function () { 402 myChart.resize(); 403 } 404 },200) 405 // window.addEventListener('resize', function () { 406 // myChart.resize(); 407 // }); 408 }) 409 },
2、元素用graph类型的画图,连线关系用type为line的关系描述,优点:连线的样式多样化,便于动态渲染。缺点:初始化的时候不显示线条
1 series: [ 2 { 3 id:'a', 4 type: 'graph', 5 coordinateSystem: 'cartesian2d', 6 legendHoverLink: false, 7 hoverAnimation: true, 8 nodeScaleRatio: false, 9 roam: false, 10 lineStyle: {//去掉自带的那条线,不要删 11 normal: { 12 width: 0, 13 shadowColor: 'none', 14 color: 'transparent' 15 }, 16 }, 17 data: viewData.element, 18 }, 19 { 20 type: 'lines', //大数据到块1,2,...n 21 coordinateSystem: 'cartesian2d', 22 z: 1, 23 // showAllSymbol:true, 24 effect: { 25 show: true, 26 smooth: true, 27 trailLength: 0, 28 symbol: "arrow", 29 color: '#ffc776', 30 symbolSize: 8, 31 period: 6, 32 loop: true, 33 }, 34 lineStyle: { 35 normal: { 36 curveness: 0, 37 color: lineColorOne, 38 width: 1, 39 } 40 }, 41 data:viewData.line, 42 } 43 ] 44 45 // 此函数中会根据拖拽后的新位置,改变 data 中的值,并用新的 data 值,重绘折线图,从而使折线图同步于被拖拽的隐藏圆点。 46 function onPointDragging(dataIndex) { 47 // 这里的 data 就是本文最初的代码块中声明的 data,在这里会被更新。 48 // 这里的 this 就是被拖拽的圆点。this.position 就是圆点当前的位置。 49 data[dataIndex] = myChart.convertFromPixel('grid', this.position); 50 let initIndex = that.viewData.element[dataIndex].value 51 viewData.element[dataIndex].value = data[dataIndex] 52 console.log( that, data[dataIndex]) 53 //元素位置改变后重新划线(关键代码) 54 for(let i = 0;i < viewData.line.length;i ++){ 55 if(viewData.line[i].fromName === viewData.element[dataIndex].id){ 56 viewData.line[i].coords[0] = data[dataIndex] 57 }else if(viewData.line[i].toName === viewData.element[dataIndex].id){ 58 viewData.line[i].coords[1] = data[dataIndex] 59 } 60 } 61 // 用更新后的 data,重绘折线图。 62 myChart.setOption(option); 63 } 64
1、需求——如何在echarts中实现托拖拽的效果
2、解决方案
1、用Echarts的type为graph类型画图,优点:拖拽不用重新定点划线,有自带的连线关系,缺点:连线的样式及特效不能很好呈现
关键代码:
代码块
2、元素用graph类型的画图,连线关系用type为line的关系描述,优点:连线的样式多样化,便于动态渲染。缺点:初始化的时候不显示线条
在以上的代码部分修改
代码块
默默搬砖中 ——假装自己是小白