0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AnimateCC(CreateJS)でカーニングを設定する

Last updated at Posted at 2023-03-16

(追記:2023/03/20)
下記、p._drawTextLine メソッドはいじらなくても大丈夫でした
p._prepContext メソッド内だけ、letterSpacing の設定をしてあげれば機能します

CreateJSでカーニングを設定したいと思ってドキュメント見ても設定がなくて、
いろいろ悩んでたら、なんか出来たような

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/letterSpacing
に、letterSpacing は書いてあるのだけど、これを、CreateJSでやると、
全テキストに反映しちゃって、使えん orz

んで、いろいろ悩んでて、createjs.js 本体をいろいろいじってたら出来たような

createjs.js では毎フレーム?の度に

	/**
	 * @method _drawTextLine
	 * @param {CanvasRenderingContext2D} ctx
	 * @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.outline) { ctx.strokeText(text, 0, y, this.maxWidth||0xFFFF); }
		else { ctx.fillText(text, 0, y, this.maxWidth||0xFFFF); }
	};

_drawTextLine メソッドが呼ばれてて、ここの最後の行

ctx.fillText(text, 0, y, this.maxWidth||0xFFFF);

これが、毎回呼ばれるので最後に設定した letterSpacing、例えば、

ctx.letterSpacing = "5px";

とすると、この "5px" が毎回全テキストに反映されてしまう
なので、ctx.fillText() の前で、テキスト毎に letterSpacing に再設定してあげれば
個々のテキストに対応できるようになります

んで、こんな感じに変更してみた

	/**
	 * @method _drawTextLine
	 * @param {CanvasRenderingContext2D} ctx
	 * @param {String} text
	 * @param {Number} y
	 * @protected
	 **/
	p._drawTextLine = function(ctx, text, y) {
		// console.log("p._drawTextLine()");
		// Chrome 17 will fail to draw the text if the last param is included but null, so we feed it a large value instead:
		ctx.save(); // ← これ要らないかも
		ctx.letterSpacing = (this.letterSpacing === undefined)? "" : this.letterSpacing + "px";
		if (this.outline) {
			ctx.strokeText(text, 0, y, this.maxWidth||0xFFFF);
		}else{
			ctx.fillText(text, 0, y, this.maxWidth||0xFFFF);
		}
		ctx.restore(); // ← これ要らないかも
	};

ctx.letterSpacing = (this.letterSpacing === undefined)? "" : this.letterSpacing + "px";
これを追加

この2行は念のためしてるけど要らないかも、
ctx.save(); // ← これ要らないかも
ctx.restore(); // ← これ要らないかも

これで、個々の Text 毎にカーニングが設定できます

それと、Textの幅を取得するメソッド p._getMeasuredWidth でも、letterSpacing を設定してあげないと、正常な幅が取れないので、
p._getMeasuredWidth 内から呼ばれている、p._prepContext メソッド内に、

	/**
	 * @method _getWorkingContext
	 * @param {CanvasRenderingContext2D} ctx
	 * @return {CanvasRenderingContext2D}
	 * @protected
	 **/
	p._prepContext = function(ctx) {
		ctx.font = this.font||"10px sans-serif";
		ctx.textAlign = this.textAlign||"left";
		ctx.textBaseline = this.textBaseline||"top";
		ctx.lineJoin = "miter";
		ctx.miterLimit = 2.5;

		ctx.letterSpacing = (this.letterSpacing === undefined)? "" : this.letterSpacing + "px";

		return ctx;
	};

ctx.letterSpacing = (this.letterSpacing === undefined)? "" : this.letterSpacing + "px";
を追加します
これで、letterSpacing を設定後も正常な幅が取得できます

また、Textのコンストラクタに、

function Text(text, font, color) {
    this.letterSpacing = 0;

と、this.letterSpacing の初期値を与えておけば、上記の undefined のチェックは要らないかも

使い方は、

let txt:createjs.Text = new createjs.Text("ほげほげ");
txt.letterSpacing = 10;

こんな感じ
また、

txt.letterSpacing -= 1;

とかも可

Animateのステージ上に配置してある Textインスタンス についても、

test_txt.letterSpacing = 10;

な感じで設定ができます

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?