Skip to content

Instantly share code, notes, and snippets.

@h-tawara
Last active Mar 9, 2021
Embed
What would you like to do?
【Photoshop】指定レイヤーの文字列をスライスして複数レイヤーにするツール
/*================================================================================
# TextSlicer for Photoshop
# 指定レイヤーの文字列をスライスして複数レイヤーにするツール
================================================================================*/
#target photoshop
//================================================================================
const SCRIPT_TITLE = "TextSlicer";
const STATIC_TEXT_MIN_WIDTH = 60;
const EDIT_TEXT_MIN_WIDTH = 100;
const EDIT_TEXT_MIN_HEIGHT = 30;
//================================================================================
var g_DocRef;
var g_TargetLayer;
var g_TextContents;
var g_Height;
var g_XAddPos;
//================================================================================
// 実行部
app.activeDocument.suspendHistory("TextSlicer","Run()");
//================================================================================
// メイン処理
function Run() {
// 単位設定を保持+Pixelに変換
var myRulerUnits = preferences.rulerUnits;
preferences.rulerUnits = Units.PIXELS;
g_DocRef = app.activeDocument;
g_TargetLayer = g_DocRef.activeLayer;
Init();
// 設定のチェック
if (SettingCheck ()) {
// 実行ボタンが押されたら
grpSystemButton.btnApply.onClick = function () {
// テキストのパラメータを設定
InitTextParam();
switch(grpSlicePattern.sliceType.selection.text) {
case "char":
TextCharSlice();
break;
case "line":
TextLineSlice();
break;
default:
alert("スライス方式を選択してください。", "エラー通知");
break;
}
//元レイヤーを削除する?
if (grpDeleteCheck.cBox.value) {
g_TargetLayer.remove();
}
alert("スライスが完了しました。", "完了通知");
}
dlg.show();
}
// 単位設定を元に戻す
preferences.rulerUnits = myRulerUnits;
}
//================================================================================
// 初期化処理
function Init () {
SettingWindow();
grpSlicePattern.sliceType.selection = 0;
}
//================================================================================
// ウィンドウの設定
function SettingWindow () {
// --ウィンドウの生成
dlg = new Window ("dialog", SCRIPT_TITLE);
dlg.minimumSize = [200, 100];
dlg.margins = [10, 10, 10, 10];
// --Panel > Setting
dlg.pnlSetting = dlg.add("panel", undefined,"Setting");
dlg.pnlSetting.alignment = "left";
dlg.pnlSetting.minimumSize = [210, undefined];
// -- Setting > SlicePattern
grpSlicePattern = dlg.pnlSetting.add("group");
grpSlicePattern.alignment = "left";
grpSlicePattern.sText = grpSlicePattern.add("statictext", undefined, "スライス方式:");
grpSlicePattern.sText.minimumSize = [STATIC_TEXT_MIN_WIDTH, undefined];
grpSlicePattern.sliceType = grpSlicePattern.add("dropdownlist", undefined, ["char", "line"]);
// -- Setting > DeleteCheck
grpDeleteCheck = dlg.pnlSetting.add("group");
grpDeleteCheck.alignment = "left";
grpDeleteCheck.cBox = grpDeleteCheck.add("checkbox", undefined, ":元レイヤーを削除");
// --システムボタン
grpSystemButton = dlg.add("group");
grpSystemButton.btnApply = grpSystemButton.add("button",undefined, "実行", { name:"apply"});
grpSystemButton.btnApply.minimumSize = [EDIT_TEXT_MIN_WIDTH, EDIT_TEXT_MIN_HEIGHT];
grpSystemButton.btnCancel = grpSystemButton.add("button",undefined, "閉じる", { name:"cancel"});
grpSystemButton.btnCancel.minimumSize = [EDIT_TEXT_MIN_WIDTH, EDIT_TEXT_MIN_HEIGHT];
}
//================================================================================
// 設定のエラーチェック処理
function SettingCheck() {
if (g_TargetLayer.kind != LayerKind.TEXT) {
alert("選択レイヤーがテキストレイヤーではありません。", "エラー通知");
return false;
}
return true;
}
//================================================================================
// テキストを1文字ずつスライス処理
function TextCharSlice() {
var xCount = 0;
var yCount = 0;
for (var i = 0; i < g_TextContents.length; i++) {
// 改行文字の場合
if(g_TextContents[i] == "\r" || g_TextContents[i] == "\n" || g_TextContents[i] == "\r\n") {
yCount++;
xCount = 0;
} else {
var newLayer = g_TargetLayer.duplicate();
newLayer.textItem.contents = g_TextContents[i];
switch(g_TargetLayer.textItem.justification) {
case Justification.LEFT:
newLayer.translate(g_XAddPos * xCount, g_Height * yCount);
break;
case Justification.CENTER:
var center = Math.ceil(g_TextContents.length / 2.0);
var pos;
if (i < center) {
pos = -(center - i - 1);
} else {
pos = i - center + 1;
}
newLayer.translate(g_XAddPos * pos, g_Height * yCount);
break;
case Justification.RIGHT:
var pos = (g_TextContents.length - 1) - xCount;
newLayer.translate(-g_XAddPos * pos, g_Height * yCount);
break;
default:
newLayer.translate(g_XAddPos * xCount, g_Height * yCount);
break;
}
xCount++;
}
}
}
//================================================================================
// テキストを行ごとにスライス処理
function TextLineSlice() {
var text = g_TargetLayer.textItem.contents;
var lineList = text.split(/\r\n|\r|\n/);
for (var i = 0; i < lineList.length; i++) {
var newLayer = g_TargetLayer.duplicate();
newLayer.textItem.contents = lineList[i];
newLayer.translate(0, g_Height * i);
}
}
//================================================================================
// テキストレイヤーのパラメータを取得、設定
function InitTextParam() {
var currentTextItem = g_TargetLayer.textItem;
g_TextContents = currentTextItem.contents;
// 改行の高さが自動行送りに設定されていたら
if (currentTextItem.useAutoLeading) {
alert("「自動行送り」が設定されています。\n高さを揃える場合はテキストの行の高さを設定してください。","警告");
g_Height = currentTextItem.size;
} else {
g_Height = currentTextItem.leading;
}
// 文字の横移動値を計算
var textSize = currentTextItem.size;
g_XAddPos = textSize;
// 横スケールの反映
try {
var horizontalScale = currentTextItem.horizontalScale / 100
g_XAddPos *= horizontalScale;
} catch(e) {
// プロパティで一度も値を設定していない時にプロパティが取れないので回避
}
// トラッキングの反映
try {
var tracking = currentTextItem.tracking;
var trackingSpace = textSize * (tracking / 1000);
g_XAddPos += trackingSpace;
} catch(e) {
// プロパティで一度も値を設定していない時にプロパティが取れないので回避
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment