Copyright notice: This article is the blogger’s original article, shall not be reproduced without the permission of the blogger. Please contact the author by leaving a comment at the bottom of the article.

The background,

In the actual development process, the UI design draft may be found to be quite different from the official sample diagram in order to make the graphics look good. As I’ve seen, with a bar chart as a background, each bar corresponds to the data of each point on the line chart and is displayed. As shown below, we will explain how to achieve it.

Second, graphic implementation

First of all, since I developed on the mobile side, I used the library ANTV/F2 for development. Because F2 is a visualization solution for mobile terminals, it is very convenient.

1. Install

npm install @antv/f2 --save
Copy the code

2. The introduction of

import F2 from '@antv/f2';
Copy the code

After F2 introduced the page, we were ready to create a chart.

3. Create charts

Create a

on the page and specify id:

<canvas id="chart" style={{ width: "90%".height: "200px"}} / >Copy the code

1) Create a Chart object and specify the Chart ID, width, height, margin and other information

In my demo, I only set pixelRatio below, and other attributes can be set according to your own needs, please refer to Chart

const lineChart = new F2.Chart({
    id: `chart`.// Specify the id of the canvas
    // pixelRatio pixelRatio of the screen canvas
    // Since the canvas will be blurred on the HD screen, 'pixelRatio' needs to be set. In general, the Settings are as follows
    pixelRatio: window.devicePixelRatio 
});
Copy the code

2) Data source processing

Because of the particularity of the graph, the data source needs special processing before use. Let’s look at the data source format we’re going to use:

const resData = [
    {
        date: "02.01".// Date: February 1st
        number: 0./ / value
        isDisplay: false  // mark whether the point is displayed
    },
    {
        date: "02.02".number: 119.isDisplay: true}... ]Copy the code

First we need to find the maximum value from the data source. If the returned data is empty, we need to set a default maximum value, 20 in this case, and override the value we found if the maximum value exists.

import { maxBy } from "lodash"; ./ / array
    let newDataArr = [];
    let maxDataItem = maxBy(resData, (o) = > o.number); // Find the maximum value
    let maximum = 20; // Default maximum value
    
    if (maxDataItem && maxDataItem.number) {
      maximum = maxDataItem.number; // If the maximum value exists, take the maximum value
    }
Copy the code

After this preparation, you must wonder what the maximum is used for.

Because when the data is returned blank, we only display the bar graph with gray background by default. The default maximum value is actually used to fill the gray background data, and the effect is shown below.

If the returned data exists, we need to modify the data and fill the grey histogram data with backupNumber:

// Return data is not null
if (resData.length) {
  resData.map((item) = > {
    // Add gray background data to each data source, where 10 is added to make the bar graph a little farther than the maximum point of the line graphnewDataArr.push({ ... item,backupNumber: maximum + 10 });
  });
}

Copy the code

If the data is empty, newDataArr is an empty array. To display a gray bar background as the default, populate the data manually. The default display is 14 columns.

// Data is empty using grey data fields
if(! newDataArr.length) {for (let i = 0; i < 14; i++) {
    newDataArr.push({
      date: i,
      isDisplay: false.backupNumber: maximum + 10}); }}Copy the code

The above data processing, the following for some special date display effect to do a processing:

We use the array xAxisTicks to record the x-coordinate display points, which will be used later when loading the data source.

  1. The dates of the first and last days are shown on the diagram

    • When the data source exists, the first day ([resData[0].date]) and the last day (resData[arrLength - 1].date) into the arrayxAxisTicks.
  2. Dates are displayed for points where isDisplay is true and marked on the line chart

    • To the data sourcemapTraverse, index each data homeindexField, useful for the next step
    • And then filter it outisDisplaytrueIs obtaineddisplayDotArr.
  3. If multiple consecutive dates need to be displayed, only the last consecutive date is displayed

    • To implement agetDisplayDotSortMethod that returns only the most pointy date after processing consecutive dates

The concrete implementation is as follows:

// Implement it
let arrLength; // Array length
let xAxisTicks = []; // the abscissa displays the point

// The data source exists
if (resData.length) {
    // Record the data source length
    arrLength = resData.length;
    // Date of the first day
    xAxisTicks = [resData[0].date];

    // Find the array of points to display
    let displayDotArr = resData
        .map((item, i) = > ({ ...item, index: i }))
        .filter((d) = > d.isDisplay);

    // The date array of the points to display
    getDisplayDotSort(displayDotArr).forEach((d) = > {
        xAxisTicks.push(d.date);
    });

    // The date of last day
    xAxisTicks.push(resData[arrLength - 1].date);
}
Copy the code

getDisplayDotSort

