Home > Latest topics

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

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

拡張機能で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


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

Post a comment

writeback message: Ready to post a comment.

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

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき