[tech] デカい文字をA4で分割して印刷するツールをJSで書いた | Sat, Mar 7. 2015 - 氾濫原 では、実寸サイズを扱うので、多くの場所で mm や cm やら pt などの単位で数値を書きたくなる。

いろんな方法

mm を係数にして毎回乗算する方法

var mm = dpi / 25.4;

10*mm

mm を係数にして毎回除算する方法

var mm = 25.4 / dpi;

10/mm

乗算の逆。

変換を関数にする方法

function mm (num) { ... }

mm(10)

Number のプロトタイプ拡張

Number.prototype.mm = function () { ... };

10..mm()


しかし JSLint とかは 10..mm みたいな呼びかたをすると怒る。

Number のアクセサディスクリプタ

単純なプロトタイプ拡張と比べ、括弧がいらない。

10..mm
function setDPI (dpi) {
	var dpmm = dpi / 25.4;
	var pt = dpi / 72;
	var units = {
		'in' : dpi,
		'pt' : pt,
		'mm' : dpmm,
		'cm' : dpmm * 10,
		'm' : dpmm * 1000
	};

	for (var unit in units) if (units.hasOwnProperty(unit)) (function (factor) {
		Object.defineProperty(Number.prototype, unit, {
			get: function () {
				return this.valueOf() * factor;
			}
		});
	})(units[unit]);
}

setDPI(150);

console.log(10..mm);
console.log(10..cm);

しかし JSLint とかは 10..mm みたいな呼びかたをすると怒る。

アクロバティックな方法

'10 mm'

とかを数値に変換する形

var UnitConverter = function () { this.init.apply(this, arguments) };
UnitConverter.prototype = {
	init : function (opts) {
		if (!opts) opts = {};
		this.setDPI(opts.dpi || 96);
	},

	setDPI : function (dpi) {
		this.dpi = dpi;
		var dpmm = dpi / 25.4;
		var pt = dpi / 72;
		this.units = {
			'in' : dpi,
			'pt' : pt,
			'mm' : dpmm,
			'cm' : dpmm * 10,
			'm' : dpmm * 1000
		};

		var unitNames = [];
		for (var key in this.units) if (this.units.hasOwnProperty(key)) {
			unitNames.push(key);
		}

		this.re = new RegExp('([0-9.]+) (' + unitNames.join('|') + ')');
	},

	unit : function (string) {
		if (string.match(new RegExp('^' + this.re.source + '$'))) {
			return +RegExp.$1 * this.units[RegExp.$2];
		} else {
			return null;
		}
	},

	context : function (fun) {
		var self = this;
		var args = Array.prototype.slice.call(arguments, 1);
		fun = eval('(' + fun.toString().replace(new RegExp("'(" + this.re.source + ")'", 'g'), function (_, s) {
			return self.unit(s);
		}) + ')');
		fun.apply(null ,args);
	}
};

文字列化した関数を置換する。みためクロージャなのにクロージャになってないので変数アクセスで混乱する。つくれない。

結論

普通に係数使うのが一番シンプル。除算のほうがかっこいい気がする。ただし演算子の優先順位に気をつかわないとハマる。

  1. トップ
  2. tech
  3. JS 数値リテラルに単位をつけたい
▲ この日のエントリ