
Adobe XDはこれまで,アクションやスクリプトといった機能拡張に対応していませんでした。しかし2018年10月にアップデートされ,現在はプラグインで自動処理ができるようになっています。
プラグインといってもJavaScriptで記述する親しみやすいものです。今後はどんどん個人開発者が増え,便利になっていくことでしょう。楽しみですね。
さて本題です。図版やスライドなどを作る際には,1行程度のテキストを大量に用意することになります。
通常ですと,テキストエディタなどで入力した改行区切りのテキストを1行ずつコピペして分割していきます。ただこれはかなり疲弊する作業です。
もしIllustratorでやる場合にはテキストばらしという定番スクリプトがあり,名前の通りテキストを一瞬で1行ごとにばらしてくれます。XDにもこれがあったら嬉しいですね。
そこで今回は,改行区切りのテキストを1行ずつに分解するXD用プラグインを紹介します。
インストール方法
リンクからプラグインマネージャーでSplit Rowsをインストール
こちらのファイルをダウンロードしてください。
XDのプラグインはxdxというファイルでできています。このファイルをダブルクリックするなどして開くと,それだけでインストールできます。今回のプラグインの名前はSplit Rowsです。
2019.12.17 追記
version 2.0.3 Split Simple, Split Preserve Appearanceの2つのメニューに分けました。Simpleは今までと同じ動き,Preserve Appearanceは位置とスタイルを保持します。
2019.03.19 追記
version 1.2.1 自動行送りと段落スペースに対応しました。
使いかた
XDのアートボード上でテキストを選択し,メニューバーの プラグイン:Split Rows を選んで実行するだけです。すぐに1行ごとに分割されます。
▼動作イメージ
感激です!
ちなみに
プラグイン内のmanifest.jsonを編集すると,キーボードショートカットを割り振れます。文字を入力するだけの簡単仕様なので,参考サイトを見ながら設定してみてください。
はじめてのAdobe XDプラグイン開発!定番のHello Worldを表示させてみよう #AdobeXD #AdobeMAX – Adobe Creative Station
これでまた少し仕事が速くなりました。今日もさっさと仕事を切り上げて好きなことをしましょう!
プラグインを紹介していただきました。
コードはこちら
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
/** * @file テキストを行で分割する * @version 1.2.1 * @author sttk3.com * @copyright (c) 2019 sttk3.com */ const { Text } = require('scenegraph') ; const commands = require('commands') ; const { error } = require('./lib/dialogs.js') ; async function splitRowsMenuItem(selection) { const errorTitle = 'Error : ' ; const errorMsg = 'Please select the text, and then execute this plugin.' ; if(selection.items.length <= 0) { await error(errorTitle, errorMsg) ; return ; } let targetItem = selection.items[0] ; let newSelection ; switch(targetItem.constructor.name) { case 'Text' : newSelection = splitRows(selection, targetItem) ; break ; case 'Group' : const itemChildren = targetItem.children.filter(aItem => {return aItem instanceof Text}) ; if(itemChildren.length <= 0) { await error(errorTitle, errorMsg) ; return ; } newSelection = ungroupSession(selection, targetItem, (oldChildren, newChildren) => { Array.prototype.push.apply(newChildren, splitRows(selection, itemChildren[0])) ; }) ; break ; default : await error(errorTitle, errorMsg) ; return ; } if(newSelection[0] != null) {selection.items = newSelection ;} } /** * EditContextの編集制限回避のため,選択しているGroupのグループ解除・callback適用・再グループ化を行うブロック構文<br> * (oldChildren, newChildren) => {<br> * // do something<br> * <br> * // set new children<br> * newChildren = [...oldChildren] ;<br> * } * @param {Selection} selection selectionをそのまま渡す * @param {Group} groupItem 選択しているGroup * @param {Function} callback 実行するFunction * @return {Array} */ function ungroupSession(selection, groupItem, callback) { // Groupに名前がついていれば記録する let groupName ; if(!groupItem.hasDefaultName) {groupName = groupItem.name ;} // Group.childrenをarrayにする const oldChildren = [] ; groupItem.children.forEach(aItem => {oldChildren.push(aItem) ;}) ; // 再グループ化のためのarrayを用意する const newChildren = [] ; try { // グループを解除する selection.items = [groupItem] ; commands.ungroup() ; // callbackを実行する callback.call(callback, oldChildren, newChildren) ; } catch(e) { console.log(e) ; } finally { // 解除したものを再グループ化する selection.items = newChildren ; commands.group() ; if(groupName != null) {selection.items[0].name = groupName ;} } return [selection.items[0]] ; } /** * テキストを行ごとに分解する * @param {Selection} selection selectionをそのまま渡す * @param {Text} textNode 分解するText * @return {Array} */ function splitRows(selection, textNode) { // 元のテキストの情報を取得する const rows = textNode.text.split(/[\r\n]/g) ; let leading = textNode.lineSpacing ; let isAutoLeading = false ; const spaceAfter = textNode.paragraphSpacing ; const charSize = textNode.styleRanges[0].fontSize ; const halfCharSize = Math.ceil(charSize / 2) ; if(rows.length <= 1) {return textNode ;} // 情報を取得したあとはデータを軽くしておく textNode.text = 'dummy' ; // areaTextの場合は高さを文字と合わせる const box = textNode.areaBox ; if(box) { textNode.resize(box.width, charSize) ; } // lineSpacingが0,つまり行送り自動の場合は文字サイズの1.7倍(小数点以下切り上げ)にする if(leading <= 0) { isAutoLeading = true ; leading = Math.ceil(charSize * 1.7) ; } // テキストを行ごとに分割する。repeatGridを使いたかったが,現状ではプラグインから作成できないらしい const patternInvisibleLine = /^[\s]*$/m ; const offset = leading + spaceAfter ; let narrowAmount = 0 ; let currentNode ; let res = [] ; rows.forEach((row, i) => { if(patternInvisibleLine.test(row)) { if(isAutoLeading) { narrowAmount -= halfCharSize ; } } else { selection.items = [textNode] ; commands.duplicate() ; // selection.itemsに対して行われる currentNode = selection.items[0] ; currentNode.text = row ; currentNode.moveInParentCoordinates(0, (offset * i) + narrowAmount) ; res.push(currentNode) ; } }) ; // 元のテキストを削除する textNode.removeFromParent() ; return res ; } module.exports = { commands: { splitRows: splitRowsMenuItem } } ; |
このサイトで配布しているスクリプトやその他のファイルを,無断で転載・配布・販売することを禁じます。
それらの使用により生じたあらゆる損害について,私どもは責任を負いません。
スクリプトやファイルのダウンロードを行った時点で,上記の規定に同意したとみなします。
コメント