Autor Zpráva
Witiko
Profil
Pracoval jsem na vlastním řešení používání nových fontů v javascriptových aplikacích. Mým cílem bylo napsat script, který by můj obrázek s písmeny fontu "rozparsoval" a pak pomocí divů s display: inline a background-position vykreslil (více informací například zde) slovo. Ale zde se objevil problém.

1, Nejprve jsem se pokusil situaci vyřešit tak, že jsem vytvořil span a do něho jsem vnořil pro každé písmeno jeden div s display:inline. Vše skvěle fungovalo v MSIE, nicméně Firefox ani Opera nic nezobrazovaly. Z toho co jsem pochopil odmítají oba prohlížeče zobrazovat inline elementy, pokud mají prázdné innerHTML.

2, Druhým mým pokusem byla table s display: inline a jedním td pro každé písmeno. Vše se zobrazilo v Mozzile, ale jak MSIE tak Opera neukazují pořád nic (Opera neukazovala nic ani v jednom případě). Jsem tímto chováním mírně zmatený.

Kódy:

font.js
/*

    GFX Fonts - Library allowing you to parse an image into sprites and use them as a Font
    Copyright (C) 2010  Vít Novotný

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  
*/

var Font = function() {
  this.ready = false;
  this.type = "font";
}

Font.prototype.finalize = function(callback) {
  if(this.ready || !this.image || typeof this.definition != "object") return false;
  
  // Rewriting the definition into an Array which is easier to access
  var temporary = this.definition.slice(0);
  this.definition = new Array();
  for(var count = 0; count <= 235; count++) {
    for(var count2 = 0; count2 < temporary.length; count2++) {
      if(temporary[count2]["letter"].charCodeAt(0) == count+20) {
        this.definition[count] = temporary[count2]["coords"];
        break;
      }
    }
    if(!this.definition[count]) this.definition[count] = false;
  }
  
  // Preloading the given image
  var loaded = false;
  var that = this;
  image = new Image();
  image.onload = function()
    {
    if(loaded) return;
    loaded = true;
    that.ready = true;
    if(typeof callback == "function") callback();
    };
  image.onreadystatechange = function()
    {
    if(loaded || (this.readyState != "loaded" && this.readyState != "complete")) return;
    loaded = true;
    that.ready = true;
    if(typeof callback == "function") callback();
    };
  image.src = this.image;
  
  return true;
}

var drawText = function(text, font, element) {
  text = String(text)
  if(typeof text != "string" || typeof font != "object" || font["type"] != "font" || !font["ready"] || !element) return false;
  
  //  Creating a span in which the whole word will be stored
  var span = document.createElement("span");
  
  // Creating spans containing letters and attaching them to the parent span
  var letters = new Array();
  var temporary;
  for(var count = 0; count < text["length"]; count++) {
  
    temporary = text["charAt"](count).charCodeAt(0)-20;
    letters[count] = document.createElement("span");
    letters[count].className = "font";

    if(font.definition[temporary]) {
    
      //  Should the font contain this letter, print the letter
      letters[count].style.width = String(Math.abs(font.definition[temporary][0] - font.definition[temporary][2])) + "px";
      letters[count].style.height = String(Math.abs(font.definition[temporary][1] - font.definition[temporary][3])) + "px";
      letters[count].style.background = "url('"+font.image+"') no-repeat";
      letters[count].style.backgroundPosition = String(0 - font.definition[temporary][0]) + "px " + String(0 - font.definition[temporary][1]) + "px"
    } else {
    
      //  Otherwise print a question mark
      temporary = "?".charCodeAt(0)-20;
      if(font.definition[temporary]) {
      
        // Should the font contain the question mark symbol, print it as an image
        letters[count].style.width = String(Math.abs(font.definition[temporary][0] - font.definition[temporary][2])) + "px";
        letters[count].style.height = String(Math.abs(font.definition[temporary][1] - font.definition[temporary][3])) + "px";
        letters[count].style.background = "url('"+font.image+"') no-repeat";
        letters[count].style.backgroundPosition = String(0 - font.definition[temporary][0]) + "px " + String(0 - font.definition[temporary][1]) + "px"
      } else {
      
        //Otherwise print is as a text symbol
        letters[count].style.fontSize = "smaller"
        letters[count].innerHTML = "?";
      }
    }
    span.appendChild(letters[count]);
  }
  return {"element":element.appendChild(span),"parentElement":element};
}

var undrawText = function(object) {
  if(typeof object != "object") return false;
  return object["parentElement"].removeChild(object["element"]);
}


font.ini
SketchedAlphabet = new Font();
SketchedAlphabet.image = "font.gif";
SketchedAlphabet.definition = [
  {
    "letter":"0",
    "coords":[4,3,12,20]
  },
  {
    "letter":"1",
    "coords":[13,3,18,20]
  }
];



font.css
.font {
    display: inline-block;
    vertical-align: bottom;
}


font.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta http-equiv="Content-Language" content="cs">
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1250">
    <script type="text/javascript" src="font.js"></script>
    <script type="text/javascript" src="font.ini"></script>
    <link rel="stylesheet" type="text/css" href="font.css">
    <title>GFX Fonts test</title>
  </head>
  <body onload="SketchedAlphabet.finalize(function(){drawText('000910',SketchedAlphabet,document.getElementById('body-text'));});">
    <div id="body-text" align="left"></div>
  </body>
</html>


Obrázek spritů font.gif
Živá ukázka: zde
Chamurappi
Profil
Reaguji na Witika:
Nejspíš hledáš display: inline-block. Nebo ty elementy floatuj.

callback = arguments[0]?arguments[0]:null
To jde zapsat i jako callback = arguments[0] || null.
Co máš proti pojmenovávání argumentů? Nebylo by to přehlednější než lovit je z arguments?
Witiko
Profil
Chamurappi
Díky, display: inline-block bylo to, co jsem hledal. Přepsáno přes spany, živá ukázka a kód nahoře updatovány.

„Co máš proti pojmenovávání argumentů?“
Vůbec nic, jen jsem to, že je každé metodě předáváno pole argumentů, zjistil teprve nedávno a tak to možná s používáním přeháním. :)

„To jde zapsat i jako callback = arguments[0] || null“
Zajímavé, nikdy mě nenapadlo používat logické operátory mimo podmínky. Vždy, když sem napíšu, tak se dozvím něco nového.

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: