2013年5月11日土曜日

EaselJS (CreateJS) を拡張してTextで縦書きできるようにしてみた

最近EaselJSをさわりはじめたんですが、AS3を少しやっていたのでAPIがにていてわかりやすいです。
そんなに複雑なもの作ろうとしているわけじゃないので、別に素のJSをつかってかいても良かったんですが、、、

EaselJSのTextですが、例によって縦書きはできないようで、縦書きをたまに使用する日本人にはかゆいところに手が届かない感じです。
EaselJSはMITライセンスのOSSだったので、勉強がてら拡張して縦書きもできるTextExを作ってみました。

TextEx.js

変更点はdirectionプロパティを追加して、directionが"vertical"のときforで一文字ずつ縦に描画するようにしただけです。
--- Text.js 2013-05-11 19:36:31.000000000 +0900
+++ TextEx.js 2013-05-11 20:57:56.000000000 +0900
@@ -41,7 +41,7 @@
  * multiple font styles, you will need to create multiple text instances, and position them manually.
  *
  * <h4>Example</h4>
- *      var text = new createjs.Text("Hello World", "20px Arial", "#ff7700");
+ *      var text = new createjs.TextEx("Hello World", "20px Arial", "#ff7700");
  *      text.x = 100;
  *      text.textBaseline = "alphabetic";
  *
@@ -59,17 +59,17 @@
  * @param {String} [color] The color to draw the text in. Any valid value for the CSS color attribute is acceptable (ex.
  * "#F00", "red", or "#FF0000").
  **/
-var Text = function(text, font, color) {
+var TextEx = function(text, font, color) {
   this.initialize(text, font, color);
 }
-var p = Text.prototype = new createjs.DisplayObject();
+var p = TextEx.prototype = new createjs.DisplayObject();
 
  /**
   * @property _workingContext
   * @type CanvasRenderingContext2D
   * @private
   **/
- Text._workingContext = (createjs.createCanvas?createjs.createCanvas():document.createElement("canvas")).getContext("2d");
+ TextEx._workingContext = (createjs.createCanvas?createjs.createCanvas():document.createElement("canvas")).getContext("2d");
 
 // public properties:
  /**
@@ -142,6 +142,13 @@
   **/
  p.lineWidth = null;
  
+ /**
+  * Indicates the text direction. Any of "horizontal" or "vertical". Default is "horizontal".
+  * @property direction
+  * @type String
+  */
+ p.direction = "horizontal";
+ 
 // constructor:
  /**
   * @property DisplayObject_initialize
@@ -182,7 +189,7 @@
  p.DisplayObject_draw = p.draw;
  
  /**
-  * Draws the Text into the specified context ignoring it's visible, alpha, shadow, and transform.
+  * Draws the TextEx into the specified context ignoring it's visible, alpha, shadow, and transform.
   * Returns true if the draw was handled (useful for overriding functionality).
   * NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
   * @method draw
@@ -226,7 +233,7 @@
 
  /**
   * Returns the approximate height of multi-line text by multiplying the number of lines against either the
-  * <code>lineHeight</code> (if specified) or {{#crossLink "Text/getMeasuredLineHeight"}}{{/crossLink}}. Note that
+  * <code>lineHeight</code> (if specified) or {{#crossLink "TextEx/getMeasuredLineHeight"}}{{/crossLink}}. Note that
   * this operation requires the text flowing logic to run, which has an associated CPU cost.
   * @method getMeasuredHeight
   * @return {Number} The approximate height of the drawn multi-line text.
@@ -236,12 +243,12 @@
  }
  
  /**
-  * Returns a clone of the Text instance.
+  * Returns a clone of the TextEx instance.
   * @method clone
-  * @return {Text} a clone of the Text instance.
+  * @return {TextEx} a clone of the TextEx instance.
   **/
  p.clone = function() {
-  var o = new Text(this.text, this.font, this.color);
+  var o = new TextEx(this.text, this.font, this.color);
   this.cloneProps(o);
   return o;
  }
@@ -252,7 +259,7 @@
   * @return {String} a string representation of the instance.
   **/
  p.toString = function() {
-  return "[Text (text="+  (this.text.length > 20 ? this.text.substr(0, 17)+"..." : this.text) +")]";
+  return "[TextEx (text="+  (this.text.length > 20 ? this.text.substr(0, 17)+"..." : this.text) +")]";
  }
  
 // private methods:
@@ -266,7 +273,7 @@
 
  /** 
   * @method cloneProps
-  * @param {Text} o
+  * @param {TextEx} o
   * @protected 
   **/
  p.cloneProps = function(o) {
@@ -284,7 +291,7 @@
   * @protected 
   **/
  p._getWorkingContext = function() {
-  var ctx = Text._workingContext;
+  var ctx = TextEx._workingContext;
   ctx.font = this.font;
   ctx.textAlign = this.textAlign||"start";
   ctx.textBaseline = this.textBaseline||"alphabetic";
@@ -333,16 +340,28 @@
  /** 
   * @method _drawTextLine
   * @param {CanvasRenderingContext2D} ctx
-  * @param {Text} text
+  * @param {String} text
   * @param {Number} y
   * @protected 
   **/
  p._drawTextLine = function(ctx, text, y) {
   // Chrome 17 will fail to draw the text if the last param is included but null, so we feed it a large value instead:
+  if (this.direction === "vertical") {
+   var lineHeight = this.lineHeight||this.getMeasuredLineHeight();
+   if (this.outline) {
+    for (var i=0, l=text.length; i<l; ++i) {
+     ctx.strokeText(text.charAt(i), -y - lineHeight, i*lineHeight, this.maxWidth||0xFFFF);
+    }
+   } else {
+    for (var i=0, l=text.length; i<l; ++i) {
+     ctx.fillText(text.charAt(i), -y - lineHeight, i*lineHeight, this.maxWidth||0xFFFF);
+    }
+   }
+  } else {
    if (this.outline) { ctx.strokeText(text, 0, y, this.maxWidth||0xFFFF); }
    else { ctx.fillText(text, 0, y, this.maxWidth||0xFFFF); }
-  
+  }
  }
 
-createjs.Text = Text;
-}());
\ No newline at end of file
+createjs.TextEx = TextEx;
+}());

1 件のコメント:

  1. あまりよくないやり方だと思ったので、書き直しています。
    今のところ最新版は以下です。
    https://github.com/aaharu/komenuka/blob/develop/public/js/TextEx.js

    返信削除