Canvas 希腊语 google 字体无法正确呈现

Canvas Greek google fonts not rendering correctly

我认为这是一个错误,但如果你们知道任何解决方法,请告诉我。

首先,字体加载101%。

  1. 我同步加载Google种字体

  2. 我定期检查以确保字体已加载。

  3. 我使用 canvas 成功地将字符串转换为图像(使用以下函数)(当 我用英文字符)

  4. 渲染几个英文字符后,我尝试渲染一个希腊字符 word 但 canvas 退回到浏览器默认字体。

  5. Firefox 没有任何问题,它运行良好。问题是 Chrome.

Bellow 是根据给定字符串在左上角创建色带标签背景图像的函数(PS:此函数 return imageData 稍后将与其他 imageData 合并):

ImageProcessor.prototype.createLabelImageData = function ( str, size, font, color, backgroundColor, shadowColor, shadowOffsetX, shadowOffsetY, shadowBlur, width, height ) {

    this.canvas.width = width || this.settings.width;
    this.canvas.height = height || this.settings.height;
    this.ctx.clearRect( 0, 0, this.canvas.width, this.canvas.height );

    this.ctx.font = "Bold " + ( size || 64 ) + "px " + ( font || "Arial" );
    this.ctx.textAlign = "center";
    this.ctx.textBaseline = "middle";

    var labelHeight = ( size || 64 ) + ( ( size || 64 ) / 4 );
    var labelTop = this.canvas.height / 2 - labelHeight / 2;
    var labelWidth = this.canvas.width;

    var strLen = this.ctx.measureText( str + "    " ).width;
    var side = Math.sqrt( ( strLen * strLen ) / 2 );
    var distance = Math.sqrt( ( side * side ) - ( ( strLen / 2 ) * ( strLen / 2 ) ) );

    this.ctx.save();
    this.ctx.rotate( -Math.PI / 4 );
    this.ctx.translate( -this.canvas.width / 2, -this.canvas.height / 2 + distance );

    this.ctx.fillStyle = ( backgroundColor || '#f00' );
    this.ctx.beginPath();
    this.ctx.moveTo( 0, labelTop );
    this.ctx.lineTo( labelWidth, labelTop );
    this.ctx.lineTo( labelWidth, labelTop + labelHeight );
    this.ctx.lineTo( 0, labelTop + labelHeight );
    this.ctx.closePath();
    this.ctx.fill();

    if ( shadowColor ) {

        this.ctx.shadowColor = shadowColor;
        this.ctx.shadowOffsetX = ( shadowOffsetX || 0 );
        this.ctx.shadowOffsetY = ( shadowOffsetY || 0 );
        this.ctx.shadowBlur = ( shadowBlur || size || 64 );

    }

    this.ctx.fillStyle = ( color || "#fff" );
    this.ctx.fillText( str, this.canvas.width / 2, this.canvas.height / 2 );
    this.ctx.restore();

    var imageData = this.ctx.getImageData( 0, 0, this.canvas.width, this.canvas.height );

    this.canvas.width = this.settings.width;
    this.canvas.height = this.settings.height;

    return imageData;

};

经过一些测试、反复试验和许多小时的阅读...

我发现在canvas中要使用字体时,是否已经下载并不重要。在其他任何事情和任何检查之前对我有用的是创建 n*2 div 元素(n 加载的字体数)并将它们定位在视口之外。 n*2 因为在一些我添加了 font-weight:bold.

底线是您希望在 canvas 中使用的确切字体必须是:

  1. 预加载
  2. 使用所有语言的 innerHTML 文本创建一个虚拟 dom 元素 变体(在我的例子中是拉丁语和希腊语)。

请注意,您必须为字体的粗体变体创建额外的元素。

这是我目前用来预加载字体并确保它们在 canvas 中可用的代码。

Vise.prototype.initializeFonts = function ( settings, globalCallback ) {



    var that = this; // reference to parent class



    /********************************************
     ********************************************
     **
     **
     **     Default settings
     **
     **
     ********************************************
     ********************************************/



    var defaults = {
        interval: 100,
        timeout: 10000,
        families: [
            'Open+Sans+Condensed:300,300italic,700:latin,greek',
            'Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800:latin,greek',
            'Roboto+Condensed:300italic,400italic,700italic,400,700,300:latin,greek',
            'Roboto:400,100,100italic,300,300italic,400italic,500,500italic,700,700italic,900,900italic:latin,greek'
        ]
    };

    // initialization

    this.fonts = new Fonts( $.extend( true, defaults, settings ) );
    this.fonts.onload = globalCallback;
    this.fonts.load();

};



/********************************************
 ********************************************
 **
 **
 **     Fonts class
 **
 **
 ********************************************
 ********************************************/



function Fonts( settings ) {

    this.settings = settings;
    this.success = [];
    this.fail = [];
    this.interval = null;
    this.elapsedTime = this.settings.interval;
    this.fontDetective = new Detector();

}

Fonts.prototype.load = function () {

    WebFont.load( {
        google: {
            families: this.settings.families
        }
    } );

    for ( var i in this.settings.families ) {

        var el, elBold;
        var familyStr = this.settings.families[ i ];
        var family = familyStr.split( ':' )[ 0 ].replace( /[+]/gi, ' ' );

        el = document.createElement( "div" );
        el.innerHTML = "Font loader  Φόρτωμα γραμματοσειράς";
        el.style.fontFamily = family;
        el.style.color = "#f00";
        el.style.position = "fixed";
        el.style.zIndex = 9999;
        el.style.left = "9999px";
        document.body.appendChild( el );

        elBold = document.createElement( "div" );
        elBold.innerHTML = "Font loader  Φόρτωμα γραμματοσειράς";
        elBold.style.fontFamily = family;
        elBold.style.fontWeight = "bold";
        elBold.style.color = "#f00";
        elBold.style.position = "fixed";
        elBold.style.zIndex = 9999;
        elBold.style.left = "9999px";
        document.body.appendChild( elBold );

    }

    this.interval = setInterval( this.areLoaded.bind( this ), this.settings.interval );

};

Fonts.prototype.areLoaded = function () {

    for ( var i in this.settings.families ) {

        var familyStr = this.settings.families[ i ];
        var family = familyStr.split( ':' )[ 0 ].replace( /[+]/gi, ' ' );
        var successIdx, failIdx;

        if ( this.fontDetective.detect( family ) ) {

            successIdx = this.success.indexOf( family );
            failIdx = this.fail.indexOf( family );

            if ( successIdx === -1 ) {
                this.success.push( family );
                console.log( "[" + family + "] was successfully loaded." );
            }

            if ( failIdx > -1 ) {
                this.fail.splice( failIdx, 1 );
            }

        } else {

            successIdx = this.success.indexOf( family );
            failIdx = this.fail.indexOf( family );

            if ( successIdx > -1 ) {
                this.success.splice( successIdx, 1 );
            }

            if ( failIdx === -1 ) {
                this.fail.push( family );
            }

        }

    }

    if ( this.elapsedTime >= this.settings.timeout ) {

        clearInterval( this.interval );

        var err = new Error( "Unable to load fonts: " + this.fail.toString() );

        this.onload( err, null );

        return;
    }

    if ( this.success.length === this.settings.families.length ) {

        clearInterval( this.interval );

        this.onload( null, null );

        return;
    }

    this.elapsedTime += this.settings.interval;

};

这对我有用,以防其他人在 chrome 上遇到同样的问题。

PS:看看我在代码中使用的 fontdetect.js