Safari3 に HTML5::Canvas の Text API を実装した
WebKit530未満(Safari3.x)には、Text API(fillText, strokeText, measureText) が実装されていません。
また、window.CanvasRenderingContext2D が存在しないため、prototype ベースでの機能拡張ができません。
uuCanvas.js では、getContext() をラップすることで Safari3.x に Text API を実装しました。
uuCanvas.js により拡張される機能
- Text API(fillText(), strokeText(), measureText()) をサポートします。
- Text Shadow プロパティ(shadowColor, shadowBlur, shadowOffsetX, shadowOffsetY) をサポートします。
- Text プロパティ(font, textAlign, textBaseline) をサポートします。
制限事項
これで
Safari3.x に Text API を実装できたので、全てのモダンブラウザ(IE6+, Safari3.1+, Opera9.2+, Firefox2+, Google Chrome2+)で Canvas Text API がそれなりに利用可能になります。
追加したコード
追加実装したコード片はこんな感じになります。
// 初期化処理 if (_mm.enginever < 530) { // Safari3.x var nodes = _doc.getElementsByTagName("canvas"), v, i = 0; while ( (v = nodes[i++]) ) { initOldWebKitCanvas(v); } } // getContext のラッパー function initOldWebKitCanvas(node, type) { if (!node._getContext) { node._getContext = node.getContext; // keep original method // wrapper node.getContext = function(type) { var ctx = node._getContext(type || "2d"); return ctx._stack ? ctx : _canvas.extend.textAPI(ctx); }; } return node; } // 動的に生成した canvas オブジェクトの初期化 // uuCanvas.init - initialize a canvas made dynamically init: function(canvas, // @param Node: canvas element vml) { // @param Boolean(= false): true = force VML // @return Node: new canvas if (_mm.webkit && _mm.enginever < 530) { return initOldWebKitCanvas(canvas); } return canvas.getContext ? canvas // already initialized : (vml || !_mm.slver) ? VMLInit(canvas) : SLInit(canvas); }, // 実体 // === Extend Text API for old WebKit ====================== _extend.textAPI = function(ctx) { // @param CanvasRenderingContext2D: // @return CanvasRenderingContext2D: ctx._stack = []; ctx._save = ctx.save; ctx._restore = ctx.restore; ctx._clearRect = ctx.clearRect; ctx.font = "10px sans-serif"; ctx.textAlign = "start"; ctx.textBaseline = "top"; // spec: "alphabetic" ctx.xMissColor = "#000"; ctx.xTextMarginTop = 1.3; ctx.save = function() { this._stack.push([ctx[FONT], ctx[TEXT_ALIGN], ctx[TEXT_BASELINE]]); this._save(); }; ctx.restore = function() { ctx._restore(); if (ctx._stack.length) { var last = ctx._stack.pop(); ctx[FONT] = last[0]; ctx[TEXT_ALIGN] = last[1]; ctx[TEXT_BASELINE] = last[2]; } }; ctx.clearRect = function(x, y, w, h) { clearRectDOM(ctx, x, y, w, h); }; ctx.fillText = function(text, x, y, maxWidth, wire) { fillTextDOM(ctx, text, x, y, maxWidth, wire); }; ctx.strokeText = function(text, x, y, maxWidth) { fillTextDOM(ctx, text, x, y, maxWidth, 1); }; ctx.measureText = function(text) { var metric = _extend.getTextMetric(text, ctx[FONT]); return new _extend.TextMetrics(metric.w, metric.h); } return ctx; };