브라우저가 표시 할 수있는 모든 글꼴 (또는 글꼴 계열)의 이름을 가져 오는 방법이 자바 스크립트에 있습니까? (사용자에게 사용 가능한 모든 글꼴 목록이있는 드롭 다운을 제공하고 사용자가 글꼴을 선택할 수 있도록 허용하고 싶습니다.)이 목록을 미리 하드 코딩하거나 서버에서 보내지 않아도됩니다. (직관적으로 브라우저는 어떤 글꼴이 있는지 알고 있어야하며 이는 어떻게 든 자바 스크립트에 노출되어야합니다.)
답변:
자바 스크립트 버전은 약간 불안정합니다. 알려진 글꼴과 테스트를 반복하여 글꼴을 얻습니다.
가장 정확한 방법 (독점 플러그인을 사용해야하지만)은 Flash 를 사용하는 것 입니다. 여기에서 치수를 사용하여 개별적으로 테스트 할 필요없이 글꼴 목록을 가져올 수 있습니다.
일부 장치 (iDevices, Flash 플러그인이없는 브라우저 등)에서 작동하지 않는 대신 정확한 목록을 가질 것인지 아니면 JavaScript를 통해서만 더 잘 지원 되는 일부 목록 을 가질 것인지 결정해야합니다 .
네, 있습니다! 나도이 질문을 사용하고 싶기 때문에이 질문을 해주셔서 감사합니다.
질문에 +1하고 답변은 다음과 같습니다. :)
http://www.lalit.org/lab/javascript-css-font-detect
코드 에서 http://www.lalit.org/wordpress/wp-content/uploads/2008/05/fontdetect.js?ver=0.3
/**
* JavaScript code to detect available availability of a
* particular font in a browser using JavaScript and CSS.
*
* Author : Lalit Patel
* Website: http://www.lalit.org/lab/javascript-css-font-detect/
* License: Apache Software License 2.0
* http://www.apache.org/licenses/LICENSE-2.0
* Version: 0.15 (21 Sep 2009)
* Changed comparision font to default from sans-default-default,
* as in FF3.0 font of child element didn't fallback
* to parent element if the font is missing.
* Version: 0.2 (04 Mar 2012)
* Comparing font against all the 3 generic font families ie,
* 'monospace', 'sans-serif' and 'sans'. If it doesn't match all 3
* then that font is 100% not available in the system
* Version: 0.3 (24 Mar 2012)
* Replaced sans with serif in the list of baseFonts
*/
/**
* Usage: d = new Detector();
* d.detect('font name');
*/
var Detector = function() {
// a font will be compared against all the three default fonts.
// and if it doesn't match all 3 then that font is not available.
var baseFonts = ['monospace', 'sans-serif', 'serif'];
//we use m or w because these two characters take up the maximum width.
// And we use a LLi so that the same matching fonts can get separated
var testString = "mmmmmmmmmmlli";
//we test using 72px font size, we may use any size. I guess larger the better.
var testSize = '72px';
var h = document.getElementsByTagName("body")[0];
// create a SPAN in the document to get the width of the text we use to test
var s = document.createElement("span");
s.style.fontSize = testSize;
s.innerHTML = testString;
var defaultWidth = {};
var defaultHeight = {};
for (var index in baseFonts) {
//get the default width for the three base fonts
s.style.fontFamily = baseFonts[index];
h.appendChild(s);
defaultWidth[baseFonts[index]] = s.offsetWidth; //width for the default font
defaultHeight[baseFonts[index]] = s.offsetHeight; //height for the defualt font
h.removeChild(s);
}
function detect(font) {
var detected = false;
for (var index in baseFonts) {
s.style.fontFamily = font + ',' + baseFonts[index]; // name of the font along with the base font for fallback.
h.appendChild(s);
var matched = (s.offsetWidth != defaultWidth[baseFonts[index]] || s.offsetHeight != defaultHeight[baseFonts[index]]);
h.removeChild(s);
detected = detected || matched;
}
return detected;
}
this.detect = detect;
};
요약
어떻게 작동합니까?
이 코드는 각 문자가 서로 다른 글꼴에서 다르게 표시된다는 단순한 원칙에 따라 작동합니다. 따라서 다른 글꼴은 동일한 글꼴 크기의 동일한 문자열에 대해 다른 너비와 높이를 사용합니다.
이것을 사용하는 방법이 있습니다 document.fonts
반환 된 값은 문서의 FontFaceSet 인터페이스입니다. FontFaceSet 인터페이스는 새 글꼴을로드하고 이전에로드 된 글꼴의 상태를 확인하는 데 유용합니다.
function listFonts() {
let { fonts } = document;
const it = fonts.entries();
let arr = [];
let done = false;
while (!done) {
const font = it.next();
if (!font.done) {
arr.push(font.value[0]);
} else {
done = font.done;
}
}
return arr;
}
function listFonts() {
let { fonts } = document;
const it = fonts.entries();
let arr = [];
let done = false;
while (!done) {
const font = it.next();
if (!font.done) {
arr.push(font.value[0].family);
} else {
done = font.done;
}
}
// converted to set then arr to filter repetitive values
return [...new Set(arr)];
}
HTML의 글꼴을 연결하지 않고 테스트 한 다음 Roboto 글꼴을 연결하고 다시 테스트 한 다음 결과에 추가되었습니다.
<SCRIPT>
function getFonts()
{
var nFontLen = dlgHelper.fonts.count;
var rgFonts = new Array();
for ( var i = 1; i < nFontLen + 1; i++ )
rgFonts[i] = dlgHelper.fonts(i);
rgFonts.sort();
for ( var j = 0; j < nFontLen; j++ )
document.write( rgFonts[j] + "<BR>" );
}
</SCRIPT>
<BODY onload="getFonts()">
<OBJECT id=dlgHelper CLASSID="clsid:3050f819-98b5-11cf-bb82-00aa00bdce0b" width="0px" height="0px">
</OBJECT>
'Arial',
'Arial Black',
'Bahnschrift',
'Calibri',
'Cambria',
'Cambria Math',
'Candara',
'Comic Sans MS',
'Consolas',
'Constantia',
'Corbel',
'Courier New',
'Ebrima',
'Franklin Gothic Medium',
'Gabriola',
'Gadugi',
'Georgia',
'HoloLens MDL2 Assets',
'Impact',
'Ink Free',
'Javanese Text',
'Leelawadee UI',
'Lucida Console',
'Lucida Sans Unicode',
'Malgun Gothic',
'Marlett',
'Microsoft Himalaya',
'Microsoft JhengHei',
'Microsoft New Tai Lue',
'Microsoft PhagsPa',
'Microsoft Sans Serif',
'Microsoft Tai Le',
'Microsoft YaHei',
'Microsoft Yi Baiti',
'MingLiU-ExtB',
'Mongolian Baiti',
'MS Gothic',
'MV Boli',
'Myanmar Text',
'Nirmala UI',
'Palatino Linotype',
'Segoe MDL2 Assets',
'Segoe Print',
'Segoe Script',
'Segoe UI',
'Segoe UI Historic',
'Segoe UI Emoji',
'Segoe UI Symbol',
'SimSun',
'Sitka',
'Sylfaen',
'Symbol',
'Tahoma',
'Times New Roman',
'Trebuchet MS',
'Verdana',
'Webdings',
'Wingdings',
'Yu Gothic',
'American Typewriter',
'Andale Mono',
'Arial',
'Arial Black',
'Arial Narrow',
'Arial Rounded MT Bold',
'Arial Unicode MS',
'Avenir',
'Avenir Next',
'Avenir Next Condensed',
'Baskerville',
'Big Caslon',
'Bodoni 72',
'Bodoni 72 Oldstyle',
'Bodoni 72 Smallcaps',
'Bradley Hand',
'Brush Script MT',
'Chalkboard',
'Chalkboard SE',
'Chalkduster',
'Charter',
'Cochin',
'Comic Sans MS',
'Copperplate',
'Courier',
'Courier New',
'Didot',
'DIN Alternate',
'DIN Condensed',
'Futura',
'Geneva',
'Georgia',
'Gill Sans',
'Helvetica',
'Helvetica Neue',
'Herculanum',
'Hoefler Text',
'Impact',
'Lucida Grande',
'Luminari',
'Marker Felt',
'Menlo',
'Microsoft Sans Serif',
'Monaco',
'Noteworthy',
'Optima',
'Palatino',
'Papyrus',
'Phosphate',
'Rockwell',
'Savoye LET',
'SignPainter',
'Skia',
'Snell Roundhand',
'Tahoma',
'Times',
'Times New Roman',
'Trattatello',
'Trebuchet MS',
'Verdana',
'Zapfino',
const fontCheck = new Set([
// Windows 10
'Arial', 'Arial Black', 'Bahnschrift', 'Calibri', 'Cambria', 'Cambria Math', 'Candara', 'Comic Sans MS', 'Consolas', 'Constantia', 'Corbel', 'Courier New', 'Ebrima', 'Franklin Gothic Medium', 'Gabriola', 'Gadugi', 'Georgia', 'HoloLens MDL2 Assets', 'Impact', 'Ink Free', 'Javanese Text', 'Leelawadee UI', 'Lucida Console', 'Lucida Sans Unicode', 'Malgun Gothic', 'Marlett', 'Microsoft Himalaya', 'Microsoft JhengHei', 'Microsoft New Tai Lue', 'Microsoft PhagsPa', 'Microsoft Sans Serif', 'Microsoft Tai Le', 'Microsoft YaHei', 'Microsoft Yi Baiti', 'MingLiU-ExtB', 'Mongolian Baiti', 'MS Gothic', 'MV Boli', 'Myanmar Text', 'Nirmala UI', 'Palatino Linotype', 'Segoe MDL2 Assets', 'Segoe Print', 'Segoe Script', 'Segoe UI', 'Segoe UI Historic', 'Segoe UI Emoji', 'Segoe UI Symbol', 'SimSun', 'Sitka', 'Sylfaen', 'Symbol', 'Tahoma', 'Times New Roman', 'Trebuchet MS', 'Verdana', 'Webdings', 'Wingdings', 'Yu Gothic',
// macOS
'American Typewriter', 'Andale Mono', 'Arial', 'Arial Black', 'Arial Narrow', 'Arial Rounded MT Bold', 'Arial Unicode MS', 'Avenir', 'Avenir Next', 'Avenir Next Condensed', 'Baskerville', 'Big Caslon', 'Bodoni 72', 'Bodoni 72 Oldstyle', 'Bodoni 72 Smallcaps', 'Bradley Hand', 'Brush Script MT', 'Chalkboard', 'Chalkboard SE', 'Chalkduster', 'Charter', 'Cochin', 'Comic Sans MS', 'Copperplate', 'Courier', 'Courier New', 'Didot', 'DIN Alternate', 'DIN Condensed', 'Futura', 'Geneva', 'Georgia', 'Gill Sans', 'Helvetica', 'Helvetica Neue', 'Herculanum', 'Hoefler Text', 'Impact', 'Lucida Grande', 'Luminari', 'Marker Felt', 'Menlo', 'Microsoft Sans Serif', 'Monaco', 'Noteworthy', 'Optima', 'Palatino', 'Papyrus', 'Phosphate', 'Rockwell', 'Savoye LET', 'SignPainter', 'Skia', 'Snell Roundhand', 'Tahoma', 'Times', 'Times New Roman', 'Trattatello', 'Trebuchet MS', 'Verdana', 'Zapfino',
].sort());
(async() => {
await document.fonts.ready;
const fontAvailable = new Set();
for (const font of fontCheck.values()) {
if (document.fonts.check(`12px "${font}"`)) {
fontAvailable.add(font);
}
}
console.log('Available Fonts:', [...fontAvailable.values()]);
})();
위의 Lalit Patel의 Detector에 두 가지 방법을 추가했습니다.
이를 통해 다음을 수행 할 수 있습니다.
fonts = [ 'Arial', 'Arial Black', { family: 'Lato', stylesheetUrl: 'https://fonts.googleapis.com/css?family=Lato'}, 'Leelawadee UI']
(new FontDetector()).addFontsArr(fonts);
암호:
/**
* JavaScript code to detect available availability of a
* particular font in a browser using JavaScript and CSS.
*
* Author : Lalit Patel
* Website: http://www.lalit.org/lab/javascript-css-font-detect/
* License: Apache Software License 2.0
* http://www.apache.org/licenses/LICENSE-2.0
* Version: 0.15 (21 Sep 2009)
* Changed comparision font to default from sans-default-default,
* as in FF3.0 font of child element didn't fallback
* to parent element if the font is missing.
* Version: 0.2 (04 Mar 2012)
* Comparing font against all the 3 generic font families ie,
* 'monospace', 'sans-serif' and 'sans'. If it doesn't match all 3
* then that font is 100% not available in the system
* Version: 0.3 (24 Mar 2012)
* Replaced sans with serif in the list of baseFonts
*/
/**
* Usage: d = new Detector();
* d.detect('font name');
*/
function FontDetector() {
this.detect = detect;
this.addFont = addFont;
this.addFontsArr = addFontsArr;
// a font will be compared against all the three default fonts.
// and if it doesn't match all 3 then that font is not available.
var baseFonts = ['monospace', 'sans-serif', 'serif'];
//we use m or w because these two characters take up the maximum width.
// And we use a LLi so that the same matching fonts can get separated
var testString = "mmmmmmmmmmlli";
//we test using 72px font size, we may use any size. I guess larger the better.
var testSize = '72px';
var h = document.getElementsByTagName("body")[0];
// create a SPAN in the document to get the width of the text we use to test
var s = document.createElement("span");
s.style.fontSize = testSize;
s.innerHTML = testString;
var defaultWidth = {};
var defaultHeight = {};
for (var index in baseFonts) {
//get the default width for the three base fonts
s.style.fontFamily = baseFonts[index];
h.appendChild(s);
defaultWidth[baseFonts[index]] = s.offsetWidth; //width for the default font
defaultHeight[baseFonts[index]] = s.offsetHeight; //height for the defualt font
h.removeChild(s);
}
function detect(font) {
var detected = false;
for (var index in baseFonts) {
s.style.fontFamily = font + ',' + baseFonts[index]; // name of the font along with the base font for fallback.
h.appendChild(s);
var matched = (s.offsetWidth != defaultWidth[baseFonts[index]] || s.offsetHeight != defaultHeight[baseFonts[index]]);
h.removeChild(s);
detected = detected || matched;
}
return detected;
}
function addFont(family, stylesheetUrl, ruleString) {
if (detect(family)) {
//console.log('using internal font '+family);
return true;
}
if (stylesheetUrl) {
console.log('added stylesheet '+stylesheetUrl);
var head = document.head, link = document.createElement('link');
link.type = 'text/css';
link.rel = 'stylesheet';
link.href = stylesheetUrl;
head.appendChild(link);
return true;
}
if (ruleString) {
console.log('adding font rule:'+rule);
var newStyle = document.createElement('style');
newStyle.appendChild(document.createTextNode(rule));
document.head.appendChild(newStyle);
return true;
}
console.log('could not add font '+family);
}
function addFontsArr(arr) {
arr.forEach(a => typeof a==='string' ? addFont(a) : addFont(a.family, a.stylesheetUrl, a.ruleString));
}
};
특정 문자에 대해 알려진 글꼴 이미지가있는 스프라이트 시트를 사용하고 브라우저가 동일한 글꼴로보고하는 것과 동일한 문자가 그려지는 캔버스 요소의 스냅 샷과 비교하여 완전히 다른 방식으로 수행 할 수 있습니다. 비교는 resemble.js 와 같은 것으로 수행 될 수 있습니다 .
속도는 느리지 만 브라우저가 거짓말을 할 때 감지 할 수 있어야합니다.
짧은 대답입니다. Flash를 사용하는 것이 이제 더 나쁜 생각이라는 점을 제외하고는 2020 년 브라우저의 글꼴 감지와 관련하여 많이 변경되지 않았습니다 .
현재 사용 가능한 모든 글꼴을 "나열"하는 브라우저 기본 시스템은 없습니다. 그러나 브라우저에서는 FontFaceSet API를 사용하여 글꼴이로드 / 준비되었는지 확인할 수 있습니다 . 최신 브라우저에서 꽤 잘 지원됩니다.
이것은 웹 글꼴이 완전히 다운로드되었는지 표시하기위한 것이지만 시스템 글꼴에서도 작동합니다. 문제는 확인할 글꼴 목록을 제공해야한다는 것 입니다.
따라서 user agent
테스트 (항상 정확하지는 않음) 와 함께 각 장치 유형에 대한 공통 시스템 글꼴 목록을 생성 할 수 있습니다 . 그런 다음로드 한 웹 글꼴과 웹 글꼴에 대해 테스트합니다.
참고 : 사용 가능한 글꼴의 전체 목록을 제공하지는 않지만 MS Office 또는 Adobe 제품에서 일반적으로 설치하는 글꼴을 확인할 수 있습니다.
최근에 HTML5 캔버스의 context.font 값을 "정크"와 같은 잘못된 값으로 설정하면 변경 사항이 캔버스에서 무시된다는 사실을 알게되었습니다. 이것이 브라우저에 특정한 것인지는 모르겠지만 Chrome에서 이런 식으로 작동하는 것 같습니다. 나는 또한 다른 브라우저에서 발생한다는 것을 나타내는 다른 게시물 ( HTML 5 canvas font being ignore )을 보았습니다 .
그런 다음 "10px sans serif"( https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/font ) 라고 생각되는 기본값으로 문자열을 작성 하고 글꼴을 설정할 수 있습니다. 테스트중인 사람에게 문자열을 다시 씁니다. 첫 번째 도면과 동일한 경우 글꼴을 사용할 수 없습니다.