/** * 创建者:王成 * 创建日期:2021年12月10日 * 描述:自定义ECharts */ /** * 构造函数 * @param {JSON} options 选项 */ function CrCharts(options) { this._init(options); this.click = options.click; } /** * 原型设置 必须的 * @param {JSON} options 选项 */ CrCharts.prototype.extend = function(options) { for (var key in options) { CrCharts.prototype[key] = options[key]; } } /** * 内部函数集合 */ CrCharts.prototype.extend({ /** * 初始化函数 * @param {JSON} options 选项 */ _init: function(options) { if (options.domId == undefined) { console.error('未设置显示容器!') return; } var self = this; //局部变量 this.selector = options.domId; //3D地图容器 this.chart = echarts.init(document.getElementById(this.selector)); /* 添加事件 */ this.chart.on('click', function(params) { if (self.click != undefined) { self.click(params); } }); this.splitLine = { show: true, lineStyle: { type: 'dashed', color: 'rgba(69,69,69,0.3)', } }; this.xAxisLine = { show: true, lineStyle: { color: "rgba(69,69,69,1.0)" }, }; this.xAxisLabel = { color: "rgba(69,69,69,1.0)", fontSize: 12, fontFamily: 'TTTGB-Medium', interval: 0, }; this.yAxisLine = { show: true, lineStyle: { color: "rgba(69,69,69,1.0)" }, }; this.yAxisLabel = { color: "rgba(69,69,69,1.0)", fontSize: 12, fontFamily: 'TTTGB-Medium', }; }, /** * 结合坐标Map和数值数组 构建创建地图点的数据数组 * @param {Map} geoCoordMap 包含name字段 * @param {JSON数组} data 内部的JSON包含{name: value:} */ _convertData: function(geoCoordMap, data) { var res = []; for (var i = 0; i < data.length; i++) { var geoCoord = geoCoordMap[data[i].name]; if (geoCoord) { res.push({ name: data[i].name, value: geoCoord.concat(data[i].name).concat(data[i].value), }); } } return res; }, /** * 动态轨迹线数据转换 * @param {JSON数组} data [{from:[] to:}] * @param {String} type 类型 undefined 代表创建动态路径 而其他则代表创建底线 */ _convertLines: function(data, fromMap, toMap, type) { var res = []; for (var i = 0; i < data.length; i++) { var dataLines = data[i]; for (var idx = 0; idx < dataLines.from.length; idx++) { var coords = []; coords.push(fromMap[dataLines.from[idx]]); coords.push(toMap[dataLines.to]); if (type == undefined) { res.push({ coords: coords, }) } else { res.push({ coords: coords, lineStyle: { color: 'rgb(34,115,141)', width: 1.0, curveness: -0.4, opacity: 0.9, } }) } } } return res; }, /** * 创建地图配置 * @param {Object} minValue 区间最小值 * @param {Object} maxValue 区间最大值 */ _createVisualMap: function(minValue, maxValue) { return { min: minValue, max: maxValue, realtime: true, //拖拽时是否实时更新 calculable: false, //是否显示拖拽的手柄 show: false, //是否显示拖拽手柄 inRange: { color: ['lightskyblue', 'yellow', 'orangered'] } } }, /** * 创建地图 * @param {Object} registerName 注册名称 * @param {Object} propertyName 默认属性名称 */ _createGeo: function(registerName, propertyName) { return { map: registerName, roam: false, aspectScale: 1.0, //默认显示的地图宽高比 label: { show: false, color: "#fff" }, itemStyle: { areaColor: 'rgb(20,41,87)', borderColor: 'rgb(34,115,141)', borderWidth: 3, shadowColor: 'rgb(0, 180, 255)', shadowBlur: 20, opacity: 0.8, }, emphasis: { itemStyle: { areaColor: 'rgb(128,128,128)', } }, scaleLimit: { //滚轮缩放的极限控制 min: 1.2, //缩放最小大小 max: 6 //缩放最大大小 }, nameProperty: propertyName, } }, /** * 斜线纹理 */ _decalSlant: function() { return { color: "rgba(0, 0, 0, 0.2)", dashArrayX: [1, 0], dashArrayY: [2, 5], symbolSize: 1, rotation: 0.523598775598298, dirty: false, symbol: "rect", symbolKeepAspect: true, backgroundColor: null, maxTileWidth: 512, maxTileHeight: 512, }; }, /** * 圆形纹理 */ _decalCircle: function() { return { color: "rgba(0, 0, 0, 0.2)", dashArrayX: [ [8, 8], [0, 8, 8, 0] ], dashArrayY: [6, 0], symbolSize: 0.8, rotation: 0, dirty: false, symbol: "circle", symbolKeepAspect: true, backgroundColor: null, maxTileWidth: 512, maxTileHeight: 512, }; }, /** * 十字交叉纹理 */ _decalCross: function() { return { color: "rgba(0, 0, 0, 0.2)", dashArrayX: [ [1, 0], [1, 6] ], dashArrayY: [1, 0, 6, 0], symbolSize: 1.0, rotation: 0.7853981633974483, dirty: false, symbol: "rect", symbolKeepAspect: true, backgroundColor: null, maxTileWidth: 512, maxTileHeight: 512, } }, /** * 矩形方块 */ _decalRect: function() { return { color: "rgba(0, 0, 0, 0.2)", dashArrayX: [ [6, 6], [0, 6, 6, 0] ], dashArrayY: [6, 0], symbolSize: 1, rotation: 0, dirty: false, symbol: "rect", symbolKeepAspect: true, backgroundColor: null, maxTileWidth: 512, maxTileHeight: 512, }; }, /** * 三角形 */ _decalTriangle: function() { return { color: "rgba(0, 0, 0, 0.2)", dashArrayX: [ [9, 9], [0, 9, 9, 0] ], dashArrayY: [7, 2], symbolSize: 1, rotation: 0, dirty: false, symbol: "triangle", symbolKeepAspect: true, backgroundColor: null, maxTileWidth: 512, maxTileHeight: 512, }; } }); /** * 基础方法 */ CrCharts.prototype.extend({ /** * 清除全部内容 */ clear: function() { this.chart.clear(); }, /** * 释放资源 */ dispose: function() { if(this.chart != null && this.chart != "" && this.chart != undefined) this.chart.dispose(); }, }); /** * 对外函数 */ CrCharts.prototype.extend({ /** * 创建搬迁地图 * @param {Object} jsonFile 地图的JSON文件 * @param {Object} lines 运动线集合 * @param {Object} villageMap 村庄坐标Map * @param {Object} villageValue 村庄数据集合 * @param {Object} communityMap 社区坐标Map * @param {Object} communityValue 社区数据集合 */ CreateMap: function(jsonFile, lines, villageMap, villageValue, communityMap, communityValue) { var self = this; var series = []; series.push({ type: 'map', map: 'village', roam: false, itemStyle: { areaColor: 'rgb(20,41,87)', borderColor: 'rgb(34,115,141)', borderWidth: 1, }, emphasis: { itemStyle: { areaColor: 'rgb(128,128,128)', }, label: { color: 'rgb(255,255,255)', } }, nameProperty: 'XZQMC', aspectScale: 1.0, //默认显示的地图宽高比 scaleLimit: { //滚轮缩放的极限控制 min: 1.2, //缩放最小大小 max: 6 //缩放最大大小 }, }); series.push({ type: 'lines', zlevel: 999, animation: false, effect: { show: true, //是否显示特效 period: 7, //特效动画的重复时间 trailLength: 0.1, //尾迹线的长度[0-1]值越大,越长 color: 'rgb(255,255,255)', symbol: 'circle', symbolSize: [4, 4] }, lineStyle: { color: '#fff', width: 2.0, curveness: -0.4 }, data: self._convertLines(lines, villageMap, communityMap, undefined) }); series.push({ name: '线条', type: 'lines', coordinateSystem: 'geo', data: self._convertLines(lines, villageMap, communityMap, '') }) series.push({ name: '户数', type: 'scatter', coordinateSystem: 'geo', data: self._convertData(villageMap, villageValue), symbolSize: function(val) { return (val[3] * 4) / 1036 + 6; }, label: { show: false, position: 'right', color: 'rgb(162,200,82)', fontWeight: 'bold', fontFamily: 'TTTGB-Medium', shadowColor: 'rgb(255,255,255)', shadowBlur: '200', textBorderColor: 'rgb(255,255,255)', textBorderWidth: 0, formatter: '{b}', }, emphasis: { itemStyle: { borderColor: '#fff', borderWidth: 1 } } }); series.push({ name: '社区', type: 'effectScatter', coordinateSystem: 'geo', data: self._convertData(communityMap, communityValue), symbolSize: function(val) { return 10; }, label: { show: true, position: 'right', color: 'rgb(255,255,255)', fontWeight: 'bold', fontFamily: 'SimHei', fontSize: 14, formatter: '{b}', }, emphasis: { itemStyle: { borderColor: '#fff', borderWidth: 1 } } }); $.get(jsonFile, function(geoJson) { echarts.registerMap('village', geoJson); var option = { visualMap: self._createVisualMap(93, 1129), geo: self._createGeo('village', 'XZQMC'), series: series, } self.chart.setOption(option); }); } }); /** * 图形函数 */ CrCharts.prototype.extend({ /** * 创建饼图 * @param {JOSN} jsonData 数据 * @param {String} title 标题 */ createPie: function(jsonData, title) { var self = this; var decals = []; for (var i = 0; i < jsonData.data.length; i++) { var idx = i % 5; if (idx == 0) { decals.push(self._decalSlant()); } else if (idx == 1) { decals.push(self._decalCircle()); } else if (idx == 2) { decals.push(self._decalRect()); } else if (idx == 3) { decals.push(self._decalCross()); } else if (idx == 4) { decals.push(self._decalTriangle()); } } var option = { tooltip: { trigger: 'item' }, aria: { enabled: true, decal: { show: true, decals: decals, } }, stateAnimation: { duration: 300, easing: "cubicOut", }, animation: "auto", animationDuration: 1000, animationDurationUpdate: 500, animationEasing: "cubicInOut", animationEasingUpdate: "cubicInOut", animationThreshold: 2000, series: [{ name: title, type: 'pie', radius: jsonData.radius == undefined ? [10, 90] : jsonData.radius, center: ['50%', '50%'], roseType: 'radius', startAngle: jsonData.startAngle == undefined ? 10 : jsonData.startAngle, label: { formatter: '{a|{b}}{abg|}\n{hr|}\n{per|{d}%}', rich: { a: { color: 'rgb(69,69,69)', lineHeight: 22, align: 'center', fontFamily: 'TTTGB-Medium', fontSize: 13, }, hr: { borderColor: 'rgb(69,69,69)', width: '100%', borderWidth: 1, height: 0 }, b: { color: '#4C5058', fontSize: 10, fontWeight: 'bold', lineHeight: 33 }, per: { color: 'rgb(123,149,248)', align: 'center', fontFamily: 'TTTGB-Medium', lineHeight: 20, } } }, labelLine: { lineStyle: { color: 'rgb(69,69,69)', }, }, labelLayout: { draggable: false, //是否可以拖动标注 }, itemStyle: { borderRadius: 0, shadowColor: '#5cfbff', shadowBlur: 5, }, data: jsonData.data, }] }; self.chart.setOption(option); }, /** * 创建普通饼图 * @param {JOSN} jsonData 数据 * @param {String} title 标题 */ createNormalPie: function(jsonData, title) { var self = this; var option = { tooltip: { trigger: 'item' }, legend: { left: 'center', show: false, }, series: [{ name: title, type: 'pie', radius: ['40%', '80%'], center: ['50%', '50%'], label: { position: 'inside', formatter: '{a|{b}}{abg|}\n{per|{d}%}', rich: { a: { color: 'rgb(0,51,102)', lineHeight: 22, align: 'center', fontFamily: 'TTTGB-Medium', fontSize: 13, }, hr: { borderColor: '#fff', width: '100%', borderWidth: 2, height: 0 }, b: { color: '#4C5058', fontSize: 10, fontWeight: 'bold', lineHeight: 33 }, per: { color: '#ffff00', align: 'center', fontFamily: 'TTTGB-Medium', } } }, itemStyle: { borderRadius: 5, borderColor: 'rgb(255,255,255)', borderWidth: 0, shadowBlur: 1, }, data: jsonData, }] }; self.chart.setOption(option); }, /** * 创建横向柱状图 * @param {JSON} jsonData 横向柱状图数据 * grid:{JSON}{left: right: bottom: top: containLabel:true/false} * labels:[] * datas:[{name: values:[] color:[] lblColor: unit:}] * enabledAria:true/false */ createHorizontalBar: function(jsonData) { var self = this; var decals = []; decals.push(self._decalSlant()); var legendData = []; var series = []; for (var i = 0; i < jsonData.datas.length; i++) { var data = jsonData.datas[i]; legendData.push(data.name); /* 标签配置 */ var labelOption = { show: true, position: data.lblPosition == undefined ? 'left' : data.lblPosition, distance: data.lblPosition == undefined ? -10 : 10, align: 'left', verticalAlign: 'middle', rotate: 0, formatter: '{c}', fontSize: 12, color: data.lblColor, fontFamily: 'TTTGB-Medium', rich: { name: {} } }; /* 追加单位 */ if (data.unit != undefined) { labelOption.formatter += data.unit; } /* 追加服务 */ var item = { name: data.name, label: labelOption, type: 'bar', data: data.values, itemStyle: { shadowColor: '#5cfbff', shadowBlur: 5, } } if (data.color.length == 1) { item.itemStyle.color = data.color[0]; } else if (data.color.length >= 2) { item.itemStyle.color = { type: 'linear', x: 0, y: 0, x2: 1, y2: 0, colorStops: [{ offset: 0, color: data.color[0], // 0% 处的颜色 }, { offset: 1, color: data.color[1], // 100% 处的颜色 }], global: false // 缺省为 false }; } series.push(item); } /* 配置项 */ var option = { tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } }, aria: { enabled: jsonData.enabledAria == undefined ? false : jsonData.enabledAria, decal: { show: true, decals: decals, } }, legend: { show: jsonData.lenged == undefined ? true : jsonData.lenged.show, data: legendData, textStyle: { color: 'rgb(255,255,0)', } }, grid: jsonData.grid, xAxis: { type: 'value', boundaryGap: [0, 0.01], axisLabel: self.xAxisLabel, axisLine: self.xAxisLine, splitLine: self.splitLine, }, yAxis: { type: 'category', data: jsonData.labels, axisLabel: self.yAxisLabel, axisLine: self.yAxisLine, splitLine: self.splitLine, }, series: series, }; if (jsonData.zoom != undefined) { option.dataZoom = jsonData.zoom; } self.chart.setOption(option); }, /** * 创建竖向柱状图 * @param {JSON} jsonData 数据集 * @param {int} left 距离左侧的距离 * @param {boolean} enabledAria 是否使用花纹 * @param {array} units 单位名称 */ createVerticalBar: function(jsonData, left, enabledAria, units) { var self = this; var grid = { right: 3, bottom: jsonData.gridBottom != undefined ? jsonData.gridBottom : 20, top: 35, left: left == undefined ? 80 : left, }; if (jsonData.xrotate != undefined) { self.xAxisLabel.rotate = jsonData.xrotate; } var legendData = []; var xData = jsonData.labels; var servies = []; var decals = []; decals.push(self._decalSlant()); /*数据配置*/ for (var i = 0; i < jsonData.datas.length; i++) { var sData = jsonData.datas[i]; legendData.push(sData.name); /* 标签配置 */ var labelOption = { show: true, position: 'top', distance: 5, align: 'left', verticalAlign: 'middle', rotate: 90, formatter: function(param) { return param.value == 0.1 ? "" : param.value; }, fontSize: 10, color: 'rgb(69,69,69)', fontFamily: 'TTTGB-Medium', rich: { name: {} } }; if (sData.label != undefined) { if (sData.label.position != undefined) labelOption.position = sData.label .position; if (sData.label.rotate != undefined) labelOption.rotate = sData.label.rotate; if (sData.label.formatter != undefined) labelOption.formatter = sData.label .formatter; } var service = { name: sData.name, type: 'bar', label: labelOption, emphasis: { focus: 'series' }, data: sData.data, itemStyle: { color: sData.color, shadowColor: '#5cfbff', shadowBlur: 5, } }; if (sData.stack != undefined) service.stack = sData.stack; servies.push(service); } /* 图表配置 */ var option = { tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' }, formatter: function(params) { var strHtml = ""; strHtml += "