Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > de.comp.lang.javascript > #4922
| From | Christian Zimmermann <ch.zim@web.de> |
|---|---|
| Newsgroups | de.comp.lang.javascript |
| Subject | Re: "Optische" Zeichenhöhe berechnen |
| Date | 2017-11-20 09:36 +0100 |
| Organization | albasani.net |
| Message-ID | <ouu45o$v5o$1@news.albasani.net> (permalink) |
| References | <ouk8ir$ed9$1@news.albasani.net> |
Hi,
erstmal zum Code. Ich habe mir nun folgende Lösung für mein Problem
erstellt. Das hat etwas "länger" gedauert, weil ich zufälligerweise auch
mit "Comic Sans MS" getestet und dabei festgestellt habe, dass der
Firefox bei dieser Schriftart über den unteren Canvas-Rand
hinausschreiben kann. Dies bedarf in diesem Fall noch einer kleinen
Korrektur.
************* Code *************
<!DOCTYPE html>
<html>
<meta charset ="utf-8">
<body style="background-color:steelblue">
<canvas id="myCanvas" width="1000" height="140"
style="background-color:white">
Your browser does not support the HTML5 canvas tag.</canvas>
<script>
// test cases
var i,x,tw;
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var txt = ['g','a','A','Ä','Â','Âj','"'], h=0, fontStyle="bold 90px Arial";
var txtMet;
ctx.moveTo(0,c.height/2);
ctx.lineTo(c.width,c.height/2);
ctx.stroke();
ctx.font = fontStyle;
x = 0;
for (i = 0; i < txt.length; i++) {
txtMet = getVisualTextMetricsInPixel(txt[i], fontStyle);
tw = ctx.measureText(txt[i]).width;
ctx.textBaseline = "bottom";
ctx.fillText(txt[i], x , c.height/2 + txtMet.textHeight/2
+
txtMet.distBottomTextToBottomLine - txtMet.adjust);
ctx.textBaseline = "middle";
ctx.fillText(txt[i], x + tw + 5, c.height/2);
x = x + 2 * tw + 15;
}
function getVisualTextMetricsInPixel (text, fontStyle) {
var i;
var img, flag, lines;
var canvas, ctx;
var txtMet = {textHeight: 0, fontMaxHeight: 0,
distTopTextToBottomLine: 0,
adjust: 0};
if (text === "") return txtMet;
var body = document.getElementsByTagName("body")[0];
var div = document.createElement("div");
var textNode = document.createTextNode("jÂ");
//retrieve maximum font height
div.appendChild(textNode);
div.setAttribute("style", "font:" + fontStyle);
body.appendChild(div);
txtMet.fontMaxHeight = div.offsetHeight;
body.removeChild(div);
//retrieve "visual" font height and distance from bottom line
canvas = document.createElement("canvas");
canvas.style.visibility = "hidden";
body.appendChild(canvas);
ctx = canvas.getContext("2d");
// set the width
ctx.font = fontStyle;
canvas.width = Math.ceil(ctx.measureText(text).width);
canvas.height = txtMet.fontMaxHeight;
ctx.font = fontStyle;
ctx.textBaseline = "bottom";
ctx.fillText(text, 0, canvas.height - 1);
// check if part of the text is drawn below the bottom of the canvas rect,
// because in Firefox sometimes .fillText() with textBaseline =
"bottom" and
// font "Comic Sans MS" does
img = ctx.getImageData(0, canvas.height - 1, canvas.width, canvas.height);
i=0;
while (!isRowEmpty(img)) {
i++;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillText(text, 0, canvas.height - i);
img = ctx.getImageData(0, canvas.height - 1, canvas.width,
canvas.height);
}
if (i > 0) txtMet.adjust = i - 1;
// retrieve the text height
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillText(text, 0, canvas.height - txtMet.adjust);
img = ctx.getImageData(0, 0, canvas.width, canvas.height);
lines = getTopBottomLine(img, canvas.width, canvas.height - 1);
txtMet.textHeight = lines.bottom - lines.top + 1;
txtMet.distBottomTextToBottomLine = canvas.height - lines.bottom - 1;
body.removeChild(canvas);
return txtMet;
}
function isRowEmpty (img) {
for (var i = 0; i <= img.data.length; i+=4) {
if (img.data[i+3] > 0) { return false; }
}
return true;
}
function getTopBottomLine (img, width, height) {
var lines = {top: -1, bottom: -1};
var i,j,flag;
// Approach from top
// (to the first non-transparent pixel that belongs to the top of the
character)
flag = false;
for (j = 0; j <= height; j++) {
for (i = 0; i < width; i++) {
if (img.data[(j*width+i)*4+3] > 0) {
lines.top = j;
flag = true;
break;
}
}
if (flag) break;
}
// Approach from bottom
// (to the first non-transparent pixel that belongs to the bottom of
the character)
flag = false;
for (j = height; j >= 0; j--) {
for (i = 0; i < width; i++) {
if (img.data[(j*width+i)*4+3]>0) {
lines.bottom = j;
flag = true;
break;
}
}
if (flag) break;
}
return lines;
}
</script>
</body>
</html>
************* Code *************
Getestet habe ich mit
Firefox 52.4.0 (32bit)
Firefox 52.5.0 (32bit)
Firefox 58.0b4 (64-Bit)
IE 11.15.15299.0
Edge 41.16299.15.0
Chrome 61.0.3163.100 (32-Bit)
Chrome 62.0.3202.94 (32-Bit)
Gruß,
Christian
Back to de.comp.lang.javascript | Previous | Next — Previous in thread | Next in thread | Find similar
"Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-16 15:50 +0100
Re: "Optische" Zeichenhöhe berechnen Arno Welzel <usenet@arnowelzel.de> - 2017-11-16 19:50 +0100
Re: "Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-16 20:07 +0100
Re: "Optische" Zeichenhöhe berechnen "Peter J. Holzer" <hjp-usenet3@hjp.at> - 2017-11-16 23:33 +0100
Re: "Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-17 00:00 +0100
Re: "Optische" Zeichenhöhe berechnen Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-11-17 02:35 +0100
Re: "Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-17 08:06 +0100
Re: "Optische" Zeichenhöhe berechnen Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-11-17 14:00 +0100
Re: "Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-20 09:54 +0100
Re: "Optische" Zeichenhöhe berechnen Arno Welzel <usenet@arnowelzel.de> - 2017-11-18 19:52 +0100
Re: "Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-20 09:46 +0100
Re: "Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-20 09:36 +0100
Re: "Optische" Zeichenhöhe berechnen Christian Zimmermann <ch.zim@web.de> - 2017-11-20 10:31 +0100
csiph-web