ECharts

I haven’t written anything in the last two months because I prepared for an exam. I just got out on Saturday. I came back to post what I have done in the past two months. I will mainly use part of the visualization of Echarts, combined with the previous G2 to share the graphical things done. (This article is taken from the actual code with key notes)

Echarts

The ECharts section has about four parts:

  1. ECharts map use;
  2. Bar chart scroll and click selected events;
  3. Use of parallel coordinate system;
  4. Plus a score bar;

The map

1, take a look at the map, first in Echarts map use, annotated code must be very comfortable ~ ~

<div id="echartMap" style="width: 100%; height:100%"></div> // 100% width and height is necessaryMethods: {initMapCharts(data, init) {const that = this
      that.chartMap = echarts.init(document.getElementById('echartMap'))
      that.chartMap.clear() // It is used to clear the image sample, whether initialization or switching projects will clear the map sample, not clear the example setoption your map will have problems
      
      let sum = 0// This is the total number of fields in the upper right corner, tied directly to the HTML template
      for (let i of that.regionScore.scores) {
        sum += i.score
      }
      
      that.regionScore.scores.forEach(e= > {
        let num = e.score / sum
        e.itemStyle = {}
        e.itemStyle.areaColor = `rgba(24,${num * 500}, 255, 1) `
        if (that.isActiveCity == e.regionCode) {
          e.selected = true
        } else {
          e.selected = false}})// This method is very important, based on the score of different regions, take a color value ratio to get a blue RGBA based on the score percentage, and add a selected attribute to each region object
      
      axios.get('/echarts/chengdu.json').then(function(res) { // Here we call the local JSON file of Chengdu region to render the map
        echarts.registerMap('chengdu', res.data) 
        that.chartMap.setOption({ // Map configuration items
          backgroundColor: 'rgba(182,216,255,0)'.selectedMode: 'single'.// Click mode
          // Return string modification using formatter for tooltips that are moved to a locale to display the current locale name score and ranking
          tooltip: {
            trigger: 'item'.backgroundColor: 'rgba (4,35,134,0.38)'.borderWidth: 1.borderColor: '#0e6de9'.showDelay: 0.hideDelay: 0.enterable: true.transitionDuration: 0.extraCssText: 'z-index:100'.formatter: function(params) {
              let res = `<div style="padding: 5px">
															<span>${params.name}</span><br/> <span style="font-size: 10px; Word-break: break-all "> <span style="color: # 00ffff; color: # 00ffff; font-size: 18px; line-height: 30px">NO.${that.regionScore.scores[params.dataIndex].rank}</span><br/> <span style="font-size: 10px; Word-break: break-all "> <span style="color: # 00ffff; color: # 00ffff; font-size: 18px; line-height: 30px">${that.regionScore.scores[params.dataIndex].score}</span>
													 </div>`
              return res
            }
          },
          
          geo: {.....................// The configuration item is relatively simple
          },
          series: [{type: 'map'.mapType: 'chengdu'.roam: true.scaleLimit: {
                min: '1'
              },
              zoom: 1.2.label: {
                normal: {
                  show: true.color: '#fff'.fontWeight: '100'.fontSize: '8'.formatter: text= > {
                    if (text.name === 'Chongzhou') {
                      return 'Chongzhou'
                    }
                    // There is a problem with the coordinates of Chongzhou city, by formatting and adding blank lines, push the text to the right to solve the problem, it seems that the text coordinates in JSON are not accurate}},emphasis: {
                  show: true}},itemStyle: {
                normal: {
                  areaColor: '# 999'.borderColor: '#0a003e'.borderWidth: 0.4.shadowColor: 'rgba (19,57,108,0.45)'
                },
                emphasis: {
                  areaColor: '#05C5FF'}},data: that.regionScore.scores
            }
          ]
        })
      })
      if (init) {//init stands for resetting the map. It is used when initializing the map.
        that.chartMap.on('click'.function(params) { // Since there are listening events for the map, if you perform the map listening again for the second rendering, all your click events will be triggered twice
          // Click the map event, the other three parts of the data linkage
          if (that.regionCode == that.regionScore.scores[params.dataIndex].regionCode) {
            that.regionCode = that.regionScore.regionCode
            that.isActiveCity = null
            that.isActiveDepart = null
            that.title = ' '
          } else {
            that.regionCode = that.regionScore.scores[params.dataIndex].regionCode
            that.isActiveCity = that.regionScore.scores[params.dataIndex].regionCode
            that.isActiveDepart = null
            let item = that.regionScore.scores.find(
              v= > v.regionCode == that.regionScore.scores[params.dataIndex].regionCode
            )
            if (item) {
              that.title = item.name
            } else {
              that.title = ' '
            }
          }
          that.componentIndex = null
          that.dataIndex = null
          that.getRegionIndicatorScore()
          that.getDepartScore()
        })
      }
    },
}
Copy the code

