preface

Currently, I am working on a project of dynamic table, but I cannot determine the column width of the table because I cannot know the specific content of each column, and the unified setting will lead to crowded contents in some columns and empty contents in others, resulting in poor overall vision.

To analyze problems

For Ant Design’s Table component column, if width is not set, all columns will split the width of the Table, resulting in some Table header display problems, so we definitely need to specify the column width for each column. Now the question is how to accurately calculate the pixel value of the string length returned in the background.

Q: Can the column width be determined by the number of characters returned in the background? A: can’t. First of all, we have no way to know the type of characters returned in the background, whether it is pure Chinese or contains English, numbers, special characters, etc. That would make our calculations inaccurate

To solve the problem

This paper uses Canvas canvas to measure strings.

Front knowledge

Canvas [portal] create a canvas object document. The createElement method (” canvas “) HTMLCanvasElement. GetContext () method to obtain the element of context, the image will be rendered in the later CanvasRenderingContext2D. MeasureText () method returns a text TextMetrics about measured object contains information (such as the width of its TextMetrics. Width).

** Note: the canvas> element itself has no drawing capability (it's just a container for graphics) - you must use scripts to do the actual drawing. The getContext() method returns an object that provides methods and properties for drawing on the canvasCopy the code

Here’s how to measure the actual length of text

Function getTextWidth(text,) function getTextWidth(text, font="14px Microsoft YaHei") { const canvas = document.createElement("canvas"); let context = canvas.getContext("2d"); context.font = font let textmetrics = context.measureText(text) return textmetrics.width; }Copy the code

Adaptive column width table

The first edition

// Define a Map to receive the length values of each column
  let widthMap = new Map(a)// Columns are a header array of dynamic tables. Data is an array of data
// Get the longest line and write down its width
  data.forEach(target= > {
    for(let key in target) {
      if(target.hasOwnProperty(key)) {
        let keyWidth = getTextWidth(target[key])
        let curValue = widthMap.get(key)
        // If the field has a value, put it into the array
        widthMap.set(key, Math.max(curValue,keyWidth))
      }
    }
  })

// Select the maximum column width to ensure that the table header is not newline. 35 is the padding + border around the title
columns.map((item) = >{
    // title and dataIndex are parameters corresponding to ant Design Table
    let textWidth = getTextWidth(item.title) 
    if(widthMap.get(item.dataIndex) < textWidth) {
      widthMap.set(item.dataIndex, textWidth)
    }
    return item.width = Math.ceil(widthMap.get(item.dataIndex)) + 35} <Table columns={columns} dataSource={data} bordered rowKey={record= > record.id}
/>
Copy the code

Advantages: Each column can be seen at a glance. Disadvantages: Each row may be empty due to the different length of the background returned contents

Scope of application: uniform length of content list.

The second edition

  // Define a Map to receive the length values of each column
  let widthMap = new Map(a)// Columns are a header array of dynamic tables. Data is an array of data
  // Write down the width of each column
  data.forEach(target= > {
    for(let key in target) {
      if(target.hasOwnProperty(key)) {
        let keyWidth = getTextWidth(target[key])
        // If the field has a value, put it into the array
         widthMap.has(key) ? widthMap.set(key,widthMap.get(key).concat(keyWidth)) : widthMap.set(key,[].concat(keyWidth ? keyWidth : [] ))
      }
    }
  })
  
   // Calculate the average value to ensure that the column width is as balanced as possible
  for(let [mapKey] of widthMap) {
    let valueArr = widthMap.get(mapKey)
    let len = valueArr.length
    let value = valueArr.reduce((acc, cur) = > acc + 1/cur,0)
    widthMap.set(mapKey, len/value)
  }

  // Select the maximum column width to ensure that the table header is not newline. 35 is the padding + border around the title
  columns.map((item) = >{
    // title and dataIndex are parameters corresponding to ant Design Table
    let textWidth = getTextWidth(item.title) 
    if(widthMap.get(item.dataIndex) < textWidth) {
      widthMap.set(item.dataIndex, textWidth)
    }
    return item.width = Math.ceil(widthMap.get(item.dataIndex)) + 35} <Table columns={columns} dataSource={data} bordered rowKey={record= > record.id}
/>
Copy the code

Advantages: the width of each column is relatively reasonable, and the visual is more beautiful

conclusion

Generally speaking, it meets the requirements. If the table contains a large amount of data, the calculation amount of this method will increase accordingly. It is recommended that the first 20 rows of data be taken as the standard column width mean value for a large amount of data.

If it helps, please give a thumbs-up ❤ Thanks! End scatter flower ~~

Reference documentation

[canvas – MDN] blog.csdn.net/qiao_qiao_h…