Echarts:实现拖拽效果
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <script src="./echarts.js"></script> 6 </head> 7 <body> 8 <div id="myChart" style="width: 800px; height: 600px;"></div> 9 10 <script type="text/javascript"> 11 var chart = echarts.init(document.getElementById('myChart')); 12 13 var originData = [ 14 {value: 335, name: '直接访问'}, 15 {value: 310, name: '邮件营销'}, 16 {value: 234, name: '联盟广告'}, 17 {value: 135, name: '视频广告'}, 18 {value: 1548, name: '搜索引擎'}, 19 ]; 20 21 var color = ['#4a6dbf', '#15b3bc', '#f37a18', '#83c775', ' #fcb552']; 22 23 originData.forEach(function(list, i) { 24 list.itemStyle = { 25 color: color[i], 26 }; 27 }); 28 29 var data = [].slice.call(originData) 30 31 var option = { 32 tooltip: { 33 }, 34 toolbox: { 35 feature: { 36 myRestore: { 37 show: true, 38 title: '还原', 39 icon: 'M3.8,33.4 M47,18.9h9.8V8.7 M56.3,20.1 C52.1,9,40.5,0.6,26.8,2.1C12.6,3.7,1.6,16.2,2.1,30.6 M13,41.1H3.1v10.2 M3.7,39.9c4.2,11.1,15.8,19.5,29.5,18 c14.2-1.6,25.2-14.1,24.7-28.5', 40 onclick: refreshChart, 41 }, 42 }, 43 }, 44 legend: { // 图例 45 icon: 'rect', 46 data: [], 47 itemWidth: 12, 48 itemHeight: 12, 49 bottom: 'bottom', 50 }, 51 grid: { 52 top: '5%', 53 left: '5%', 54 right: '5%', 55 bottom: '40', 56 containLabel: true, 57 }, 58 xAxis: { 59 type: 'category', 60 boundaryGap: true, 61 splitLine: { // grid上每一条竖轴线 62 show: true, 63 interval: 'auto', 64 lineStyle: { 65 color: '#e8e8e8', 66 }, 67 }, 68 axisLine: { // x刻度上方的横轴线 69 lineStyle: { 70 color: '#e8e8e8', 71 }, 72 }, 73 axisLabel: { // x轴的刻度 74 textStyle: { 75 color: '#999', 76 }, 77 }, 78 data: [], 79 }, 80 yAxis: { 81 type: 'value', 82 boundaryGap: false, 83 axisLine: { // y刻度上方的横轴线 84 lineStyle: { 85 color: '#e8e8e8', 86 }, 87 }, 88 splitLine: { // grid上每一条竖轴线 89 lineStyle: { 90 color: '#e8e8e8', 91 }, 92 }, 93 axisLabel: { // y轴的刻度 94 textStyle: { 95 color: '#999', 96 }, 97 }, 98 }, 99 series: [{ 100 name: 'pie', 101 type: 'pie', 102 center: ['50%', '45%'], 103 radius: ['0', '45%'], 104 data: data, 105 }, { 106 name: '模拟一个pie容器', 107 type: 'pie', 108 center: ['50%', '45%'], 109 radius: ['0', '49%'], 110 cursor: 'default', 111 hoverAnimation: true, 112 hoverOffset: 2, 113 label: { 114 show: false, 115 }, 116 labelLine: { 117 show: false, 118 }, 119 tooltip: { 120 padding: 0, 121 formatter: function() { 122 return ''; 123 }, 124 }, 125 z: 0, 126 data: [{ 127 value: 0, 128 name: '容器', 129 itemStyle: { 130 color: '#000', 131 opacity: '.1', 132 }, 133 }], 134 }], 135 }; 136 137 chart.setOption(option, true); 138 139 var sector = null; // 鼠标点击选中的扇形 140 var sectorIndex; // 选中扇形在data中的index 141 var sx; // 原型横坐标距离鼠标位置横坐标的偏移距离 142 var sy; // 原型纵坐标距离鼠标位置纵坐标的偏移距离 143 var zr = chart.getZr(); // 生成一个zrender实例 144 var circleData = null; // 记录鼠标选中的小圆点的数据 145 var circleEl = []; // 保存生成的小圆点的数据,注意目前只有push,没有将废数据清除 146 147 function refreshChart() { 148 data = [].slice.call(originData) 149 option.series = { 150 name: 'pie', 151 type: 'pie', 152 center: ['50%', '45%'], 153 radius: ['0', '45%'], 154 data: data, 155 }; 156 157 circleEl.forEach(function(list) { 158 zr.remove(list.el); 159 }); 160 // zr.clear(); // clear会把整个chart画布清除 161 sector = null; 162 chart.setOption(option, true); 163 } 164 165 // chart.on 绑定的事件只能在chart图形内部执行 166 // 利用chart绑定的事件会比zrender绑定的事件先执行的特点来判断小圆是否进入饼图范围 167 chart.on('mouseup', function(params) { 168 if (params.componentSubType === 'pie') { 169 // 圆 170 if (circleData) { 171 data.push(circleData.data); 172 chart.setOption({ 173 series: { 174 data: data, 175 } 176 }); 177 zr.remove(circleData.el); 178 circleData = null; 179 } 180 181 // 扇形 182 if (sector) { 183 zr.remove(sector); 184 sector = null; 185 } 186 } 187 }); 188 189 zr.on('mousedown', function(e) { 190 // 如果出现:触发鼠标点击扇形事件,并且移动到echarts的DOM元素外,释放鼠标点击, 191 // 再移动到饼图内,点击鼠标,则会再次触发一个鼠标点击和释放事件,这时候,上一个选中的扇形不会被正确的移除 192 // 所以在mosuedown多一个对sector的判定 193 if (e.target && sector) { 194 zr.remove(sector); 195 sector = null; 196 } 197 if (e.topTarget) { 198 // 这个是pie容器 199 if (e.target && e.target.seriesIndex === 1) { 200 return; 201 } 202 203 // 发现一个圆 204 circleEl.forEach(function(list) { 205 if (list.id === e.topTarget.id) { 206 circleData = list; 207 } 208 }); 209 210 // 是一个扇形 211 if (!circleData && e.target && !e.target.__title) { 212 var target = e.target; 213 sectorIndex = target.dataIndex; 214 sector = new echarts.graphic.Sector({ 215 shape: echarts.util.extend({}, target.shape), 216 style: { 217 fill: target.style.fill, 218 opacity: 0.5 219 }, 220 silent: true, 221 z: 1000, 222 }); 223 224 sx = e.offsetX - target.shape.cx; 225 sy = e.offsetY - target.shape.cy; 226 227 zr.add(sector); 228 229 } 230 } 231 }); 232 233 zr.on('mousemove', function (e) { 234 if (circleData) { 235 circleData.el.setShape({ 236 cx: e.offsetX, 237 cy: e.offsetY, 238 }); 239 } else if (sector) { 240 sector.setShape({ 241 cx: e.offsetX - sx, 242 cy: e.offsetY - sy, 243 }); 244 245 chart.dispatchAction({ 246 type: 'showTip', 247 seriesIndex: 0, 248 dataIndex: sectorIndex, 249 position: [e.offsetX + 24, e.offsetY + 24], // 加24是为了避免tip影响mouseup事件判定 250 }); 251 } 252 }); 253 254 zr.on('mouseup', function(e) { 255 if (circleData) { 256 circleData = null; 257 } if (sector) { 258 var circle = new echarts.graphic.Circle({ 259 shape: { 260 cx: e.offsetX, 261 cy: e.offsetY, 262 r: 10, 263 }, 264 style: { 265 text: data[sectorIndex].name + ':' + data[sectorIndex].value, 266 textFill: sector.style.fill, 267 fill: sector.style.fill, 268 textOffset: [0, -20], 269 }, 270 silent: true, 271 z: 1000, 272 }); 273 zr.add(circle); 274 circleEl.push({ 275 id: e.topTarget.id + 1, 276 el: circle, 277 data: data[sectorIndex], 278 }); 279 280 data.splice(sectorIndex, 1); 281 chart.setOption({ 282 series: { 283 data: data, 284 } 285 }); 286 287 zr.remove(sector); 288 sector = null; 289 } 290 }); 291 </script> 292 </body> 293 </html>
这个是一年前工作里用到,莫名翻了出来。