It should be clear after looking at the annotated code, then add a few more tips:

First of all, map the json data, can be in datav.aliyun.com/tools/atlas… We can also write an interface to call json of different regions. Of course, I only used Chengdu, so I stored a local copy of Chengdu.

The second point is the data at the end of the map. During the setoption to the map, I processed the object. Let’s take a look at the example of the processed object:

	{
		itemStyle: {areaColor: "rgba(24,290.4191616766467, 255,1)"} // Define the color values for each region block individually
		name: "Qingyang District" // The map is special, and the map is judged by the Chinese region name of name
		rank: 1
		regionCode: "510104"
		score: 97
		scores: null
		selected: false // This will make the current region selected by default, which is used to rank cities under the map. Click selected, and the map will also switch to the selected state of the corresponding region
	}
Copy the code

If (that.isActivecity == e.gionCode), isActiveCity is the city code in the city ranking below I selected.

The problem is that every time you click on the city ranking below, you have to refresh the map to select the corresponding city on the top map, and the map flashes.

Then, because the map through the Name of the Chinese region to judge the rendering, also requires the background to upload the name of the region must be consistent with your region Chinese name, I really ran into the background to upload a region, I can not render the map into the data, later check the region has long been renamed, the background specially changed library…

Oh, yeah, and zoom in and out is Roam, so this is a configuration item, so it’s easy to customize.

Bar scroll plus click

