Canvas text collision detection and thinning

Demand background

Generally speaking, text thinning is used for map related requirements. I also implemented this method when I implemented a function for the company's map engine. Here, I simplified it and operated it on the ordinary Canvas without introducing the concept of map

Effect

collision detection

Calculate the range of text in canvas
// Calculate the width required for text
var p = {
    x: 10,
    y: 10,
    name: "Test text"
};
var measure = ctx.measureText(p.name);
// Find out the maximum y coordinate occupied by text in canvas drawing board
var maxX = measure.width + p.x;
// Find out the maximum y coordinate occupied by text in canvas drawing board
// canvas can only calculate the width of text, not the height of text. So we use the width of the text divided by the number of words to calculate the approximate value
var maxY = measure.width / p.name.length + p.y;

var min = { x: p.x, y: p.y };
var max = { x: maxX, y: maxY };
// bounds is the range that the text occupies in canvas.
// When taking point coordinates as the minimum range, textAlign and textBaseline will be set accurately in the following ways.
// If the setting is displayed in different positions, the maximum and minimum range points shall also be adjusted
// ctx.textAlign = "left";
// ctx.textBaseline = "top";
var bounds = new Bounds(min, max);

Bounds scope object

/**
* Define scope object
*/
function Bounds(min, max) {
    this.min = min;
    this.max = max;
}

/**
* Judge whether the range intersects another range
*/
Bounds.prototype.intersects = function(bounds) {
    var min = this.min,
    max = this.max,
    min2 = bounds.min,
    max2 = bounds.max,
    xIntersects = max2.x >= min.x && min2.x <= max.x,
    yIntersects = max2.y >= min.y && min2.y <= max.y;
    
    return xIntersects && yIntersects;
};
Testing
// Before each drawing, cross check the range with the drawn text
// If a cross is found, the current text will be discarded, otherwise it will be drawn and saved in the drawn text list
for (var index in _textBounds) {
    // Loop through all drawn text ranges to check whether there is an intersection with the current text range. If there is an intersection, the text will be skipped
    var pointBounds = _textBounds[index];
    if (pointBounds.intersects(bounds)) {
    return;
    }
}

_textBounds.push(bounds);
ctx.fillStyle = "red";
ctx.textAlign = "left";
ctx.textBaseline = "top";
ctx.fillText(p.name, p.x, p.y);

Example, code address

Example address: Example

See the complete code for details: Github address

Read the original text

Keywords: Front-end github

Added by m4x3vo on Mon, 04 Nov 2019 22:49:19 +0200