-1

Createjs text position changed after chrome version upgrade from 70 to 71. please guide me.

Lanny
  • 11,244
  • 1
  • 22
  • 30

4 Answers4

6

I didn't like the current proposed solutions (changing the lineHeight or the line count) because they're not very reliable with different fonts, styles and sizes ... so I rolled my own solution:

var cache = {}
createjs.Text.prototype._drawTextLine = function (ctx, text, y) {
    this.textBaseline = ctx.textBaseline = "alphabetic";
    if (!(this.font in cache)) {
        var metrics = this.getMetrics();
        cache[this.font] = metrics.vOffset;
    }
    var offset = cache[this.font];
    if (this.outline) {
        ctx.strokeText(text, 0, y - offset, this.maxWidth || 0xFFFF);
    } else {
        ctx.fillText(text, 0, y - offset, this.maxWidth || 0xFFFF);
    }
};

The alphabetic value of textBaseline is the most reliable crossbrowser and generally the standard nowadays.

When it's set to both the Text instance and the CanvasRenderingContext2D, we can call getMetrics and have vOffset of the font from the top of it's bounding box to its baseline.

Apply that offset to the fillText call and you generally get a decent rendering of the font. The cache is there for good measure to avoid re-measuring the metrics of the same fonts on every frame.

From the (limited amount of) tests I ran so far, it seems to be:

  • pretty stable crossbrowser
  • performance conscious
  • very close to the expected font rendering (as seen in Animate) showing just some minor offsets at high font sizes

And yet, some fonts still sucks (ie. Poppins) but I suspect it's a "fault" of the font itself in this case.


Hopefully @lanny will have an official fix in createjs soon, but there's no guarantee when that will be included in Animate sadly.

alebianco
  • 2,475
  • 18
  • 25
  • 1
    This is great! I can look at getting this integrated next week. – Lanny Jan 18 '19 at 20:03
  • Nice, thanks man. You guys can probably integrate that way better than I did. Having to use it with Animate I had to find a minimal monkey-patch to apply from "the outside" ;) – alebianco Jan 19 '19 at 21:51
1

This is an intentional change in Chrome to bring it inline with the "correct" behaviour (which Firefox has had all along). Here is more information. It looks like that Chrome 71 (and later releases) finally addresses that bug.

The only affected alignment is "top", which is the default. Here is a quick comparison between the two Chrome versions.

chrome text alignment comparison

We are considering a built-in solution in EaselJS since this is more impactful then when it was just Firefox that was the outlier.

Lanny
  • 11,244
  • 1
  • 22
  • 30
1

The issue can be solved similarly by overriding "_drawTextLine" in the same Text.js class as described here: https://forums.adobe.com/message/10845543#10845543.

The actual problem with this issue is that different fonts classic, google or adobe (former typekit) behave differently. I am looking for a solution that would normalize font alignment regardless its type or nature.

See an example below. Browser Chrome version 71

Without fix it is

enter image description here

With _drawTextLine fix

enter image description here

Suraj Kumar
  • 5,547
  • 8
  • 20
  • 42
0

Just patched it (only tested with my team and with the Open Sans font) by a simple check on the current user agent and forcing the count property to 0.2 (just tested it with the logic of 1.2 * lineHeight in mind, and it works) instead of 0. Basicaly it will just push down the text by 20% of the lineHeight property.

Be careful, it's not an offical patch, it works for me but it's not battle tested.

Add this code at the begining of the file src/easeljs/display/Text.js (thanks to is.js for the browser detection code):

var userAgent = (navigator && navigator.userAgent || "").toLowerCase();
var vendor = (navigator && navigator.vendor || "").toLowerCase();
var isChrome = /google inc/.test(vendor) ? userAgent.match(/(?:chrome|crios)\/(\d+)/) : null;

And at the line 348, replace the next line:

var maxW = 0, count = 0;

By this one:

var maxW = 0, count = isChrome ? 0.2 : 0;

Of course i'm opened to suggestions and improvments ! :)

Thanks!

Thomas H
  • 81
  • 1
  • 8