export const getDisplayDotSort = (array) = > {
  
  let res = [];
  // Iterate over the date array to display
  array.forEach((item, i) = > {
    // Set a temporary variable that can fetch the last 1 bit of the array
    let temp = res[res.length - 1] | | [];Temp temp temp temp temp temp temp temp temp temp temp temp temp temp temp temp temp temp temp
    if (item.index - temp[temp.length - 1].index === 1 ) {
      // All contiguous data are placed in an array
      temp.push(item);
    }
    // The other cases are placed in the array res
    else {
      [] is used to store each consecutive point as a group of data in an array, separated from non-adjacent points, and finally form a 2-dimensional arrayres.push([item]); }});// Cut consecutive points into arrays and return the last point of each array
  return res.map((v) = > v[v.length - 1]);
};
Copy the code

Last processedresIt’s a two-dimensional array, and you can see thatres[2]It’s a set of adjacent dates, and for adjacent dates, we just take the last date.

Processed data source:

const newDataArr = [
    {
        date: "02.01".// Date: February 1st
        number: 0./ / value
        backupNumber: 432.// Maximum gray background
        isDisplay: false  // mark whether the point is displayed
    },
    {
        date: "02.02".number: 119.isDisplay: true.backupNumber: 432}... ]Copy the code

The x-coordinate data of xAxisTicks after processing is as follows:

const xAxisTicks = ["02.01"."02.03"."02.07"."02.15"."02.18"]
Copy the code

So we’re done with the point we want to display on the x-coordinate.

3) Load the data source

For data Settings, refer to scale

// newDataArr processed data
lineChart.source(newDataArr, {
    // Configure each attribute
    number: {
        tickCount: 5.// The number of scale points on the coordinate axis. Different metric types correspond to different default values.
        min: 0        // Specify the minimum value manually
    },
    date: {
        type: "cat".// category, [' male ',' female '];
        range: [0.1].// The range of output data, the default value of numeric type is [0, 1],
        tickCount: 3.// Define the number of scale lines on the axis
        ticks: xAxisTicks // Specifies the text information used to specify the scale points on the coordinate axis. Here is the beginning, end and last point of continuous points}});Copy the code

4) Chart other configurations

Refer to the documentation for axis and Tooltip

lineChart.tooltip(false); // Hide the configuration information
lineChart.axis("number".false); // Close the Y axis corresponding to number. Line chart to display values
lineChart.axis("backupNumber".false); // Close the Y-axis corresponding to backupNumber. Gray bar graph

lineChart.axis("date", {
    label: (text, index, total) = > { // Set the bottom date x coordinate text
        const config = {};
        if (index === 0) {
            config.textAlign = "left"; // The first one is displayed on the left
        } else if (index === total - 1) {
            config.textAlign = "right"; // The last one is displayed on the right
        }

        return config;
    },
    line: null.// The axis is hidden
    labelOffset: 1 // Coordinate axis text distance axis distance
});
Copy the code

5) Create graphical syntax

Refer to document geometry notation and diagram types,

1. intervalCreate a histogram background

The geometric tag interval creates the bar chart, position determines the x – and Y-axis data fields, and color gradient Settings.

Color is a linear gradient:

lineChart
      .interval()
      // Map the 'date' data value to the x coordinate point and the 'backupNumber' data value to the y coordinate point
      .position("date*backupNumber")
      .color("L (90) 0: rgba (245245245,0.18) 1: # eee");
Copy the code

The effect is as follows:

2. lineCreate a line chart

The attributes used here are the same as above, style refer to here, and set fixed styles for all shapes. For specific Settings, see drawing properties

lineChart
    .line()
    .position("date*number")
    .color("#096dd9")
    .style({
      lineWidth: 1 // Set the line thickness property
    });
Copy the code

After superimposing the line chart, the effect is as follows:

3. pointCreate some figure

The size attribute here is the way to map data values to the size of the graph

Note: Different graphics have different meanings of size:

  • Size of the point graph affects the radius of the point.
  • Size in line, area, and path affects the thickness of the line.
  • The size of interval affects the width of the bar chart.
lineChart
      .point()
      .position("date*number")
      .color("#096dd9")
      .size("date*isDisplay".(date, isDisplay) = > {
        if (isDisplay) return 3; // The size of the point to display
        return 0; // Do not show the band you size is 0
      })
      .style({
        // Set a fixed style for all shapes
        lineWidth: 1.stroke: "#fff" // Draw the color of the graph
      });
Copy the code

The effect is as follows:

4. areaCreate area map

lineChart
      .area()
      .position("date*number")
      .color("L (90) : 0 # 096 dd9 1: rgba (9109217, 4)");
Copy the code

After superimposed area diagram:

6) Render charts

Render the chart, called at the end, so our chart is drawn:

lineChart.render();
Copy the code

The final result is as shown:

Click to see the full demo code above

reference

  • antv/f2
  • F2 Basic line chart example