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…