Home > Latest topics

Latest topics > 拡張機能でtext-shadowを実装できないものだろうか

宣伝1。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

宣伝2。Firefox Hacks Rebooted発売中。本書の1/3を使って、再起動不要なアドオンの作り方のテクニックや非同期処理の効率のいい書き方などを解説しています。既刊のFirefox 3 Hacks拡張機能開発チュートリアルと併せてどうぞ。

Firefox Hacks Rebooted ―Mozillaテクノロジ徹底活用テクニック
浅井 智也 池田 譲治 小山田 昌史 五味渕 大賀 下田 洋志 寺田 真 松澤 太郎
オライリージャパン

拡張機能でtext-shadowを実装できないものだろうか - Jul 27, 2007

CSS2からCSS3に移ったtext-shadowは、どうやらFirefox 3ではサポートされない事がほとんど確定したようだ。これでモダンブラウザでドロップシャドウを実現できないのはFirefoxだけになったな(Opera 10とSafariは対応、IEもfilterを使えば可能)。

ということで拡張機能でtext-shadowを実現するという可能性を勝手に模索してみる事にしたよ。

アルゴリズムとしては以前須藤さんがcairoで不透明度を下げた物をひたすらずらして並べるというアレです。

const SHADOW_QUALITY = 2; // 数値を上げれば上げるほど精度が落ちる

function drawShadow(aElement, aX, aY, aRadius, aColor)
{
  var XMLNS = 'http://www.w3.org/1999/xhtml';
  var nodes;
  var d = aElement.ownerDocument;
  try {
    nodes = d.evaluate('descendant::text()', aElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  }
  catch(e) {
    nodes = document.evaluate('descendant::text()', aElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  }
  var bases = [];
  var node;
  var wrapper = d.createElementNS(XMLNS, 'text-shadow-box');
  wrapper.setAttribute('style', 'position: relative;');
  var innerWrapper = d.createElementNS(XMLNS, 'text-shadow-base');
  var newWrapper, newInnerWrapper;
  for (var i = 0, maxi = nodes.snapshotLength; i < maxi; i++)
  {
    node = nodes.snapshotItem(i);
    if (/^\s+$/.test(node.nodeValue)) continue;
    newWrapper = wrapper.cloneNode(true);
    newInnerWrapper = innerWrapper.cloneNode(true);
    node.parentNode.insertBefore(newWrapper, node);
    node.parentNode.removeChild(node);
    newWrapper.appendChild(newInnerWrapper);
    newInnerWrapper.appendChild(node);
    bases.push(newWrapper);
  }

  var gap = Math.max(SHADOW_QUALITY, 1);
  aRadius = Math.max(Math.max(aRadius, 1) / gap, 1);

  var opacity = 1 / aRadius;
  var shadow = d.createElementNS(XMLNS, 'text-shadow');
  var newShadow;
  var xOffset = Math.round(aX/2);
  var yOffset = Math.round(aY/2);
  var parentBox;
  var display;
  for (var i in bases)
  {
    parentBox = bases[i];
    while ((display = d.defaultView.getComputedStyle(parentBox, null).getPropertyValue('display')) != 'block' && display != '-moz-box' && parentBox.parentNode)
    {
      parentBox = parentBox.parentNode;
    }
    if (parentBox == d) parentBox = d.documentElement;

    var width = d.getBoxObjectFor(parentBox).width;
    width -= Number(d.defaultView.getComputedStyle(parentBox, null).getPropertyValue('padding-left').match(/^[-0-9\.]+/));
    width -= Number(d.defaultView.getComputedStyle(parentBox, null).getPropertyValue('padding-right').match(/^[-0-9\.]+/));
    for (var j = 0, maxj = aRadius; j < maxj; j++)
    {
      for (var k = 0, maxk = aRadius; k < maxk; k++)
      {
        newShadow = shadow.cloneNode(true);
        newShadow.appendChild(bases[i].firstChild.firstChild.cloneNode(true));
        newShadow.setAttribute('style',
          'display: block !important; margin: 0 !important; padding: 0 !important;'
          + 'width: ' + width + 'px !important;'
          + 'position: absolute !important;'
          + 'z-index: 1 !important;'
          + 'color: ' + aColor + ' !important;'
          + 'opacity: ' + opacity + ' !important;'
          + 'top: ' + (j+gap-yOffset) + 'px !important;'
          + 'left: ' + (k+gap-xOffset) + 'px !important;'
        );
        bases[i].appendChild(newShadow);
      }
    }
    bases[i].firstChild.setAttribute('style', 'display: block;');
    window.setTimeout(function(aNode) {
      aNode.setAttribute('style', 'position: relative; z-index: 2;');
    }, 0, bases[i].firstChild);
  }
}

drawShadow(document.getElementsByTagName('h2')[0], 0, 0, 6, 'black');

あとSHADOW_QUALITYを1にした状態だとradiusが10とかになると相当重くなる(radiusの二乗分の個数のノードを新たに生成しているので)。

スタイルシートを解析する処理を書いたら一応ブチ込む事はできるわけですが……

追記。最初は折り返しがあるとうまく動かない物だったけど、工夫したら折り返しが合っても大丈夫にできた。

分類:Mozilla > XUL, , , , , , 時刻:02:30 | Comments/Trackbacks (3) | Edit

Comments/Trackbacks

Opera の text-shadow サポート時期

> (Opera 10とSafariは対応、IEもfilterを使えば可能)。

Opera 10 ではなく 9.5 で text-shadow をサポートするようです。
http://my.opera.com/desktopteam/blog/kestrel-is-coming

Commented by Taken at 2007/07/27 (Fri) 08:44:32

[これはすごい][Firefox]

すばらしい。ぜひともFirefox3にマージしてほしいなー。

Commented by Koshian at 2007/07/27 (Fri) 15:28:35

no title

> これでモダンブラウザでドロップシャドウを実現できないのはFirefoxだけになったな(Opera 10とSafariは対応、IEもfilterを使えば可能)。

filter を使えば可能、というレベルでよいのであれば、Firefox でも trunk Linux 版では前からできてますし、Windows 版でも、クラッシュするバグに対するパッチのレビューは通ってますので、もうすぐできるかもしれません。
http://taken.s101.xrea.com/blog/article.php?id=757

Commented by at 2007/07/27 (Fri) 21:29:00

TrackBack ping me at


の末尾に2014年1月19日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2007-07-27_textshadow.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。

Post a comment

writeback message: Ready to post a comment.

2014年1月19日時点の日本の首相のファミリーネーム(ひらがなで回答)

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のつぶやき

オススメ

Mozilla Firefox ブラウザ無料ダウンロード