检测粗体和斜体的支持

时间:2013-01-23 21:05:07

标签: javascript css

某些字体不支持CSS斜体或粗体(例如Zapfino不支持斜体,因为它已经非常具有脚本效果)。我想检测何时不支持字体样式,因此我可以在编辑器中禁用样式按钮。

我尝试了like this

that.checkFontData = function( fontList )
{   var test = $("<span style='font-size:24px;absolute;visibility:hidden;height:auto;width:auto;white-space:nowrap;'>abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678910</span>");
    $('body').append( test );
    for (var i= 0, iMax = fontList.length; i < iMax; ++i)
    {   test.css( 'fontFamily', fontList[i] );
        var normalWidth = test.outerWidth( true );
        var normalHeight = test.outerHeight( true );
        test.css( 'fontStyle', 'italic' );
        var italicWidth = test.outerWidth( true );
        var italicHeight = test.outerHeight( true );
        test.css( 'fontStyle', 'normal' );
        test.css( 'fontWeight', 'bold' );
        var boldWidth = test.outerWidth( true );
        var boldHeight = test.outerHeight( true );
        console.log( fontList[i]  + ", normal: " + normalWidth + ", bold: " + boldWidth + ", italic: " + italicWidth  );
    }
    test.remove( );
};

但它不起作用...许多提供斜体或粗体的字体报告相同的宽度。

接下来,我想用canvas元素来检测它,但是,唉,firefox甚至没有在画布中呈现斜体文字,所以这样就让人想到了。

你会建议什么?

3 个答案:

答案 0 :(得分:4)

要检测粗体斜体支持,您可以将文本转换为图片并进行比较。

这样做的方法是:

  1. 创建canvas 见下文(无需将其附加到DOM)
  2. canvas
  3. 中绘制文字
  4. 将画布转换为图像(此处我使用png
  5. 比较图片的base64字符串
  6. 关于canvas

      

    接下来,我想用canvas元素来检测它,但是,唉,firefox甚至没有在画布中呈现斜体文字,所以这样就让人想到了。

    某些字体在Firefox中的画布中没有斜体,因为天然斜体字体不存在。其他浏览器会尝试伪造(倾斜)字体。

    View on jsFiddle (此演示还会测试Google字体Snowburst One

    function detectBoldItalic(fonts) {
        // Create canvas
        var canvas = document.createElement('canvas');
        canvas.width = 1000;
        canvas.height = 30;
        var context = canvas.getContext("2d");
        var test = {}, results = {};
        // Default
        context.font = "normal 16px a base case font";
        context.fillText("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678910", 10, 20);
        var standard = canvas.toDataURL("image/png");
        context.setTransform(1, 0, 0, 1, 0, 0);
        context.clearRect(0, 0, canvas.width, canvas.height);
        // Start test
        for (var i = 0; i < fonts.length; i++) {
            var styles = ["normal", "bold", "italic"];
            test[fonts[i]] = {};
            results[fonts[i]] = {};
            for (var j = 0; j < styles.length; j++) {
                // Draw text in canvas
                context.font = styles[j] + " 16px " + fonts[i];
                context.fillText("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678910", 10, 20);
                // Convert canvas to png
                test[fonts[i]][styles[j]] = canvas.toDataURL("image/png");
                // Clear canvas
                context.setTransform(1, 0, 0, 1, 0, 0);
                context.clearRect(0, 0, canvas.width, canvas.height);
            }
            if (test[fonts[i]]["normal"] !== standard) {
                results[fonts[i]]["bold"] = test[fonts[i]]["normal"] !== test[fonts[i]]["bold"] ? true:false; // Support bold
                results[fonts[i]]["italic"] = test[fonts[i]]["normal"] !== test[fonts[i]]["italic"] ? true:false; // Support italic
            } else {
                results[fonts[i]] = false; // Font does not exist
            }
        }
        return results;
    }
    console.log(detectBoldItalic(["Arial","Zapfino"]));
    

答案 1 :(得分:1)

我已经在jsFiddle中测试了您的代码,它确实为GeorgiaArial这样的自然网络字体提供了不同的尺寸,但是对于像Snowburst One这样的外部加载字体却没有(Googlefont) 。

JS fiddle of your script

经过一些研究后我发现,对于@font-face加载的字体,没有css字体转换适用。人们加载@font-face变体并按照以下方式应用它们:

body { font-family:"DroidSerifRegular", Georgia, serif; }
h1 {
    font-family:"DroidSerifBold", Georgia, serif;
    font-weight:normal;
}
em {
    font-family:"DroidSerifItalic", Georgia, serif;
    font-weight:normal;
    font-style:normal;
}
strong em {
    font-family:"DroidSerifBoldItalic", Georgia, serif;
    font-weight:normal;
    font-style:normal;
}

如果您使用的@font-face字体具有上述示例中的变体,则可能会提出某种命名约定。然后,您可以通过检查与后备字体相比的宽度来检查这些字体是否存在。

test.css('fontFamily', 'sans-serif');
var defaultWidth = test.outerWidth( true );

for (var i= 0, iMax = fontList.length; i < iMax; ++i)
{   test.css( 'fontFamily', fontList[i] + ', sans-serif' );

    var normalWidth = test.outerWidth( true );
    var normalHeight = test.outerHeight( true );
    test.css( 'fontFamily', fontList[i] + 'Italic, sans-serif' );
    var italicWidth = test.outerWidth( true );
    var italicHeight = test.outerHeight( true );
    test.css( 'fontFamily', fontList[i] + 'Bold, sans-serif' );
    var boldWidth = test.outerWidth( true );
    var boldHeight = test.outerHeight( true );
    console.log( "default: "+ defaultWidth + ", " fontList[i]  + ", normal: " + normalWidth + ", bold: " + boldWidth + ", italic: " + italicWidth  );
}

如果样式版本的宽度与默认版本相比有所改变,那么它就是“Bingo”!

注意:这不适用于等宽字体,因为所有字符的宽度始终相同。

答案 2 :(得分:0)

使用Font.js,您可以更可靠地访问计算的字体指标。 http://pomax.nihongoresources.com/pages/Font.js