This is the 13th day of my participation in the August More Text Challenge.More challenges in August

preface

Visual development is one of the important branches of front-end development. Daily data needs require us to skillfully use open source visualization libraries such as Echarts, Antv and Highcharts. There may also be customization requirements that require a deeper understanding of SVG, canvas, and more. SVG has D3, Canvas has Zrender, etc.

Using Echarts as an example, this article explains how to use logarithmic functions in basic elementary functions to solve extreme data business scenarios. If you understand it, other chart libraries can also solve it by analogy.

Logarithmic function 🎈

The logarithm function is one of the six basic elementary functions. If a^x=N (a>0, and a≠1), then the number x is called the logarithm base A of N, called x=logaN, where a is called the base of the logarithm, and N is called the true number.

In general, the function y=logax (a>0, and a≠1) is called a logarithmic function.

As can be seen from the figure, with the increase of x, the growth trend of logarithm function becomes more and more gentle. The core idea of this paper is to use the slow growth of logarithm function.

Let’s get down to business

The business scenario

Simulate the service scenario. Product Manager: JS needs to show this data on a broken line chart. Back end: Returns real data similar to [212, 0, 0.001, 9, 1, 133, 13200]

As you can see, the current data is quite different. Take the Echarts configuration as shown below.

let option = {
    xAxis: {
      type: 'category'.name: 'x'.data: ['Mon'.'Tue'.'Wed'.'Thu'.'Fri'.'Sat'.'Sun']},toolbox: {
      show: true.feature: {
        saveAsImage: {
            type: 'png'}}},tooltip: {
      show: true.trigger: 'axis'
    },
    yAxis: {
      type: 'value'.name: 'y'.minorSplitLine: {
        show: true}},series: [{
      data: [212.0.0.001.9.1.133.13200].type: 'line'.smooth: true}};Copy the code

Product manager: The data difference is too big, this picture does not feel good, can you optimize it? Front end: This… That’s the real data. What can we do? (Pushing the pan) Just give me a minute. I’ll think about it first.

Scroll through the Echarts documentation and discover the axistypeAttributes arelogThe result is as follows, not quite the same as expected, as if the error was reported. 😅

If you look at the + search engine, it’s 0, because the domain of logarithm x is greater than 0. So I can change this to NULL. Figure is not a lot better, excited to call the product manager to see the effect.

let option = {
    xAxis: {
        type: 'category'.name: 'x'.data: ['Mon'.'Tue'.'Wed'.'Thu'.'Fri'.'Sat'.'Sun']},toolbox: {
      show: true.feature: {
        saveAsImage: {
            type: 'png'}}},tooltip: {
      show: true.trigger: 'axis'
    },
    yAxis: {
        type: 'log'.name: 'y'.minorSplitLine: {
            show: true}},series: [{
        data: [212.null.0.001.9.1.133.13200].type: 'line'.smooth: true}};Copy the code

Product Manager: Yeah, it looks much better, but why is it disconnected? Front end: Because the data is 0, no more. Product Manager: The demand is met, really want the line is connected together (push your luck 💢) front end:…

You have to say no, but you still have to think of a plan quickly and gracefully. Echarts doesn’t provide a solution, so it’s a waste of time to switch libraries and study again. It’s impossible to draw on a canvas. So how do we extend the idea of logarithms?

When turning over the concept of logarithm, I suddenly saw a sentence: exponential function is the inverse function of logarithm function.

  1. Let’s convert the original data into a logarithmic function.
  2. And then I’ll use the exponential function to convert it back.

In this case, +1 is required for raw data processing, and -1 is ok for display. Because the logarithm is negative in the range 0,1, and it approaches minus infinity as it goes to 0. When the chart data itself is positive, it is more misleading to map to negative numbers.

The transformation is successful, as shown in the picture below, the lines are connected, and the product manager is called over proudly. Product Manager: 👏. Front end: little things ~.

The code idea is as follows:

  1. Data conversionMath.log10(d + 1)Can.
  2. For displaying dataMath.pow(10, d) - 1. Chart aspect utilizationEchartsTo provide theformatterFormatted displayyandtooltip.

The specific code is as follows, plug and play, take to use directly!!

// Convert raw data
let transformToLog = (d) = > {
    return Math.log10(d + 1)}// Log to the original data
let transformToOrigin = (d) = > {
    return Math.pow(10, d) - 1
}
let orginData = [212.null.0.001.9.1.133.13200]

let option = {
    xAxis: {
      type: 'category'.data: ['Mon'.'Tue'.'Wed'.'Thu'.'Fri'.'Sat'.'Sun']},toolbox: {
      show: true.feature: {
        saveAsImage: {
            type: 'png'}}},tooltip: {
      show: true.trigger: 'axis'.formatter: function(params) {
          return params[0].axisValue + ':' + Number(transformToOrigin(params[0].value).toFixed(3}})),yAxis: {
      type: 'value'.axisLabel: {
        formatter: function(value, index) {
            if(value > 0) { return Math.pow(10, value)}
            return value
        }  
      },
      minorSplitLine: {
        show: true}},series: [{
      data: logData,
      type: 'line'.smooth: true}};Copy the code

The product needs are met, but the story is not over. After all, the title is extreme.

This is my own question, what if the data is negative, then this is not feasible? After all, the logarithm domain is greater than 0. So what? Since it’s negative, can we think of taking the absolute value.

  1. If it’s negative, you take the absolute value, you take the logarithm, and you multiply- 1.
  2. Display, then reverse operation can be.

[212, NULL, 0.001, 9, 1, -133, 13200] Let’s look at the resulting graph. Is it elegant?

// Convert raw data
let transformToLog = (d) = > {
    let operator = 1
    d < 0 && (operator = -1)
    return Math.log10(Math.abs(d) + 1) * operator
}
// Log to the original data
let transformToOrigin = (d) = > {
    let operator = 1
    d < 0 && (operator = -1)
    return (Math.pow(10, d * operator)) * operator - 1 * operator
}
let orginData = [212.null.0.001.9.1, -133.13200]
let logData = orginData.map(item= > transformToLog(item))

let option = {
    xAxis: {
      type: 'category'.data: ['Mon'.'Tue'.'Wed'.'Thu'.'Fri'.'Sat'.'Sun']},toolbox: {
      show: true.feature: {
        saveAsImage: {
            type: 'png'}}},tooltip: {
      show: true.trigger: 'axis'.formatter: function(params) {
          return params[0].axisValue + ':' + Number(transformToOrigin(params[0].value).toFixed(3}})),yAxis: {
      type: 'value'.axisLabel: {
        formatter: function(value, index) {
            let operator = 1
            if(value < 0) operator = -1
            if(value === 0) return 0
            return Math.pow(10, value * operator) * operator 
            
        }  
      },
      minorSplitLine: {
        show: true}},series: [{
      data: logData,
      type: 'line'.smooth: true}};Copy the code

conclusion

💗 thanks for the Gold digging activity in August, I can stick to it for a month, and I recorded the basic knowledge points and some tips with words. Fortunately, I also got some likes and attention, from LV1 to LV2, and really felt the joy of writing articles.

Most of the previous articles are JS based, next, I will share a more comprehensive point, such as CSS, Node, visualization, browser, etc., will continue to share their own care (combined with real business scenarios, absolutely nothing), such as this one, see everyone’s interest (in fact, look at the likes of the number, haha).

If this article has helped you, please like, follow and bookmark it!!

Of course, you are also welcome to comment, exchange and study, criticism and correction.