{
	that.chartBar.setOption({
        backgroundColor: 'rgba (61,93,255,0)'.legend: {
          bottom: 20.right: 20.textStyle: {
            color: '#fff'
          },
          itemHeight: 10.itemWidth: 10.selectedMode: true.// The mode of legend selection controls whether the display state of series can be changed by clicking legend. (Bug opening style)
          data: ['Government reply'.'Answer by business'.'System Access'] // Legend array, 3 kinds of new data for each item
        },
        grid: {.../ / to omit
        },
        tooltip: {
          show: trueAnd...// Just like the last one
          formatter: function(params) {
            let res = `<div style="padding: 5px">
															<span>${params.name} -- ${params.seriesName}</span><br/> <span style="font-size: 10px; Word-break: break-all "> <span style="color: # 00ffff; color: # 00ffff; font-size: 18px; line-height: 30px">${params.value}</span>
												 </div>`
            return res
          }
        },
        yAxis: {.../ / to omit
        },
        xAxis: [{.../ / to omit
            axisLabel: {
              inside: false.interval: '0'.showMinLabel: 'false'.textStyle: {
                color: function(value, index) {
                // Check type to set the color of the font selected
                  if (that.cityData[0].type) {
                    return that.cityData[index].type == 1 ? 'rgb(255, 39, 124)' : 'rgb(0, 193, 170)'
                  } else {
                    return index == that.dataIndex ? '#00fff0' : 'RGB (224224224).}},fontWeight: that.cityData[0].type ? 'bold' : 'normal'.fontSize: '12'
              },
              formatter: function(value) {
                // The name of the X-axis unit is too long
                if (value.length > 4) {
                  return value.substring(0.4) + '\n' + value.substring(4, value.length)
                } else {
                  return value
                }
              }
            },
            data: that.cityData.map(i= > i.indicatorName) // X-axis background array
          },
          {
            type: 'category'And.../ / to omit
            data: that.cityData.map(i= > i.indicatorName) // The X-axis displays the array}].dataZoom:
          that.cityData.length > 9 // Set scrolling for more than 9 entries
            ? {
                show: true.realtime: true.fillerColor: 'rgba(6, 123, 201)'.backgroundColor: '# 020254'.borderColor: 'rgba (197197197,0.3)'.left: 150.bottom: 30.showDetail: false.height: 8.width: '60%'.start: 0.end: 60}, {show: false
              },
        series: [{name: 'Government reply'.type: 'bar'And.../ / to omit
            data: that.cityData.map(i= > i.governmentScore)
          },
          {
            name: 'Answer by business'.type: 'bar'And.../ / to omit
            data: that.cityData.map(i= > i.businessScore)
          },
          {
            name: 'System Access'.type: 'bar'And.../ / to omit
            data: that.cityData.map(i= > i.otherScore)
          }
        ]
      })
}
Copy the code

This focus is not so much, the code is almost clear, set scrolling, and click color change. Then click on the event:

if (init) {
        that.chartBar.on('click'.function(params) {
          if (that.isActiveDepart) {
            // Do not click indicators when selecting departments
          } else {
            if (that.componentIndex == params.componentIndex && that.dataIndex == params.dataIndex) {
              that.componentIndex = null
              that.dataIndex = null
              return
            } else {
              that.componentIndex = params.componentIndex // The selected data category is 0 government /1 enterprise /2 external
              that.dataIndex = params.dataIndex // Select the X-axis index option index
              that.indicatorTitle = params.name// This is the title name
              that.getDepartScore(that.cityData[params.dataIndex].indicatorId)
              that.getIndicatorRank(that.cityData[params.dataIndex].indicatorId)
            }
            that.initBarCharts()
            myChart.off('click')}}}Copy the code

There is nothing too fancy about it. The scrolling effect is achieved by scaling the dataZoom bar to a certain width and removing the detail. The code is very detailed

The progress bar

Echarts is Ant Design’s component of the progress bar. Tip: Switch the color of the progress bar by judging the value to achieve different rank and different color

<a-progress
    v-if="item.score! ==null"
     :strokeColor="(item.score < 60 ? '#FF5543' : '') || (item.score > 80 ? '#00C277' : '')"
     :strokeWidth="4"
     status="active"
     :percent="item.score"
     :format="percent => `${percent}`"
/>
Copy the code

Parallel coordinate system

    initParallelCharts() {
      const that = this
      var data = []
      let dataItem = that.parallelData.find(v= > {
        let objLength = Object.keys(v.data)
        if (objLength.length > 0) {
          return v
        }
      }) // Object standard, used to supplement the case when data is null
      if (dataItem == undefined) {
        that.noData = true
        return
      } else {
        that.noData = false
      }
      // No data is rendered
      
      let lineStyle = {
          width: 2.opacity: 1
      } // Line style configuration
      
      var series = [] / / the series configuration items
      for (let i of that.parallelData) {
        let arr = [[]]
        let seriesObj = {}
        let hasData = JSON.stringify(i.data) ! ='{}'
        // There is data in this area. If there is no data, the background returns an empty object. By default, the foreground adds an object attribute with a value of 0
        if (hasData) {
          for (let j in i.data) {
            arr[0].push(i.data[j])
          }
        } else {
          for (let j in dataItem.data) {
            arr[0].push(0)
          }
        }
        seriesObj = { name: i.region.name, type: 'parallel', lineStyle, data: arr }
        series.push(seriesObj)
        data.push(arr)
      }

      var schema = []
      let num = 0
      for (let i in dataItem.data) {
        let obj = { name: i, text: i, index: num }
        num += 1
        schema.push(obj)
      }


      let parallelAxis = [] / / parallelAxis configuration items
      for (let i = 0; i < schema.length; i++) {
        parallelAxis.push({
          dim: i,
          name: schema[i].text
        })
      }

      let legendName = []
      for (let i of that.parallelData) {
        legendName.push(i.region.name)
      }
      that.echartParallel = echarts.init(document.getElementById('echartParallel'))
      that.echartParallel.setOption({
        legend: {
          bottom: 0.data: legendName,
          itemGap: 15.itemWidth: 5.itemHeight: 5.textStyle: {
            color: '#F0F2F5'.fontSize: 13}},parallelAxis: parallelAxis,

        parallel:... ./ / to omit
        series
      })
    },
Copy the code

Take a look at an example of processed data:

legendName:["Jinniu District".Wuhou District."Qingyang District"."Jinjiang District"].parallelAxis: [{dim: 0.name: "Cost"}, {dim: 1.name: "Time"}, {dim: 2.name: "Link"}].series: [{data: [[89.2.70.70]]// If this is a two-dimensional array, there can be multiple lines
	lineStyle: {width: 2.opacity: 1}
	name: "Qingyang District"
	type: "parallel"}...... ]Copy the code

LegendName stores pure strings, parallelAxis stores Y coordinate unit names, and legendName stores legendName, legendName stores Y coordinate unit names. LegendName stores legendName, legendName stores Y coordinate unit names. LegendName stores legendName, legendName stores Y coordinate unit names.

Assumes that the series of data in an array, it is a legend corresponds to a line, the data which contain multiple arrays is more than a legend corresponding data, and the inside of the data array to store the value of the y axis as the index of parallelAxis corresponding. Actually look also understand ~

G2

G2, a sub-product of Ant Financial’s data visualization solution AntV, is a data-driven, highly interactive visual graphics syntax.

Look a few better, usage is similar, but the concept has a gap, community slightly chicken ribs, specific can understand oneself. Then I would like to share with you some of the G2 issues that we have documented previously:

  1. Legend uses a scroll bar.
  2. Add center text and legend percentage to Nightingale chart;
  3. G2 package overloading problem;

The legend legend uses scroll bars

First look at the effect:

this.chart.legend({ // marker: 'square', position: 'right-center', // textStyle: { fill: '#a3a9c1' }, // offsetX: 20. itemFormatter(val) { let labe = data.find(v => v.content == val).percent return `${val} ${parseInt(labe / sum * 100)}%` }else{}, useHtml: true,// Draw the legend with Html flipPage: true,// Legend out of the container whether to scroll containerTpl: '<div class="g2-legend" style="position:absolute; top:20px; right:60px; width:auto;" >' + '<h4 class="g2-legend-title"></h4>' + '<ul class="g2-legend-list" style="list-style-type:none; margin:0; padding:0;" ></ul>' + '</div>',// itemTpl: '<li class="g2-legend-list-item item-{index} {checked}" style="margin-right: 24px" data-color="{originColor}" data-value="{originValue}">' + '<i class="g2-legend-marker" style="background-color:{color};" > < / I > '+' < span class = "g2 - legend - text" > {value} < / span > < / li > '} / / graphic)Copy the code

Nightingale chart adds center text as well as legend percentage

First look at the effect:

  • Center text setting
this.chart.guide().html({
          position: ['50%'.'50%'].html: `<div style="color:#fff; font-size: 25px; text-align: center; width: 10em;" >${total}<br><div style="color:#fff; font-size:14px; Text-align: center"> </div></div>.alignX: 'middle'.alignY: 'middle'
})

Copy the code
  • Percentage setting
This.chart. legend({marker: 'square', position: 'right-center', textStyle: {fill: '#a3a9c1', fontSize: '12'}, itemFormatter(val) { let labe = data.find(v => v.title == val).population return `${val} ${parseInt(labe / sum * 100)}%` // val is the text value for each legend item}})Copy the code

chart.guide().html(cfg)

Auxiliary HTML.

chart.guide().html({
  position: { object } | { function } | { array }, // The center of the HTML
  htmlContent: { string }, / / HTML code
  alignX: { string }, // HTML horizontal layout, can be 'left', 'middle', 'right'
  alignY: { string }, // HTML vertical layout, can be 'top', 'middle', 'bottom'
  offsetX: { number },
  offsetY: { number },
  zIndex: { number },
});
Copy the code

G2 package component overload problem

G2 updates data in three main ways:

  • Just update the data on the chart
  • Clean everything up and redraw it
  • Updates when using DataView

If you need to update the chart immediately, use chart.changeData(data) :

chart.changeData(newData);
Copy the code

The view also supports view.changeData(data). If you are just updating the data and don’t need to update the chart immediately, you can call chart.source(data) or chart.repaint() when you need to update the chart.

chart.source(newData);

chart.guide().clear();/ / clean up the guide
chart.repaint();
Copy the code

Clean graph syntax: When updating data, you can also clear all elements on the graph, redefine graph syntax, and redraw

chart.line().position('x*y');

chart.render();

chart.clear(); // Clear all
chart.source(newData); // Reload the data
chart.interval().position('x*y').color('z');
chart.render();

Copy the code

The key point is:

  1. Do not instantiate chart in the initialization method
  2. Save this instance
  3. Overloaded methods don’t go to New Chart
  4. Directly execute chart.changeData ()

I write articles are generally to share their own learning exploration journey, may be more useful to more entry-level front-end or from the entry-level to advanced front-end developers, welcome to praise encourage and comment: V :v:

Feel useful for praise hahaha ~~