danoniplus 27.0.0 → 27.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/js/danoni_main.js CHANGED
@@ -4,12 +4,12 @@
4
4
  *
5
5
  * Source by tickle
6
6
  * Created : 2018/10/08
7
- * Revised : 2022/03/12
7
+ * Revised : 2022/04/10
8
8
  *
9
9
  * https://github.com/cwtickle/danoniplus
10
10
  */
11
- const g_version = `Ver 27.0.0`;
12
- const g_revisedDate = `2022/03/18`;
11
+ const g_version = `Ver 27.3.0`;
12
+ const g_revisedDate = `2022/04/10`;
13
13
  const g_alphaVersion = ``;
14
14
 
15
15
  // カスタム用バージョン (danoni_custom.js 等で指定可)
@@ -41,11 +41,11 @@ let g_localVersion2 = ``;
41
41
  */
42
42
  const current = _ => {
43
43
  if (document.currentScript) {
44
- return document.currentScript.src;
44
+ return encodeURI(document.currentScript.src);
45
45
  }
46
46
  const scripts = document.getElementsByTagName(`script`);
47
47
  const targetScript = scripts[scripts.length - 1];
48
- return targetScript.src;
48
+ return encodeURI(targetScript.src);
49
49
  };
50
50
  const g_rootPath = current().match(/(^.*\/)/)[0];
51
51
  const g_remoteFlg = g_rootPath.match(`^https://cwtickle.github.io/danoniplus/`) !== null;
@@ -54,6 +54,10 @@ const g_randTime = Date.now();
54
54
  window.onload = async () => {
55
55
  g_loadObj.main = true;
56
56
  g_currentPage = `initial`;
57
+ const links = document.querySelectorAll(`link`);
58
+ if (Array.from(links).filter(elem => elem.getAttribute(`href`).indexOf(`danoni_main.css`) !== -1).length === 0) {
59
+ await importCssFile2(`${g_rootPath}../css/danoni_main.css?${g_randTime}`);
60
+ }
57
61
 
58
62
  // ロード直後に定数・初期化ファイル、旧バージョン定義関数を読込
59
63
  await loadScript2(`${g_rootPath}../js/lib/danoni_localbinary.js?${g_randTime}`, false);
@@ -240,7 +244,7 @@ const hasVal = _data => _data !== undefined && _data !== ``;
240
244
  * @param {string} _default
241
245
  * @param {string} _type
242
246
  */
243
- const setVal = (_checkStr, _default, _type) => {
247
+ const setVal = (_checkStr, _default, _type = C_TYP_STRING) => {
244
248
 
245
249
  let convertStr = _checkStr;
246
250
 
@@ -881,6 +885,18 @@ const getFontSize = (_str, _maxWidth, _font = getBasicFont(), _maxFontsize = 64,
881
885
  return _minFontsize;
882
886
  };
883
887
 
888
+ /**
889
+ * 補足説明部分のラベル作成
890
+ * @param {string} _id
891
+ * @param {string} _str
892
+ * @param {string} _altId
893
+ * @returns
894
+ */
895
+ const createDescDiv = (_id, _str, _altId = _id) =>
896
+ createDivCss2Label(_id, _str, Object.assign(g_lblPosObj[_altId], {
897
+ siz: getFontSize(_str, g_sWidth, getBasicFont(), C_SIZ_MAIN),
898
+ }));
899
+
884
900
  /*-----------------------------------------------------------*/
885
901
  /* ラベル・ボタン・オブジェクトの作成 */
886
902
  /*-----------------------------------------------------------*/
@@ -961,6 +977,26 @@ const createImg = (_id, _imgPath, _x, _y, _width, _height) => {
961
977
  return div;
962
978
  };
963
979
 
980
+ /**
981
+ * ColorPickerの作成
982
+ * @param {string} _parentObj
983
+ * @param {string} _id
984
+ * @param {function} _func
985
+ * @param {object} _obj
986
+ * @returns
987
+ */
988
+ const createColorPicker = (_parentObj, _id, _func, { x = 0, y = 0 } = {}) => {
989
+ const picker = document.createElement(`input`);
990
+ picker.setAttribute(`type`, `color`);
991
+ picker.id = _id;
992
+ picker.style.left = `${x}px`;
993
+ picker.style.top = `${y}px`;
994
+ picker.style.position = `absolute`;
995
+ picker.addEventListener(`change`, _func);
996
+ _parentObj.appendChild(picker);
997
+ return picker;
998
+ };
999
+
964
1000
  /**
965
1001
  * 色付きオブジェクトの作成 (拡張属性対応)
966
1002
  * @param {string} _id
@@ -1221,6 +1257,7 @@ const clearWindow = (_redrawFlg = false, _customDisplayName = ``) => {
1221
1257
  // レイヤー情報取得
1222
1258
  const layer0 = document.querySelector(`#layer0`);
1223
1259
  const l0ctx = layer0.getContext(`2d`);
1260
+ layer0.width = g_sWidth;
1224
1261
 
1225
1262
  // 線画、図形をクリア
1226
1263
  l0ctx.clearRect(0, 0, g_sWidth, g_sHeight);
@@ -1228,24 +1265,26 @@ const clearWindow = (_redrawFlg = false, _customDisplayName = ``) => {
1228
1265
  if (document.querySelector(`#layer1`) !== null) {
1229
1266
  const layer1 = document.querySelector(`#layer1`);
1230
1267
  const l1ctx = layer1.getContext(`2d`);
1268
+ layer1.width = g_sWidth;
1231
1269
  l1ctx.clearRect(0, 0, g_sWidth, g_sHeight);
1232
1270
 
1233
1271
  // 線画 (title-line)
1234
1272
  l1ctx.beginPath();
1235
1273
  l1ctx.strokeStyle = `#cccccc`;
1236
1274
  l1ctx.moveTo(0, 0);
1237
- l1ctx.lineTo(g_sWidth, 0);
1275
+ l1ctx.lineTo(layer1.width, 0);
1238
1276
  l1ctx.stroke();
1239
1277
 
1240
1278
  l1ctx.beginPath();
1241
1279
  l1ctx.strokeStyle = `#cccccc`;
1242
1280
  l1ctx.moveTo(0, g_sHeight);
1243
- l1ctx.lineTo(g_sWidth, g_sHeight);
1281
+ l1ctx.lineTo(layer1.width, g_sHeight);
1244
1282
  l1ctx.stroke();
1245
1283
  }
1246
1284
  if (document.querySelector(`#layer2`) !== null) {
1247
1285
  const layer2 = document.querySelector(`#layer2`);
1248
1286
  const l2ctx = layer2.getContext(`2d`);
1287
+ layer2.width = g_sWidth;
1249
1288
  l2ctx.clearRect(0, 0, g_sWidth, g_sHeight);
1250
1289
  }
1251
1290
  }
@@ -1386,7 +1425,7 @@ const makeSpriteData = (_data, _calcFrame = _frame => _frame) => {
1386
1425
  width: setIntVal(tmpSpriteData[6]), // spanタグの場合は font-size
1387
1426
  height: escapeHtml(tmpSpriteData[7] ?? ``), // spanタグの場合は color(文字列可)
1388
1427
  opacity: setVal(tmpSpriteData[8], 1, C_TYP_FLOAT),
1389
- animationName: escapeHtml(setVal(tmpSpriteData[9], C_DIS_NONE, C_TYP_STRING)),
1428
+ animationName: escapeHtml(setVal(tmpSpriteData[9], C_DIS_NONE)),
1390
1429
  animationDuration: setIntVal(tmpSpriteData[10]) / g_fps,
1391
1430
  };
1392
1431
  if (g_headerObj.autoPreload) {
@@ -1703,15 +1742,8 @@ const initialControl = async () => {
1703
1742
  g_canLoadDifInfoFlg = true;
1704
1743
 
1705
1744
  // 譜面データの読み込みオプション
1706
- const ampSplitInput = document.querySelector(`#enableAmpersandSplit`);
1707
- if (ampSplitInput !== null) {
1708
- g_enableAmpersandSplit = setBoolVal(ampSplitInput.value, true);
1709
- }
1710
-
1711
- const decodeUriInput = document.querySelector(`#enableDecodeURI`);
1712
- if (decodeUriInput !== null) {
1713
- g_enableDecodeURI = setBoolVal(decodeUriInput.value);
1714
- }
1745
+ g_enableAmpersandSplit = setBoolVal(document.querySelector(`#enableAmpersandSplit`)?.value, true);
1746
+ g_enableDecodeURI = setBoolVal(document.querySelector(`#enableDecodeURI`)?.value);
1715
1747
 
1716
1748
  // 作品別ローカルストレージの読み込み
1717
1749
  loadLocalStorage();
@@ -1763,6 +1795,21 @@ const initialControl = async () => {
1763
1795
  makeDedupliArray(g_rootObj.keyExtraList.split(`,`), g_headerObj.undefinedKeyLists) : g_headerObj.undefinedKeyLists),
1764
1796
  });
1765
1797
 
1798
+ // 自動横幅拡張設定
1799
+ if (g_headerObj.autoSpread) {
1800
+ const widthList = [g_sWidth, g_presetObj.autoMinWidth ?? g_keyObj.minWidth];
1801
+ g_headerObj.keyLists.forEach(key => widthList.push(g_keyObj[`minWidth${key}`] ?? g_keyObj.minWidthDefault));
1802
+
1803
+ g_sWidth = Math.max(...widthList);
1804
+ $id(`canvas-frame`).width = `${g_sWidth}px`;
1805
+ }
1806
+ if (g_headerObj.playingWidth === `default`) {
1807
+ g_headerObj.playingWidth = g_sWidth;
1808
+ }
1809
+
1810
+ // 可変ウィンドウサイズを更新
1811
+ updateWindowSiz();
1812
+
1766
1813
  // キー数情報を初期化
1767
1814
  g_keyObj.currentKey = g_headerObj.keyLabels[g_stateObj.scoreId];
1768
1815
  g_keyObj.currentPtn = 0;
@@ -1791,12 +1838,12 @@ const initialControl = async () => {
1791
1838
  if (termRoopCnts.length === 1) {
1792
1839
  // Pattern Bの場合
1793
1840
  lastCnt = setIntVal(tmpPreloadImages[1], 1);
1794
- paddingLen = String(setVal(tmpPreloadImages[1], 1, C_TYP_STRING)).length;
1841
+ paddingLen = String(setVal(tmpPreloadImages[1], 1)).length;
1795
1842
  } else {
1796
1843
  // Pattern C, Dの場合
1797
1844
  startCnt = setIntVal(termRoopCnts[0], 1);
1798
1845
  lastCnt = setIntVal(termRoopCnts[1], 1);
1799
- paddingLen = String(setVal(termRoopCnts[1], 1, C_TYP_STRING)).length;
1846
+ paddingLen = String(setVal(termRoopCnts[1], 1)).length;
1800
1847
  }
1801
1848
  for (let k = startCnt; k <= lastCnt; k++) {
1802
1849
  preloadFile(`image`, tmpPreloadImages[0].replaceAll(`*`, String(k).padStart(paddingLen, `0`)));
@@ -1833,6 +1880,7 @@ const initialControl = async () => {
1833
1880
  getScoreDetailData(j);
1834
1881
  }
1835
1882
  }
1883
+ g_customJsObj.preTitle.forEach(func => func());
1836
1884
  titleInit();
1837
1885
  };
1838
1886
 
@@ -1926,7 +1974,8 @@ const loadChartFile = async (_scoreId = g_stateObj.scoreId) => {
1926
1974
 
1927
1975
  const dosInput = document.querySelector(`#dos`);
1928
1976
  const divRoot = document.querySelector(`#divRoot`);
1929
- const queryDos = getQueryParamVal(`dos`) !== null ? `dos/${getQueryParamVal('dos')}.txt` : (document.querySelector(`#externalDos`)?.value ?? ``);
1977
+ const queryDos = getQueryParamVal(`dos`) !== null ?
1978
+ `dos/${getQueryParamVal('dos')}.txt` : encodeURI(document.querySelector(`#externalDos`)?.value ?? ``);
1930
1979
 
1931
1980
  if (dosInput === null && queryDos === ``) {
1932
1981
  makeWarningWindow(g_msgInfoObj.E_0023);
@@ -2296,6 +2345,12 @@ const preheaderConvert = _dosObj => {
2296
2345
  // ヘッダー群の格納先
2297
2346
  const obj = {};
2298
2347
 
2348
+ // ウィンドウ位置の設定
2349
+ const align = _dosObj.windowAlign ?? g_presetObj.windowAlign;
2350
+ if (align !== undefined) {
2351
+ g_windowAlign[align]();
2352
+ }
2353
+
2299
2354
  obj.jsData = [];
2300
2355
 
2301
2356
  const setJsFiles = (_files, _defaultDir, _type = `custom`) => {
@@ -2315,11 +2370,11 @@ const preheaderConvert = _dosObj => {
2315
2370
 
2316
2371
  // 外部jsファイルの指定
2317
2372
  const tmpCustomjs = _dosObj.customjs ?? g_presetObj.customJs ?? C_JSF_CUSTOM;
2318
- setJsFiles(tmpCustomjs.split(`,`), C_DIR_JS);
2373
+ setJsFiles(tmpCustomjs.replaceAll(`*`, g_presetObj.customJs).split(`,`), C_DIR_JS);
2319
2374
 
2320
2375
  // 外部cssファイルの指定
2321
2376
  const tmpCustomcss = _dosObj.customcss ?? g_presetObj.customCss ?? ``;
2322
- setJsFiles(tmpCustomcss.split(`,`), C_DIR_CSS);
2377
+ setJsFiles(tmpCustomcss.replaceAll(`*`, g_presetObj.customCss).split(`,`), C_DIR_CSS);
2323
2378
 
2324
2379
  // デフォルト曲名表示、背景、Ready表示の利用有無
2325
2380
  g_titleLists.init.forEach(objName => {
@@ -2388,6 +2443,15 @@ const headerConvert = _dosObj => {
2388
2443
  Object.assign(g_lblNameObj, g_lang_lblNameObj[g_localeObj.val], g_presetObj.lblName?.[g_localeObj.val]);
2389
2444
  Object.assign(g_msgObj, g_lang_msgObj[g_localeObj.val], g_presetObj.msg?.[g_localeObj.val]);
2390
2445
 
2446
+ // 自動横幅拡張設定
2447
+ obj.autoSpread = setBoolVal(_dosObj.autoSpread, g_presetObj.autoSpread ?? true);
2448
+
2449
+ // 横幅設定
2450
+ if (hasVal(_dosObj.windowWidth)) {
2451
+ g_sWidth = setIntVal(_dosObj.windowWidth, g_sWidth);
2452
+ $id(`canvas-frame`).width = `${g_sWidth}px`;
2453
+ }
2454
+
2391
2455
  // 曲名
2392
2456
  obj.musicTitles = [];
2393
2457
  obj.musicTitlesForView = [];
@@ -2577,10 +2641,9 @@ const headerConvert = _dosObj => {
2577
2641
  }
2578
2642
 
2579
2643
  // 初期色情報
2644
+ const baseColor = (obj.baseBrightFlg ? `light` : `dark`);
2645
+ Object.assign(g_dfColorObj, g_dfColorBaseObj[baseColor]);
2580
2646
  Object.keys(g_dfColorObj).forEach(key => obj[key] = g_dfColorObj[key].concat());
2581
- if (obj.baseBrightFlg) {
2582
- Object.keys(g_dfColorLightObj).forEach(key => obj[key] = g_dfColorLightObj[key].concat());
2583
- }
2584
2647
  obj.frzColorDefault = [];
2585
2648
 
2586
2649
  // ダミー用初期矢印色
@@ -2676,9 +2739,7 @@ const headerConvert = _dosObj => {
2676
2739
  }
2677
2740
 
2678
2741
  // ハッシュタグ
2679
- if (hasVal(_dosObj.hashTag)) {
2680
- obj.hashTag = _dosObj.hashTag;
2681
- }
2742
+ obj.hashTag = setVal(_dosObj.hashTag, ``);
2682
2743
 
2683
2744
  // 自動プリロードの設定
2684
2745
  obj.autoPreload = setBoolVal(_dosObj.autoPreload, true);
@@ -2719,13 +2780,9 @@ const headerConvert = _dosObj => {
2719
2780
  // デフォルト曲名表示のフォント名
2720
2781
  // (使用例: |titlefont=Century,Meiryo UI|)
2721
2782
  obj.titlefonts = g_titleLists.defaultFonts.concat();
2722
- if (hasVal(_dosObj.titlefont)) {
2723
- _dosObj.titlefont.split(`$`).forEach((font, j) => {
2724
- obj.titlefonts[j] = `'${(font.replaceAll(`,`, `', '`))}'`;
2725
- });
2726
- if (obj.titlefonts[1] === undefined) {
2727
- obj.titlefonts[1] = obj.titlefonts[0];
2728
- }
2783
+ _dosObj.titlefont?.split(`$`).forEach((font, j) => obj.titlefonts[j] = `'${(font.replaceAll(`,`, `', '`))}'`);
2784
+ if (obj.titlefonts[1] === undefined) {
2785
+ obj.titlefonts[1] = obj.titlefonts[0];
2729
2786
  }
2730
2787
 
2731
2788
  // デフォルト曲名表示, 背景矢印のグラデーション指定css
@@ -2740,11 +2797,7 @@ const headerConvert = _dosObj => {
2740
2797
 
2741
2798
  // デフォルト曲名表示の表示位置調整
2742
2799
  obj.titlepos = [[0, 0], [0, 0]];
2743
- if (hasVal(_dosObj.titlepos)) {
2744
- _dosObj.titlepos.split(`$`).forEach((pos, j) => {
2745
- obj.titlepos[j] = pos.split(`,`).map(x => parseFloat(x));
2746
- });
2747
- }
2800
+ _dosObj.titlepos?.split(`$`).forEach((pos, j) => obj.titlepos[j] = pos.split(`,`).map(x => parseFloat(x)));
2748
2801
 
2749
2802
  // タイトル文字のアニメーション設定
2750
2803
  obj.titleAnimationName = [`leftToRight`];
@@ -2752,20 +2805,18 @@ const headerConvert = _dosObj => {
2752
2805
  obj.titleAnimationDelay = [0];
2753
2806
  obj.titleAnimationTimingFunction = [`ease`];
2754
2807
  obj.titleAnimationClass = [``];
2755
- if (hasVal(_dosObj.titleanimation)) {
2756
- _dosObj.titleanimation.split(`$`).forEach((pos, j) => {
2757
- const titleAnimation = pos.split(`,`);
2758
- obj.titleAnimationName[j] = setVal(titleAnimation[0], obj.titleAnimationName[0], C_TYP_STRING);
2759
- obj.titleAnimationDuration[j] = setVal(titleAnimation[1] / g_fps, obj.titleAnimationDuration[0], C_TYP_FLOAT);
2760
- obj.titleAnimationDelay[j] = setVal(titleAnimation[2] / g_fps, obj.titleAnimationDelay[0], C_TYP_FLOAT);
2761
- obj.titleAnimationTimingFunction[j] = setVal(titleAnimation[3], obj.titleAnimationName[3], C_TYP_STRING);
2762
- });
2763
- }
2764
- if (hasVal(_dosObj.titleanimationclass)) {
2765
- _dosObj.titleanimationclass.split(`$`).forEach((animationClass, j) => {
2766
- obj.titleAnimationClass[j] = animationClass ?? ``;
2767
- });
2768
- }
2808
+
2809
+ _dosObj.titleanimation?.split(`$`).forEach((pos, j) => {
2810
+ const titleAnimation = pos.split(`,`);
2811
+ obj.titleAnimationName[j] = setVal(titleAnimation[0], obj.titleAnimationName[0]);
2812
+ obj.titleAnimationDuration[j] = setVal(titleAnimation[1] / g_fps, obj.titleAnimationDuration[0], C_TYP_FLOAT);
2813
+ obj.titleAnimationDelay[j] = setVal(titleAnimation[2] / g_fps, obj.titleAnimationDelay[0], C_TYP_FLOAT);
2814
+ obj.titleAnimationTimingFunction[j] = setVal(titleAnimation[3], obj.titleAnimationName[3]);
2815
+ });
2816
+ _dosObj.titleanimationclass?.split(`$`).forEach((animationClass, j) => {
2817
+ obj.titleAnimationClass[j] = animationClass ?? ``;
2818
+ });
2819
+
2769
2820
  if (obj.titleAnimationName.length === 1) {
2770
2821
  g_titleLists.animation.forEach(pattern => {
2771
2822
  obj[`titleAnimation${pattern}`][1] = obj[`titleAnimation${pattern}`][0];
@@ -2899,7 +2950,7 @@ const headerConvert = _dosObj => {
2899
2950
  obj.wordAutoReverse = _dosObj.wordAutoReverse ?? g_presetObj.wordAutoReverse ?? `auto`;
2900
2951
 
2901
2952
  // プレイサイズ(X方向)
2902
- obj.playingWidth = setIntVal(_dosObj.playingWidth, g_sWidth);
2953
+ obj.playingWidth = setIntVal(_dosObj.playingWidth, `default`);
2903
2954
 
2904
2955
  // プレイ左上位置(X座標)
2905
2956
  obj.playingX = setIntVal(_dosObj.playingX);
@@ -2969,9 +3020,7 @@ const updateImgType = _imgType => {
2969
3020
  * ゲージ設定リストへの追加
2970
3021
  * @param {object} _obj
2971
3022
  */
2972
- const addGaugeFulls = _obj => {
2973
- _obj.map(key => g_gaugeOptionObj.customFulls[key] = false);
2974
- };
3023
+ const addGaugeFulls = _obj => _obj.map(key => g_gaugeOptionObj.customFulls[key] = false);
2975
3024
 
2976
3025
  /**
2977
3026
  * 矢印・フリーズアロー色のデータ変換
@@ -3020,19 +3069,18 @@ const resetBaseColorList = (_baseObj, _dosObj, { scoreId = `` } = {}) => {
3020
3069
  _baseObj[_frzInit].length : firstFrzColors.length;
3021
3070
  for (let k = 0; k < baseLength; k++) {
3022
3071
  currentFrzColors[k] = setVal(firstFrzColors[k],
3023
- _baseObj.defaultFrzColorUse ? _baseObj[_frzInit][k] : obj[`${_name}Str`][j], C_TYP_STRING);
3072
+ _baseObj.defaultFrzColorUse ? _baseObj[_frzInit][k] : obj[`${_name}Str`][j]);
3024
3073
  }
3025
3074
 
3026
- Object.keys(_baseObj.dfColorgrdSet).forEach(type => {
3075
+ Object.keys(_baseObj.dfColorgrdSet).forEach(type =>
3027
3076
  [obj[`${_frzName}${type}`][j], obj[`${_frzName}Str${type}`][j], obj[`${_frzName}Org${type}`][j]] =
3028
- setColorList(tmpFrzColors[j], currentFrzColors, _baseObj[_frzInit].length, {
3029
- _defaultColorgrd: _baseObj.dfColorgrdSet[type],
3030
- _colorCdPaddingUse: _baseObj.colorCdPaddingUse,
3031
- _defaultFrzColorUse: _baseObj.defaultFrzColorUse,
3032
- _objType: `frz`,
3033
- _shadowFlg: pattern === `Shadow`,
3034
- });
3035
- });
3077
+ setColorList(tmpFrzColors[j], currentFrzColors, _baseObj[_frzInit].length, {
3078
+ _defaultColorgrd: _baseObj.dfColorgrdSet[type],
3079
+ _colorCdPaddingUse: _baseObj.colorCdPaddingUse,
3080
+ _defaultFrzColorUse: _baseObj.defaultFrzColorUse,
3081
+ _objType: `frz`,
3082
+ _shadowFlg: pattern === `Shadow`,
3083
+ }));
3036
3084
  }
3037
3085
 
3038
3086
  obj[`${_name}Default`] = obj[_name].concat();
@@ -3316,8 +3364,7 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList.split(`,`) }
3316
3364
  if (_dosObj[keyheader] !== undefined) {
3317
3365
  const tmps = _dosObj[keyheader].split(`$`);
3318
3366
  for (let k = 0; k < tmps.length; k++) {
3319
- g_keyObj[`${keyheader}_${k}`] = setVal(g_keyObj[`${_name}${tmps[k]}`],
3320
- setVal(tmps[k], ``, _type), C_TYP_STRING);
3367
+ g_keyObj[`${keyheader}_${k}`] = setVal(g_keyObj[`${_name}${tmps[k]}`], setVal(tmps[k], ``, _type));
3321
3368
  }
3322
3369
  }
3323
3370
  };
@@ -3372,6 +3419,9 @@ const keysConvert = (_dosObj, { keyExtraList = _dosObj.keyExtraList.split(`,`) }
3372
3419
  // キーの名前 (keyNameX)
3373
3420
  g_keyObj[`keyName${newKey}`] = _dosObj[`keyName${newKey}`] ?? newKey;
3374
3421
 
3422
+ // キーの最小横幅 (minWidthX)
3423
+ g_keyObj[`minWidth${newKey}`] = _dosObj[`minWidth${newKey}`] ?? g_keyObj.minWidthDefault;
3424
+
3375
3425
  // 矢印色パターン (colorX_Y)
3376
3426
  tmpMinPatterns = newKeyMultiParam(newKey, `color`, toNumber, {
3377
3427
  errCd: `E_0101`,
@@ -3534,11 +3584,8 @@ const titleInit = _ => {
3534
3584
  const titlegrd2 = g_headerObj.titlegrds[1] || titlegrd1;
3535
3585
 
3536
3586
  const titlegrds = [];
3537
- [titlegrd1, titlegrd2].forEach((titlegrd, j) => {
3538
- titlegrds[j] = makeColorGradation(titlegrd, {
3539
- _defaultColorgrd: false, _objType: `titleMusic`,
3540
- });
3541
- });
3587
+ [titlegrd1, titlegrd2].forEach((titlegrd, j) =>
3588
+ titlegrds[j] = makeColorGradation(titlegrd, { _defaultColorgrd: false, _objType: `titleMusic` }));
3542
3589
 
3543
3590
  let titlefontsize = 64;
3544
3591
  for (let j = 0; j < g_headerObj.musicTitleForView.length; j++) {
@@ -3619,6 +3666,17 @@ const titleInit = _ => {
3619
3666
  let reloadFlg = false;
3620
3667
  const getLinkSiz = _name => getFontSize(_name, g_sWidth / 2 - 20, getBasicFont(), C_LBL_LNKSIZE, 12);
3621
3668
 
3669
+ /**
3670
+ * クレジット用リンク作成
3671
+ * @param {string} _id
3672
+ * @param {string} _text
3673
+ * @param {string} _url
3674
+ * @returns
3675
+ */
3676
+ const createCreditBtn = (_id, _text, _url) =>
3677
+ createCss2Button(_id, _text, _ => true,
3678
+ Object.assign(g_lblPosObj[_id], { siz: getLinkSiz(_text), resetFunc: _ => openLink(_url) }), g_cssObj.button_Default);
3679
+
3622
3680
  // ボタン描画
3623
3681
  multiAppend(divRoot,
3624
3682
 
@@ -3639,63 +3697,49 @@ const titleInit = _ => {
3639
3697
  localStorage.setItem(g_localStorageUrl, JSON.stringify(g_localStorage));
3640
3698
  reloadFlg = true;
3641
3699
  }
3642
- }, {
3643
- x: 0, y: g_sHeight - 20, w: g_sWidth / 4, h: 16, siz: 12, title: g_msgObj.dataReset,
3700
+ }, Object.assign(g_lblPosObj.btnReset, {
3644
3701
  resetFunc: _ => {
3645
3702
  if (reloadFlg) {
3646
3703
  location.reload();
3647
3704
  }
3648
3705
  },
3649
- }, g_cssObj.button_Reset),
3706
+ }), g_cssObj.button_Reset),
3650
3707
 
3651
3708
  // ロケール切替
3652
- createCss2Button(`btnReload`, g_localeObj.val, _ => true, {
3653
- x: 10, y: 10, w: 30, h: 30, siz: 20, title: g_msgObj.reload,
3654
- resetFunc: _ => {
3655
- g_localeObj.num = (++g_localeObj.num) % g_localeObj.list.length;
3656
- g_langStorage.locale = g_localeObj.list[g_localeObj.num];
3657
- localStorage.setItem(`danoni-locale`, JSON.stringify(g_langStorage));
3658
- location.reload();
3659
- },
3660
- }, g_cssObj.button_Start),
3709
+ createCss2Button(`btnReload`, g_localeObj.val, _ => true,
3710
+ Object.assign(g_lblPosObj.btnReload, {
3711
+ resetFunc: _ => {
3712
+ g_localeObj.num = (++g_localeObj.num) % g_localeObj.list.length;
3713
+ g_langStorage.locale = g_localeObj.list[g_localeObj.num];
3714
+ localStorage.setItem(`danoni-locale`, JSON.stringify(g_langStorage));
3715
+ location.reload();
3716
+ },
3717
+ }), g_cssObj.button_Start),
3661
3718
 
3662
3719
  // ヘルプ
3663
- createCss2Button(`btnHelp`, `?`, _ => true, {
3664
- x: 0, y: g_sHeight - 150, w: 40, h: 40, siz: 30, title: g_msgObj.howto,
3665
- resetFunc: _ => openLink(`https://github.com/cwtickle/danoniplus/wiki/AboutGameSystem`),
3666
- }, g_cssObj.button_Setting),
3720
+ createCss2Button(`btnHelp`, `?`, _ => true,
3721
+ Object.assign(g_lblPosObj.btnHelp, {
3722
+ resetFunc: _ => openLink(`https://github.com/cwtickle/danoniplus/wiki/AboutGameSystem`),
3723
+ }), g_cssObj.button_Setting),
3667
3724
 
3668
3725
  // 製作者表示
3669
- createCss2Button(`lnkMaker`, `${g_lblNameObj.maker}: ${g_headerObj.tuningInit}`, _ => true, {
3670
- x: 0, y: g_sHeight - 50, w: g_sWidth / 2, h: C_LNK_HEIGHT,
3671
- siz: getLinkSiz(`${g_lblNameObj.maker}: ${g_headerObj.tuningInit}`), align: C_ALIGN_LEFT,
3672
- title: g_headerObj.creatorUrl,
3673
- resetFunc: _ => openLink(g_headerObj.creatorUrl),
3674
- }, g_cssObj.button_Default),
3726
+ createCreditBtn(`lnkMaker`, `${g_lblNameObj.maker}: ${g_headerObj.tuningInit}`, g_headerObj.creatorUrl),
3675
3727
 
3676
3728
  // アーティスト表示
3677
- createCss2Button(`lnkArtist`, `${g_lblNameObj.artist}: ${g_headerObj.artistName}`, _ => true, {
3678
- x: g_sWidth / 2, y: g_sHeight - 50, w: g_sWidth / 2, h: C_LNK_HEIGHT,
3679
- siz: getLinkSiz(`${g_lblNameObj.artist}: ${g_headerObj.artistName}`), align: C_ALIGN_LEFT,
3680
- title: g_headerObj.artistUrl,
3681
- resetFunc: _ => openLink(g_headerObj.artistUrl),
3682
- }, g_cssObj.button_Default),
3729
+ createCreditBtn(`lnkArtist`, `${g_lblNameObj.artist}: ${g_headerObj.artistName}`, g_headerObj.artistUrl),
3683
3730
 
3684
3731
  // バージョン描画
3685
- createCss2Button(
3686
- `lnkVersion`, versionName, _ => true, {
3687
- x: g_sWidth / 4, y: g_sHeight - 20, w: g_sWidth * 3 / 4 - 20, h: 16,
3688
- siz: getFontSize(versionName, g_sWidth * 3 / 4 - 20, getBasicFont(), 12),
3689
- align: C_ALIGN_RIGHT, title: g_msgObj.github,
3690
- resetFunc: _ => openLink(`https://github.com/cwtickle/danoniplus`),
3691
- }, g_cssObj.button_Tweet),
3732
+ createCss2Button(`lnkVersion`, versionName, _ => true,
3733
+ Object.assign(g_lblPosObj.lnkVersion, {
3734
+ siz: getFontSize(versionName, g_sWidth * 3 / 4 - 20, getBasicFont(), 12),
3735
+ resetFunc: _ => openLink(`https://github.com/cwtickle/danoniplus`),
3736
+ }), g_cssObj.button_Tweet),
3692
3737
 
3693
3738
  // セキュリティリンク
3694
- createCss2Button(`lnkComparison`, `&#x1f6e1;`, _ => true, {
3695
- x: g_sWidth - 20, y: g_sHeight - 20, w: 20, h: 16, siz: 12,
3696
- title: g_msgObj.security,
3697
- resetFunc: _ => openLink(`https://github.com/cwtickle/danoniplus/security/policy`),
3698
- }, g_cssObj.button_Tweet),
3739
+ createCss2Button(`lnkComparison`, `&#x1f6e1;`, _ => true,
3740
+ Object.assign(g_lblPosObj.lnkComparison, {
3741
+ resetFunc: _ => openLink(`https://github.com/cwtickle/danoniplus/security/policy`),
3742
+ }), g_cssObj.button_Tweet),
3699
3743
  );
3700
3744
 
3701
3745
  // コメントエリア作成
@@ -3715,19 +3759,11 @@ const titleInit = _ => {
3715
3759
  }
3716
3760
  } else {
3717
3761
  multiAppend(divRoot,
3718
-
3719
- createDivCss2Label(`lblComment`, convCommentVal, {
3720
- x: 0, y: 70, w: g_sWidth, h: g_sHeight - 180, siz: C_SIZ_DIFSELECTOR, align: C_ALIGN_LEFT,
3721
- overflow: `auto`, background: `#222222`, color: `#cccccc`, display: C_DIS_NONE,
3722
- }),
3723
-
3762
+ createDivCss2Label(`lblComment`, convCommentVal, g_lblPosObj.lblComment),
3724
3763
  createCss2Button(`btnComment`, g_lblNameObj.comment, _ => {
3725
3764
  const lblCommentDef = lblComment.style.display;
3726
3765
  lblComment.style.display = (lblCommentDef === C_DIS_NONE ? C_DIS_INHERIT : C_DIS_NONE);
3727
- }, {
3728
- x: g_sWidth - 160, y: (g_sHeight / 2) + 150, w: 140, h: 50, siz: 20, border: `solid 1px #999999`,
3729
- }, g_cssObj.button_Default),
3730
-
3766
+ }, g_lblPosObj.btnComment, g_cssObj.button_Default),
3731
3767
  );
3732
3768
  setUserSelect(lblComment.style, `text`);
3733
3769
  }
@@ -3865,31 +3901,31 @@ const commonSettingBtn = _labelName => {
3865
3901
  multiAppend(divRoot,
3866
3902
 
3867
3903
  // タイトル画面へ戻る
3868
- createCss2Button(`btnBack`, g_lblNameObj.b_back, _ => true, {
3869
- animationName: (g_initialFlg ? `` : `smallToNormalY`), resetFunc: _ => titleInit(),
3870
- }, g_cssObj.button_Back),
3904
+ createCss2Button(`btnBack`, g_lblNameObj.b_back, _ => true,
3905
+ Object.assign(g_lblPosObj.btnBack, {
3906
+ animationName: (g_initialFlg ? `` : `smallToNormalY`), resetFunc: _ => titleInit(),
3907
+ }), g_cssObj.button_Back),
3871
3908
 
3872
3909
  // キーコンフィグ画面へ移動
3873
- createCss2Button(`btnKeyConfig`, g_lblNameObj.b_keyConfig, _ => true, {
3874
- x: g_sWidth / 3,
3875
- animationName: (g_initialFlg ? `` : `smallToNormalY`), resetFunc: _ => keyConfigInit(`Main`),
3876
- }, g_cssObj.button_Setting),
3910
+ createCss2Button(`btnKeyConfig`, g_lblNameObj.b_keyConfig, _ => true,
3911
+ Object.assign(g_lblPosObj.btnKeyConfig, {
3912
+ animationName: (g_initialFlg ? `` : `smallToNormalY`), resetFunc: _ => keyConfigInit(`Main`),
3913
+ }), g_cssObj.button_Setting),
3877
3914
 
3878
3915
  // プレイ開始
3879
3916
  makePlayButton(_ => loadMusic()),
3880
3917
 
3881
3918
  // Display設定へ移動
3882
- createCss2Button(`btn${_labelName}`, `>`, _ => true, {
3883
- x: g_sWidth / 2 + 175 - C_LEN_SETMINI_WIDTH / 2, y: 25,
3884
- w: C_LEN_SETMINI_WIDTH, h: 40, title: g_msgObj[`to${_labelName}`],
3885
- resetFunc: _ => g_jumpSettingWindow[g_currentPage](),
3886
- }, g_cssObj.button_Mini),
3919
+ createCss2Button(`btn${_labelName}`, `>`, _ => true,
3920
+ Object.assign(g_lblPosObj.btnSwitchSetting, {
3921
+ title: g_msgObj[`to${_labelName}`], resetFunc: _ => g_jumpSettingWindow[g_currentPage](),
3922
+ }), g_cssObj.button_Mini),
3887
3923
 
3888
3924
  // データセーブフラグの切替
3889
- createCss2Button(`btnSave`, g_lblNameObj.dataSave, evt => switchSave(evt), {
3890
- x: 0, y: 5, w: g_sWidth / 5, h: 16, siz: 12,
3891
- title: g_msgObj.dataSave, borderStyle: `solid`, cxtFunc: evt => switchSave(evt),
3892
- }, g_cssObj.button_Default, (g_stateObj.dataSaveFlg ? g_cssObj.button_ON : g_cssObj.button_OFF)),
3925
+ createCss2Button(`btnSave`, g_lblNameObj.dataSave, evt => switchSave(evt),
3926
+ Object.assign(g_lblPosObj.btnSave, {
3927
+ cxtFunc: evt => switchSave(evt),
3928
+ }), g_cssObj.button_Default, (g_stateObj.dataSaveFlg ? g_cssObj.button_ON : g_cssObj.button_OFF)),
3893
3929
  );
3894
3930
  };
3895
3931
 
@@ -3897,13 +3933,11 @@ const commonSettingBtn = _labelName => {
3897
3933
  * PLAYボタンの作成
3898
3934
  * @param {function} _func
3899
3935
  */
3900
- const makePlayButton = _func => {
3901
- return createCss2Button(`btnPlay`, g_lblNameObj.b_play, _ => true, {
3902
- x: g_sWidth * 2 / 3,
3936
+ const makePlayButton = _func => createCss2Button(`btnPlay`, g_lblNameObj.b_play, _ => true,
3937
+ Object.assign(g_lblPosObj.btnPlay, {
3903
3938
  animationName: (g_initialFlg ? `` : `smallToNormalY`),
3904
3939
  resetFunc: _func,
3905
- }, g_cssObj.button_Next);
3906
- };
3940
+ }), g_cssObj.button_Next);
3907
3941
 
3908
3942
  /**
3909
3943
  * 設定・オプション画面初期化
@@ -3943,12 +3977,11 @@ const optionInit = _ => {
3943
3977
  const setSpriteList = _settingList => {
3944
3978
  const optionWidth = (g_sWidth - 450) / 2;
3945
3979
  const spriteList = [];
3946
- _settingList.forEach(setting => {
3980
+ _settingList.forEach(setting =>
3947
3981
  spriteList[setting[0]] = createEmptySprite(optionsprite, `${setting[0]}Sprite`, {
3948
3982
  x: 25, y: setting[1] * C_LEN_SETLBL_HEIGHT + setting[2] + 20,
3949
3983
  w: optionWidth + setting[3], h: C_LEN_SETLBL_HEIGHT + setting[4],
3950
- });
3951
- });
3984
+ }));
3952
3985
  return spriteList;
3953
3986
  };
3954
3987
 
@@ -4210,19 +4243,18 @@ const createOptionWindow = _sprite => {
4210
4243
  setSetting(_val, `scoreDetail`);
4211
4244
  viewScText();
4212
4245
  $id(`detail${g_stateObj.scoreDetail}`).visibility = `visible`;
4213
- }
4246
+ };
4214
4247
 
4215
4248
  multiAppend(scoreDetail,
4216
4249
  createScoreDetail(`Speed`),
4217
4250
  createScoreDetail(`Density`),
4218
4251
  createScoreDetail(`ToolDif`, false),
4219
- makeSettingLblCssButton(`lnkScoreDetailB`, `- - -`, 0, _ => changeScoreDetail(-1), {
4220
- x: 10, w: 100, visibility: `hidden`,
4221
- }, g_cssObj.button_RevON),
4222
- makeSettingLblCssButton(`lnkScoreDetail`, `${getStgDetailName(g_stateObj.scoreDetail)}`, 0, _ => changeScoreDetail(), {
4223
- x: 10, w: 100, borderStyle: `solid`,
4224
- cxtFunc: _ => changeScoreDetail(-1),
4225
- }, g_cssObj.button_RevON),
4252
+ makeSettingLblCssButton(`lnkScoreDetailB`, `- - -`, 0, _ => changeScoreDetail(-1),
4253
+ g_lblPosObj.lnkScoreDetailB, g_cssObj.button_RevON),
4254
+ makeSettingLblCssButton(`lnkScoreDetail`, `${getStgDetailName(g_stateObj.scoreDetail)}`, 0, _ => changeScoreDetail(),
4255
+ Object.assign(g_lblPosObj.lnkScoreDetail, {
4256
+ cxtFunc: _ => changeScoreDetail(-1),
4257
+ }), g_cssObj.button_RevON),
4226
4258
  );
4227
4259
  viewScText();
4228
4260
  }
@@ -4440,9 +4472,8 @@ const createOptionWindow = _sprite => {
4440
4472
  * @param {string} _data
4441
4473
  * @param {object} _obj
4442
4474
  */
4443
- const makeDifInfoLabel = (_lbl, _data, { x = 130, y = 25, w = 125, h = 35, siz = C_SIZ_DIFSELECTOR, ...rest } = {}) => {
4444
- return createDivCss2Label(_lbl, _data, { x, y, w, h, siz, align: C_ALIGN_LEFT, ...rest });
4445
- }
4475
+ const makeDifInfoLabel = (_lbl, _data, { x = 130, y = 25, w = 125, h = 35, siz = C_SIZ_DIFSELECTOR, ...rest } = {}) =>
4476
+ createDivCss2Label(_lbl, _data, { x, y, w, h, siz, align: C_ALIGN_LEFT, ...rest });
4446
4477
 
4447
4478
  let printData = ``;
4448
4479
  for (let j = 0; j < g_detailObj.arrowCnt.length; j++) {
@@ -4468,24 +4499,22 @@ const createOptionWindow = _sprite => {
4468
4499
  `${obj.playingTime}\r\n`;
4469
4500
  }
4470
4501
  multiAppend(detailToolDif,
4471
- makeDifInfoLabel(`lblTooldif`, g_lblNameObj.s_level, { y: 5, w: 250, siz: C_SIZ_JDGCNTS }),
4472
- makeDifInfoLabel(`dataTooldif`, ``, { x: 270, y: 3, w: 160, siz: 18 }),
4473
- makeDifInfoLabel(`lblDouji`, g_lblNameObj.s_douji),
4474
- makeDifInfoLabel(`lblTate`, g_lblNameObj.s_tate, { x: 270 }),
4475
- makeDifInfoLabel(`dataDouji`, ``, { x: 200, w: 160 }),
4476
- makeDifInfoLabel(`dataTate`, ``, { x: 345, w: 160 }),
4477
- makeDifInfoLabel(`lblArrowInfo`, g_lblNameObj.s_cnts, { x: 130, y: 45, w: 290, siz: C_SIZ_JDGCNTS }),
4478
- makeDifInfoLabel(`dataArrowInfo`, ``, { x: 270, y: 45, w: 160, siz: C_SIZ_JDGCNTS }),
4479
- makeDifInfoLabel(`lblArrowInfo2`, ``, { x: 130, y: 70, w: 200, h: 90 }),
4480
- makeDifInfoLabel(`dataArrowInfo2`, ``, { x: 140, y: 70, w: 275, h: 150, overflow: `auto` }),
4502
+ makeDifInfoLabel(`lblTooldif`, g_lblNameObj.s_level, g_lblPosObj.lblTooldif),
4503
+ makeDifInfoLabel(`dataTooldif`, ``, g_lblPosObj.dataTooldif),
4504
+ makeDifInfoLabel(`lblDouji`, g_lblNameObj.s_douji, g_lblPosObj.lblDouji),
4505
+ makeDifInfoLabel(`lblTate`, g_lblNameObj.s_tate, g_lblPosObj.lblTate),
4506
+ makeDifInfoLabel(`dataDouji`, ``, g_lblPosObj.dataDouji),
4507
+ makeDifInfoLabel(`dataTate`, ``, g_lblPosObj.dataTate),
4508
+ makeDifInfoLabel(`lblArrowInfo`, g_lblNameObj.s_cnts, g_lblPosObj.lblArrowInfo),
4509
+ makeDifInfoLabel(`dataArrowInfo`, ``, g_lblPosObj.dataArrowInfo),
4510
+ makeDifInfoLabel(`lblArrowInfo2`, ``, g_lblPosObj.lblArrowInfo2),
4511
+ makeDifInfoLabel(`dataArrowInfo2`, ``, g_lblPosObj.dataArrowInfo2),
4481
4512
  makeSettingLblCssButton(`lnkDifInfo`, g_lblNameObj.s_print, 0, _ => {
4482
4513
  copyTextToClipboard(
4483
4514
  `****** ${g_lblNameObj.s_printTitle} [${g_version}] ******\r\n\r\n`
4484
4515
  + `\t${g_lblNameObj.s_printHeader}\r\n\r\n${printData}`, g_msgInfoObj.I_0003
4485
4516
  );
4486
- }, {
4487
- x: 10, y: 30, w: 100, borderStyle: `solid`
4488
- }, g_cssObj.button_RevON),
4517
+ }, g_lblPosObj.lnkDifInfo, g_cssObj.button_RevON),
4489
4518
  );
4490
4519
  createScText(lnkDifInfo, `DifInfo`, { targetLabel: `lnkDifInfo`, x: -10 });
4491
4520
  };
@@ -4535,12 +4564,10 @@ const createOptionWindow = _sprite => {
4535
4564
  ];
4536
4565
 
4537
4566
  spriteList.scroll.appendChild(
4538
- createCss2Button(`btnReverse`, `${g_lblNameObj.Reverse}:${getStgDetailName(g_stateObj.reverse)}`, evt => setReverse(evt.target), {
4539
- x: 160, y: 0,
4540
- w: 90, h: 21, siz: C_SIZ_DIFSELECTOR,
4541
- borderStyle: `solid`,
4542
- cxtFunc: evt => setReverse(evt.target),
4543
- }, g_cssObj.button_Default, g_cssObj[`button_Rev${g_stateObj.reverse}`])
4567
+ createCss2Button(`btnReverse`, `${g_lblNameObj.Reverse}:${getStgDetailName(g_stateObj.reverse)}`, evt => setReverse(evt.target),
4568
+ Object.assign(g_lblPosObj.btnReverse, {
4569
+ cxtFunc: evt => setReverse(evt.target),
4570
+ }), g_cssObj.button_Default, g_cssObj[`button_Rev${g_stateObj.reverse}`])
4544
4571
  );
4545
4572
  spriteList[g_settings.scrolls.length > 1 ? `reverse` : `scroll`].style.display = C_DIS_NONE;
4546
4573
  } else {
@@ -4575,12 +4602,7 @@ const createOptionWindow = _sprite => {
4575
4602
  spriteList.gauge.appendChild(createLblSetting(`Gauge`));
4576
4603
 
4577
4604
  // ゲージ設定詳細 縦位置: ゲージ設定+1
4578
- spriteList.gauge.appendChild(
4579
- createDivCss2Label(`lblGauge2`, ``, {
4580
- x: C_LEN_SETLBL_LEFT - 35, y: C_LEN_SETLBL_HEIGHT,
4581
- w: C_LEN_SETLBL_WIDTH + 60, h: C_LEN_SETLBL_HEIGHT * 2, siz: 11,
4582
- })
4583
- );
4605
+ spriteList.gauge.appendChild(createDivCss2Label(`lblGauge2`, ``, g_lblPosObj.lblGauge2));
4584
4606
 
4585
4607
  /**
4586
4608
  * ゲージ設定メイン
@@ -4766,9 +4788,8 @@ const createOptionWindow = _sprite => {
4766
4788
  // 縦位置: 11 スライダーあり
4767
4789
  spriteList.fadein.appendChild(createLblSetting(`Fadein`));
4768
4790
 
4769
- const lnkFadein = createDivCss2Label(`lnkFadein`, `${g_stateObj.fadein}${g_lblNameObj.percent}`, {
4770
- x: C_LEN_SETLBL_LEFT, y: 0,
4771
- }, g_cssObj.settings_FadeinBar);
4791
+ const lnkFadein = createDivCss2Label(`lnkFadein`, `${g_stateObj.fadein}${g_lblNameObj.percent}`,
4792
+ g_lblPosObj.lnkFadein, g_cssObj.settings_FadeinBar);
4772
4793
  spriteList.fadein.appendChild(lnkFadein);
4773
4794
 
4774
4795
  const setFadein = _sign => {
@@ -4784,9 +4805,8 @@ const createOptionWindow = _sprite => {
4784
4805
  makeMiniCssButton(`lnkFadein`, `L`, 0, _ => setFadein(-1)),
4785
4806
 
4786
4807
  // フェードインのスライダー処理
4787
- createDivCss2Label(`lblFadeinBar`, `<input id="fadeinSlider" type="range" value="${g_stateObj.fadein}" min="0" max="99" step="1">`, {
4788
- x: C_LEN_SETLBL_LEFT, y: 0,
4789
- }),
4808
+ createDivCss2Label(`lblFadeinBar`, `<input id="fadeinSlider" type="range" value="${g_stateObj.fadein}" min="0" max="99" step="1">`,
4809
+ g_lblPosObj.lblFadeinBar),
4790
4810
 
4791
4811
  )
4792
4812
 
@@ -5245,12 +5265,7 @@ const settingsDisplayInit = _ => {
5245
5265
  createSettingsDisplayWindow(divRoot);
5246
5266
 
5247
5267
  // ショートカットキーメッセージ
5248
- divRoot.appendChild(
5249
- createDivCss2Label(`scMsg`, g_lblNameObj.sdShortcutDesc, {
5250
- x: 0, y: g_sHeight - 45, w: g_sWidth, h: 20,
5251
- siz: getFontSize(g_lblNameObj.sdShortcutDesc, g_sWidth, getBasicFont(), C_SIZ_MAIN),
5252
- })
5253
- );
5268
+ divRoot.appendChild(createDescDiv(`scMsg`, g_lblNameObj.sdShortcutDesc));
5254
5269
 
5255
5270
  // ユーザカスタムイベント(初期)
5256
5271
  g_customJsObj.settingsDisplay.forEach(func => func());
@@ -5336,11 +5351,7 @@ const createSettingsDisplayWindow = _sprite => {
5336
5351
  const displaySprite = createEmptySprite(optionsprite, `displaySprite`, g_windowObj.displaySprite);
5337
5352
  const spriteList = setSpriteList(settingList);
5338
5353
 
5339
- _sprite.appendChild(
5340
- createDivCss2Label(`sdDesc`, g_lblNameObj.sdDesc, {
5341
- x: 0, y: 65, w: g_sWidth, h: 20, siz: C_SIZ_MAIN,
5342
- })
5343
- );
5354
+ _sprite.appendChild(createDivCss2Label(`sdDesc`, g_lblNameObj.sdDesc, g_lblPosObj.sdDesc));
5344
5355
  g_displays.forEach((name, j) => makeDisplayButton(name, j % 7, Math.floor(j / 7)));
5345
5356
 
5346
5357
  // ---------------------------------------------------
@@ -5354,16 +5365,13 @@ const createSettingsDisplayWindow = _sprite => {
5354
5365
 
5355
5366
  // Hidden+/Sudden+初期値用スライダー、ロックボタン
5356
5367
  multiAppend(spriteList.appearance,
5357
- createDivCss2Label(`lblAppearancePos`, `${g_hidSudObj.filterPos}${g_lblNameObj.percent}`, {
5358
- x: C_LEN_SETLBL_LEFT, y: 20, siz: 12, align: C_ALIGN_CENTER,
5359
- }),
5360
- createDivCss2Label(`lblAppearanceBar`, `<input id="appearanceSlider" type="range" value="${g_hidSudObj.filterPos}" min="0" max="100" step="1">`, {
5361
- x: C_LEN_SETLBL_LEFT, y: 15,
5362
- }),
5363
- createCss2Button(`lnkLockBtn`, g_lblNameObj.filterLock, evt => setLockView(evt.target), {
5364
- x: C_LEN_SETLBL_LEFT + C_LEN_SETLBL_WIDTH - 40, y: 0, w: 40, h: C_LEN_SETLBL_HEIGHT, siz: 12,
5365
- borderStyle: `solid`, cxtFunc: evt => setLockView(evt.target),
5366
- }, g_cssObj.button_Default, g_cssObj[`button_Rev${g_stateObj.filterLock}`]),
5368
+ createDivCss2Label(`lblAppearancePos`, `${g_hidSudObj.filterPos}${g_lblNameObj.percent}`, g_lblPosObj.lblAppearancePos),
5369
+ createDivCss2Label(`lblAppearanceBar`, `<input id="appearanceSlider" type="range" value="${g_hidSudObj.filterPos}" min="0" max="100" step="1">`,
5370
+ g_lblPosObj.lblAppearanceBar),
5371
+ createCss2Button(`lnkLockBtn`, g_lblNameObj.filterLock, evt => setLockView(evt.target),
5372
+ Object.assign(g_lblPosObj.lnkLockBtn, {
5373
+ cxtFunc: evt => setLockView(evt.target),
5374
+ }), g_cssObj.button_Default, g_cssObj[`button_Rev${g_stateObj.filterLock}`]),
5367
5375
  );
5368
5376
 
5369
5377
  const setLockView = (_btn) => {
@@ -5459,17 +5467,10 @@ const keyConfigInit = (_kcType = g_kcType) => {
5459
5467
  `<div class="settings_Title">${g_lblNameObj.key}</div><div class="settings_Title2">${g_lblNameObj.config}</div>`
5460
5468
  .replace(/[\t\n]/g, ``), 0, 15, g_cssObj.flex_centering),
5461
5469
 
5462
- createDivCss2Label(`kcDesc`, g_lblNameObj.kcDesc.split(`{0}`).join(g_kCd[C_KEY_RETRY])
5463
- .split(`{1}:`).join(g_isMac ? `` : `Delete:`), {
5464
- x: 0, y: 68, w: g_sWidth, h: 20,
5465
- siz: getFontSize(g_lblNameObj.kcDesc, g_sWidth, getBasicFont(), C_SIZ_MAIN),
5466
- }),
5467
-
5468
- createDivCss2Label(`kcShuffleDesc`, g_lblNameObj.kcShuffleDesc, {
5469
- x: 5, y: g_sHeight - 125, w: g_sWidth, h: 20, align: C_ALIGN_LEFT,
5470
- siz: getFontSize(g_lblNameObj.kcShuffleDesc, g_sWidth, getBasicFont(), C_SIZ_MAIN),
5471
- }),
5470
+ createDescDiv(`kcDesc`, g_lblNameObj.kcDesc.split(`{0}`).join(g_kCd[C_KEY_RETRY])
5471
+ .split(`{1}:`).join(g_isMac ? `` : `Delete:`)),
5472
5472
 
5473
+ createDescDiv(`kcShuffleDesc`, g_lblNameObj.kcShuffleDesc),
5473
5474
  );
5474
5475
 
5475
5476
  // キーの一覧を表示
@@ -5760,26 +5761,17 @@ const keyConfigInit = (_kcType = g_kcType) => {
5760
5761
  viewGroup(_type);
5761
5762
  };
5762
5763
 
5763
- const scMsg = g_lblNameObj.kcShortcutDesc.split(`{0}`).join(g_isMac ? `Shift+${g_kCd[g_headerObj.keyRetry]}` : g_kCd[g_headerObj.keyTitleBack])
5764
- .split(`{1}`).join(g_kCd[g_headerObj.keyRetry]);
5765
-
5766
5764
  multiAppend(divRoot,
5767
5765
 
5768
5766
  // ショートカットキーメッセージ
5769
- createDivCss2Label(
5770
- `scMsg`, scMsg,
5771
- {
5772
- x: 0, y: g_sHeight - 45, w: g_sWidth, h: 20,
5773
- siz: getFontSize(scMsg, g_sWidth, getBasicFont(), C_SIZ_MAIN),
5774
- }),
5767
+ createDescDiv(`scMsg`, g_lblNameObj.kcShortcutDesc.split(`{0}`).join(g_isMac ? `Shift+${g_kCd[g_headerObj.keyRetry]}` : g_kCd[g_headerObj.keyTitleBack])
5768
+ .split(`{1}`).join(g_kCd[g_headerObj.keyRetry]), `scKcMsg`),
5775
5769
 
5776
5770
  // 別キーモード警告メッセージ
5777
5771
  createDivCss2Label(
5778
5772
  `kcMsg`,
5779
5773
  hasVal(g_keyObj[`transKey${keyCtrlPtn}`]) ? g_lblNameObj.transKeyDesc : ``,
5780
- {
5781
- x: 0, y: g_sHeight - 25, w: g_sWidth, h: 20, siz: C_SIZ_MAIN,
5782
- }, g_cssObj.keyconfig_warning
5774
+ g_lblPosObj.kcMsg, g_cssObj.keyconfig_warning
5783
5775
  ),
5784
5776
 
5785
5777
  // キーコンフィグタイプ切替ボタン
@@ -5886,11 +5878,26 @@ const keyConfigInit = (_kcType = g_kcType) => {
5886
5878
  lnkKcType.textContent = getStgDetailName(g_kcType);
5887
5879
  };
5888
5880
 
5881
+ /**
5882
+ * ColorPickerの色切替
5883
+ * @param {number} _j
5884
+ * @param {string} _type
5885
+ * @param {string} _color
5886
+ */
5887
+ const changeColorPicker = (_j, _type, _color) => {
5888
+ if (_color !== ``) {
5889
+ document.getElementById(`pick${_type}${_j}`).value = _color.slice(0, 7);
5890
+ document.getElementById(`pick${_type}${_j}`).style.display = C_DIS_INHERIT;
5891
+ } else {
5892
+ document.getElementById(`pick${_type}${_j}`).style.display = C_DIS_NONE;
5893
+ }
5894
+ };
5895
+
5889
5896
  /**
5890
5897
  * ColorTypeの制御
5891
5898
  * @param {number} _scrollNum
5892
5899
  */
5893
- const setColorType = (_scrollNum = 1) => {
5900
+ const setColorType = (_scrollNum = 1, _reloadFlg = true) => {
5894
5901
  const nextNum = getNextNum(_scrollNum, `colorTypes`, g_colorType);
5895
5902
  g_colorType = g_keycons.colorTypes[nextNum];
5896
5903
  if (g_headerObj.colorUse) {
@@ -5899,6 +5906,15 @@ const keyConfigInit = (_kcType = g_kcType) => {
5899
5906
  changeSetColor();
5900
5907
  viewGroupObj.color(`_${g_keycons.colorGroupNum}`);
5901
5908
  lnkColorType.textContent = `${getStgDetailName(g_colorType)}${g_localStorage.colorType === g_colorType ? ' *' : ''}`;
5909
+ if (_reloadFlg) {
5910
+ colorPickSprite.style.display = ([`Default`, `Type0`].includes(g_colorType) ? C_DIS_NONE : C_DIS_INHERIT);
5911
+ for (let j = 0; j < g_headerObj.setColor.length; j++) {
5912
+ changeColorPicker(j, `arrow`, g_headerObj.setColor[j]);
5913
+ changeColorPicker(j, `arrowShadow`, g_headerObj.setShadowColor[j]);
5914
+ changeColorPicker(j, `frz`, g_headerObj.frzColor[j][0]);
5915
+ changeColorPicker(j, `frzBar`, g_headerObj.frzColor[j][1]);
5916
+ }
5917
+ }
5902
5918
  };
5903
5919
 
5904
5920
  const setImgType = (_scrollNum = 1) => {
@@ -5911,6 +5927,50 @@ const keyConfigInit = (_kcType = g_kcType) => {
5911
5927
  keyConfigInit(g_kcType);
5912
5928
  };
5913
5929
 
5930
+ const colorPickSprite = createEmptySprite(divRoot, `colorPickSprite`, g_windowObj.colorPickSprite);
5931
+ if ([`Default`, `Type0`].includes(g_colorType)) {
5932
+ colorPickSprite.style.display = C_DIS_NONE;
5933
+ }
5934
+ multiAppend(colorPickSprite,
5935
+ createDivCss2Label(`lblPickArrow`, g_lblNameObj.s_arrow, Object.assign({ y: 0 }, g_lblPosObj.pickPos)),
5936
+ createDivCss2Label(`lblPickFrz`, g_lblNameObj.s_frz, Object.assign({ y: 140 }, g_lblPosObj.pickPos)),
5937
+ createCss2Button(`lnkColorCopy`, `[↓]`, _ => {
5938
+ if (window.confirm(g_msgObj.colorCopyConfirm)) {
5939
+ for (let j = 0; j < g_headerObj.setColor.length; j++) {
5940
+ g_headerObj[`frzColor${g_colorType}`][j] = [...Array(g_headerObj[`frzColor${g_colorType}`][j].length)].fill(g_headerObj[`setColor${g_colorType}`][j]);
5941
+ [``, `Bar`].forEach((val, k) =>
5942
+ document.getElementById(`pickfrz${val}${j}`).value = g_headerObj[`frzColor${g_colorType}`][j][k]);
5943
+ }
5944
+ }
5945
+ }, g_lblPosObj.lnkColorCopy, g_cssObj.button_Start),
5946
+ );
5947
+
5948
+ /**
5949
+ * ColorPicker部分の作成
5950
+ * @param {number} _j
5951
+ * @param {string} _type
5952
+ * @param {function} _func
5953
+ * @param {object} _obj
5954
+ */
5955
+ const createColorPickWindow = (_j, _type, _func, { x = 0, y = 15 } = {}) =>
5956
+ createColorPicker(colorPickSprite, `pick${_type}${_j}`, _func, { x, y: y + 25 * _j });
5957
+
5958
+ for (let j = 0; j < g_headerObj.setColor.length; j++) {
5959
+ createColorPickWindow(j, `arrow`, _ => {
5960
+ g_headerObj[`setColor${g_colorType}`][j] = document.getElementById(`pickarrow${j}`).value;
5961
+ setColorType(0, false);
5962
+ });
5963
+
5964
+ createColorPickWindow(j, `arrowShadow`, _ => {
5965
+ g_headerObj[`setShadowColor${g_colorType}`][j] = `${document.getElementById(`pickarrowShadow${j}`).value}80`;
5966
+ setColorType(0, false);
5967
+ }, { x: 25 });
5968
+
5969
+ [``, `Bar`].forEach((val, k) =>
5970
+ createColorPickWindow(j, `frz${val}`, _ =>
5971
+ g_headerObj[`frzColor${g_colorType}`][j][k] = document.getElementById(`pickfrz${val}${j}`).value, { x: 25 * k, y: 155 }));
5972
+ }
5973
+
5914
5974
  // ConfigType, ColorTypeの初期設定
5915
5975
  setConfigType(0);
5916
5976
  setColorType(0);
@@ -5943,21 +6003,15 @@ const keyConfigInit = (_kcType = g_kcType) => {
5943
6003
  g_currentj = 0;
5944
6004
  g_currentk = 0;
5945
6005
  g_prevKey = 0;
5946
- }, {
5947
- x: g_sWidth / 3, y: g_sHeight - 75,
5948
- w: g_sWidth / 3, h: C_BTN_HEIGHT / 2, siz: C_LBL_BTNSIZE * 2 / 3,
6006
+ }, Object.assign(g_lblPosObj.btnKcBack, {
5949
6007
  resetFunc: _ => (g_baseDisp === `Settings` ? optionInit() : settingsDisplayInit()),
5950
- }, g_cssObj.button_Back),
6008
+ }), g_cssObj.button_Back),
5951
6009
 
5952
- createDivCss2Label(`lblPattern`, `${g_lblNameObj.KeyPattern}: ${g_keyObj.currentPtn === -1 ? 'Self' : g_keyObj.currentPtn + 1}${lblTransKey}`, {
5953
- x: g_sWidth / 6, y: g_sHeight - 100,
5954
- w: g_sWidth / 3, h: C_BTN_HEIGHT / 2,
5955
- }),
6010
+ createDivCss2Label(`lblPattern`, `${g_lblNameObj.KeyPattern}: ${g_keyObj.currentPtn === -1 ?
6011
+ 'Self' : g_keyObj.currentPtn + 1}${lblTransKey}`, g_lblPosObj.lblPattern),
5956
6012
 
5957
6013
  // パターン変更ボタン描画(右回り)
5958
- createCss2Button(`btnPtnChangeR`, `>>`, _ => true, {
5959
- x: g_sWidth / 2, y: g_sHeight - 100,
5960
- w: g_sWidth / 6, h: C_BTN_HEIGHT / 2, siz: C_LBL_BTNSIZE * 2 / 3,
6014
+ createCss2Button(`btnPtnChangeR`, `>>`, _ => true, Object.assign(g_lblPosObj.btnPtnChangeR, {
5961
6015
  resetFunc: _ => {
5962
6016
  const tempPtn = searchPattern(g_keyObj.currentPtn + 1, 1, g_headerObj.transKeyUse, `transKey`);
5963
6017
  g_keyObj.currentPtn = (g_keyObj[`keyCtrl${g_keyObj.currentKey}_${tempPtn}`] !== undefined ?
@@ -5965,12 +6019,10 @@ const keyConfigInit = (_kcType = g_kcType) => {
5965
6019
 
5966
6020
  keyConfigInit();
5967
6021
  },
5968
- }, g_cssObj.button_Setting),
6022
+ }), g_cssObj.button_Setting),
5969
6023
 
5970
6024
  // パターン変更ボタン描画(左回り)
5971
- createCss2Button(`btnPtnChangeL`, `<<`, _ => true, {
5972
- x: 0, y: g_sHeight - 100,
5973
- w: g_sWidth / 6, h: C_BTN_HEIGHT / 2, siz: C_LBL_BTNSIZE * 2 / 3,
6025
+ createCss2Button(`btnPtnChangeL`, `<<`, _ => true, Object.assign(g_lblPosObj.btnPtnChangeL, {
5974
6026
  resetFunc: _ => {
5975
6027
  const tempPtn = searchPattern(g_keyObj.currentPtn - 1, -1, g_headerObj.transKeyUse, `transKey`);
5976
6028
  g_keyObj.currentPtn = (g_keyObj[`keyCtrl${g_keyObj.currentKey}_${tempPtn}`] !== undefined ?
@@ -5978,7 +6030,7 @@ const keyConfigInit = (_kcType = g_kcType) => {
5978
6030
 
5979
6031
  keyConfigInit();
5980
6032
  },
5981
- }, g_cssObj.button_Setting),
6033
+ }), g_cssObj.button_Setting),
5982
6034
 
5983
6035
  // キーコンフィグリセットボタン描画
5984
6036
  createCss2Button(`btnReset`, g_lblNameObj.b_reset, _ => {
@@ -5993,10 +6045,7 @@ const keyConfigInit = (_kcType = g_kcType) => {
5993
6045
  resetCursor(Number(g_kcType === `Replaced`));
5994
6046
  keyconSprite.scrollLeft = - maxLeftX;
5995
6047
  }
5996
- }, {
5997
- x: 0, y: g_sHeight - 75,
5998
- w: g_sWidth / 3, h: C_BTN_HEIGHT / 2, siz: C_LBL_BTNSIZE * 2 / 3,
5999
- }, g_cssObj.button_Reset),
6048
+ }, g_lblPosObj.btnKcReset, g_cssObj.button_Reset),
6000
6049
 
6001
6050
  // プレイ開始
6002
6051
  makePlayButton(_ => loadMusic())
@@ -6737,7 +6786,7 @@ const scoreConvert = (_dosObj, _scoreId, _preblankFrame, _dummyNo = ``,
6737
6786
  const frame = calcFrame(tmpcssMotionData[0]);
6738
6787
  const arrowNum = parseFloat(tmpcssMotionData[1]);
6739
6788
  const styleUp = (tmpcssMotionData[2] === `none` ? `` : tmpcssMotionData[2]);
6740
- const styleDown = (tmpcssMotionData[3] === `none` ? `` : setVal(tmpcssMotionData[3], styleUp, C_TYP_STRING));
6789
+ const styleDown = (tmpcssMotionData[3] === `none` ? `` : setVal(tmpcssMotionData[3], styleUp));
6741
6790
 
6742
6791
  cssMotionData.push([frame, arrowNum, styleUp, styleDown]);
6743
6792
  });
@@ -7896,10 +7945,9 @@ const MainInit = _ => {
7896
7945
  }, g_cssObj.main_stepKeyDown),
7897
7946
 
7898
7947
  // ヒット時モーション
7899
- createColorObject2(`stepHit${j}`, {
7900
- x: -15, y: -15, w: C_ARW_WIDTH + 30, h: C_ARW_WIDTH + 30,
7948
+ createColorObject2(`stepHit${j}`, Object.assign(g_lblPosObj.stepHit, {
7901
7949
  rotate: g_workObj.stepHitRtn[j], styleName: `StepHit`, opacity: 0,
7902
- }, g_cssObj.main_stepDefault),
7950
+ }), g_cssObj.main_stepDefault),
7903
7951
 
7904
7952
  );
7905
7953
  }
@@ -7920,23 +7968,13 @@ const MainInit = _ => {
7920
7968
 
7921
7969
  // Hidden+, Sudden+用のライン、パーセント表示
7922
7970
  const filterCss = g_stateObj.filterLock === C_FLG_OFF ? g_cssObj.life_Failed : g_cssObj.life_Cleared;
7923
- [`filterBar0`, `filterBar1`, `borderBar0`, `borderBar1`].forEach(obj => {
7924
- mainSprite.appendChild(
7925
- createColorObject2(`${obj}`, {
7926
- w: g_headerObj.playingWidth - 50, h: 1, styleName: `lifeBar`,
7927
- opacity: 0.0625,
7928
- }, filterCss)
7929
- );
7930
- });
7971
+ [`filterBar0`, `filterBar1`, `borderBar0`, `borderBar1`].forEach(obj =>
7972
+ mainSprite.appendChild(createColorObject2(obj, g_lblPosObj.filterBar, filterCss)));
7931
7973
  borderBar0.style.top = `${g_posObj.stepDiffY}px`;
7932
7974
  borderBar1.style.top = `${g_posObj.stepDiffY + g_posObj.arrowHeight}px`;
7933
7975
 
7934
7976
  if (g_appearanceRanges.includes(g_stateObj.appearance)) {
7935
- mainSprite.appendChild(
7936
- createDivCss2Label(`filterView`, ``, {
7937
- x: g_headerObj.playingWidth - 70, y: 0, w: 10, h: 10, siz: 10, align: C_ALIGN_RIGHT,
7938
- })
7939
- );
7977
+ mainSprite.appendChild(createDivCss2Label(`filterView`, ``, g_lblPosObj.filterView));
7940
7978
  if (g_stateObj.d_filterline === C_FLG_ON) {
7941
7979
  [`filterBar0`, `filterBar1`, `filterView`].forEach(obj => {
7942
7980
  $id(obj).opacity = g_stateObj.opacity / 100;
@@ -7964,7 +8002,7 @@ const MainInit = _ => {
7964
8002
  if (isNaN(parseFloat(g_workObj.arrowRtn[j]))) {
7965
8003
  multiAppend(frzHit,
7966
8004
  createColorObject2(`frzHitShadow${j}`, {
7967
- rotate: g_workObj.arrowRtn[j], styleName: `Shadow`
8005
+ rotate: g_workObj.arrowRtn[j], styleName: `Shadow`,
7968
8006
  }, g_cssObj.main_objShadow),
7969
8007
  createColorObject2(`frzHitTop${j}`, {
7970
8008
  background: g_workObj.frzHitColors[j], rotate: g_workObj.arrowRtn[j],
@@ -7972,10 +8010,9 @@ const MainInit = _ => {
7972
8010
  );
7973
8011
  } else {
7974
8012
  frzHit.appendChild(
7975
- createColorObject2(`frzHitTop${j}`, {
7976
- x: -8, y: -8, w: C_ARW_WIDTH + 16, h: C_ARW_WIDTH + 16,
8013
+ createColorObject2(`frzHitTop${j}`, Object.assign(g_lblPosObj.frzHitTop, {
7977
8014
  rotate: g_workObj.arrowRtn[j], styleName: `Shadow`,
7978
- }, g_cssObj.main_frzHitTop)
8015
+ }), g_cssObj.main_frzHitTop)
7979
8016
  );
7980
8017
  }
7981
8018
  }
@@ -8102,24 +8139,16 @@ const MainInit = _ => {
8102
8139
  }, g_cssObj.life_Border, g_cssObj.life_BorderColor),
8103
8140
 
8104
8141
  // 曲名・アーティスト名表示
8105
- createDivCss2Label(`lblCredit`, creditName, {
8106
- x: 125, y: g_sHeight - 30, w: g_headerObj.playingWidth - 125, h: 20, siz: checkMusicSiz(creditName, C_SIZ_MUSIC_TITLE), align: C_ALIGN_LEFT,
8107
- }),
8142
+ createDivCss2Label(`lblCredit`, creditName, Object.assign(g_lblPosObj.lblCredit, { siz: checkMusicSiz(creditName, C_SIZ_MUSIC_TITLE) })),
8108
8143
 
8109
8144
  // 譜面名表示
8110
- createDivCss2Label(`lblDifName`, difName, {
8111
- x: 125, y: g_sHeight - 16, w: g_headerObj.playingWidth, h: 20, siz: checkMusicSiz(difName, 12), align: C_ALIGN_LEFT,
8112
- }),
8145
+ createDivCss2Label(`lblDifName`, difName, Object.assign(g_lblPosObj.lblDifName, { siz: checkMusicSiz(difName, 12) })),
8113
8146
 
8114
8147
  // 曲時間表示:現在時間
8115
- createDivCss2Label(`lblTime1`, `-:--`, {
8116
- x: 18, y: g_sHeight - 30, w: 40, h: 20, siz: C_SIZ_MAIN, align: C_ALIGN_RIGHT, display: g_workObj.musicinfoDisp,
8117
- }),
8148
+ createDivCss2Label(`lblTime1`, `-:--`, Object.assign(g_lblPosObj.lblTime1, { display: g_workObj.musicinfoDisp })),
8118
8149
 
8119
8150
  // 曲時間表示:総時間
8120
- createDivCss2Label(`lblTime2`, `/ ${fullTime}`, {
8121
- x: 60, y: g_sHeight - 30, w: 60, h: 20, siz: C_SIZ_MAIN, display: g_workObj.musicinfoDisp,
8122
- }),
8151
+ createDivCss2Label(`lblTime2`, `/ ${fullTime}`, Object.assign(g_lblPosObj.lblTime2, { display: g_workObj.musicinfoDisp })),
8123
8152
  );
8124
8153
 
8125
8154
  // ボーダーライン表示
@@ -8132,11 +8161,7 @@ const MainInit = _ => {
8132
8161
  const wordSprite = createEmptySprite(judgeSprite, `wordSprite`, { w: g_headerObj.playingWidth });
8133
8162
  for (let j = 0; j <= g_scoreObj.wordMaxDepth; j++) {
8134
8163
  const wordY = (j % 2 === 0 ? 10 : (g_headerObj.bottomWordSetFlg ? g_posObj.distY + 10 : g_sHeight - 60));
8135
- wordSprite.appendChild(createDivCss2Label(`lblword${j}`, ``, {
8136
- x: 100, y: wordY, w: g_headerObj.playingWidth - 200, h: 50,
8137
- siz: C_SIZ_MAIN, align: C_ALIGN_LEFT, fontFamily: getBasicFont(),
8138
- display: `block`, margin: `auto`,
8139
- }));
8164
+ wordSprite.appendChild(createDivCss2Label(`lblword${j}`, ``, Object.assign(g_lblPosObj.lblWord, { y: wordY, fontFamily: getBasicFont() })));
8140
8165
  }
8141
8166
 
8142
8167
  const jdgGroups = [`J`, `FJ`];
@@ -8191,17 +8216,11 @@ const MainInit = _ => {
8191
8216
  });
8192
8217
 
8193
8218
  // パーフェクト演出
8194
- judgeSprite.appendChild(
8195
- createDivCss2Label(`finishView`, ``, {
8196
- x: g_headerObj.playingWidth / 2 - 150, y: g_sHeight / 2 - 50, w: 300, h: 20, siz: 50,
8197
- }, g_cssObj.common_kita)
8198
- );
8219
+ judgeSprite.appendChild(createDivCss2Label(`finishView`, ``, g_lblPosObj.finishView, g_cssObj.common_kita));
8199
8220
 
8200
8221
  // 曲情報OFF
8201
8222
  if (g_stateObj.d_musicinfo === C_FLG_OFF) {
8202
- [`lblCredit`, `lblDifName`].forEach(labelName => {
8203
- changeStyle(labelName, { x: 20, animationDuration: `4.0s`, animationName: `leftToRightFade`, animationFillMode: `both` });
8204
- });
8223
+ [`lblCredit`, `lblDifName`].forEach(labelName => changeStyle(labelName, g_lblPosObj.musicInfoOFF));
8205
8224
  }
8206
8225
 
8207
8226
  // ローカル時のみフレーム数を残す
@@ -9572,10 +9591,9 @@ const resultInit = _ => {
9572
9591
  const scoreIdHeader = setScoreIdHeader(g_stateObj.scoreId, g_stateObj.scoreLockFlg);
9573
9592
 
9574
9593
  g_animationData.forEach(sprite => {
9575
- if (g_rootObj[`${sprite}failedS${scoreIdHeader}_data`] !== undefined) {
9576
- [g_headerObj[`${sprite}ResultData`], g_headerObj[`${sprite}ResultMaxDepth`]] = makeSpriteData(g_rootObj[`${sprite}failedS${scoreIdHeader}_data`]);
9577
- } else if (g_rootObj[`${sprite}failedS_data`] !== undefined) {
9578
- [g_headerObj[`${sprite}ResultData`], g_headerObj[`${sprite}ResultMaxDepth`]] = makeSpriteData(g_rootObj[`${sprite}failedS_data`]);
9594
+ const failedData = g_rootObj[`${sprite}failedS${scoreIdHeader}_data`] ?? g_rootObj[`${sprite}failedS_data`];
9595
+ if (failedData !== undefined) {
9596
+ [g_headerObj[`${sprite}ResultData`], g_headerObj[`${sprite}ResultMaxDepth`]] = makeSpriteData(failedData);
9579
9597
  }
9580
9598
  });
9581
9599
  } else if (g_gameOverFlg) {
@@ -9615,8 +9633,7 @@ const resultInit = _ => {
9615
9633
 
9616
9634
  // スコア計算(一括)
9617
9635
  const scoreTmp = Object.keys(g_pointAllocation).reduce(
9618
- (score, name) => score + g_resultObj[name] * g_pointAllocation[name]
9619
- , 0)
9636
+ (score, name) => score + g_resultObj[name] * g_pointAllocation[name], 0);
9620
9637
 
9621
9638
  const allScore = g_fullArrows * 10;
9622
9639
  const resultScore = Math.round(scoreTmp / allScore * g_maxScore) || 0;
@@ -9759,35 +9776,25 @@ const resultInit = _ => {
9759
9776
 
9760
9777
  // ランク描画
9761
9778
  resultWindow.appendChild(
9762
- createDivCss2Label(`lblRank`, rankMark, {
9763
- x: 340, y: 160, w: 70, h: 20, siz: 50, align: C_ALIGN_CENTER,
9779
+ createDivCss2Label(`lblRank`, rankMark, Object.assign(g_lblPosObj.lblRank, {
9764
9780
  color: rankColor, fontFamily: getBasicFont(`"Bookman Old Style"`),
9765
- })
9781
+ }))
9766
9782
  );
9767
9783
 
9768
9784
  // Cleared & Failed表示
9769
9785
  const lblResultPre = createDivCss2Label(
9770
9786
  `lblResultPre`,
9771
9787
  resultViewText(g_gameOverFlg ? `failed` : `cleared`),
9772
- {
9773
- x: g_sWidth / 2 - 150, y: g_sHeight / 2 - 160,
9774
- w: 200, h: 50, siz: 60,
9775
- opacity: 0, animationDuration: (g_gameOverFlg ? `3s` : `2.5s`),
9788
+ Object.assign(g_lblPosObj.lblResultPre, {
9789
+ animationDuration: (g_gameOverFlg ? `3s` : `2.5s`),
9776
9790
  animationName: (g_gameOverFlg ? `upToDownFade` : `leftToRightFade`)
9777
- }, g_cssObj.result_Cleared, g_cssObj.result_Window
9791
+ }), g_cssObj.result_Cleared, g_cssObj.result_Window
9778
9792
  );
9779
9793
  divRoot.appendChild(lblResultPre);
9780
9794
 
9781
- divRoot.appendChild(
9782
- createDivCss2Label(
9783
- `lblResultPre2`,
9784
- resultViewText(g_gameOverFlg ? `failed` :
9785
- (playingArrows === g_fullArrows ? g_resultObj.spState : ``)),
9786
- {
9787
- x: g_sWidth / 2 + 50, y: 40, w: 200, h: 30, siz: 20,
9788
- }, g_cssObj.result_Cleared
9789
- )
9790
- );
9795
+ divRoot.appendChild(createDivCss2Label(`lblResultPre2`,
9796
+ resultViewText(g_gameOverFlg ? `failed` : (playingArrows === g_fullArrows ? g_resultObj.spState : ``)),
9797
+ g_lblPosObj.lblResultPre2, g_cssObj.result_Cleared));
9791
9798
 
9792
9799
  // プレイデータは Cleared & Failed に合わせて表示
9793
9800
  playDataWindow.style.animationDuration = `3s`;
@@ -9883,7 +9890,7 @@ const resultInit = _ => {
9883
9890
 
9884
9891
  // Twitter用リザルト
9885
9892
  // スコアを上塗りする可能性があるため、カスタムイベント後に配置
9886
- const hashTag = (g_headerObj.hashTag !== undefined ? ` ${g_headerObj.hashTag}` : ``);
9893
+ const hashTag = (hasVal(g_headerObj.hashTag) ? ` ${g_headerObj.hashTag}` : ``);
9887
9894
  let tweetDifData = `${getKeyName(g_headerObj.keyLabels[g_stateObj.scoreId])}${transKeyData}${getStgDetailName('k-')}${g_headerObj.difLabels[g_stateObj.scoreId]}${assistFlg}`;
9888
9895
  if (g_stateObj.shuffle !== `OFF`) {
9889
9896
  tweetDifData += `:${getShuffleName()}`;
@@ -9919,57 +9926,39 @@ const resultInit = _ => {
9919
9926
  const resultText = `${unEscapeHtml(tweetResultTmp)}`;
9920
9927
  const tweetResult = `https://twitter.com/intent/tweet?text=${encodeURIComponent(resultText)}`;
9921
9928
 
9922
- // ボタン描画
9923
- multiAppend(divRoot,
9924
-
9925
- // タイトル画面へ戻る
9926
- createCss2Button(`btnBack`, g_lblNameObj.b_back, _ => {
9929
+ /** 音源、ループ処理の停止 */
9930
+ const resetCommonBtn = (_id, _name, _posObj, _func, _cssClass) =>
9931
+ createCss2Button(_id, _name, _ => {
9927
9932
  if (g_finishFlg) {
9928
9933
  g_audio.pause();
9929
9934
  }
9930
9935
  clearTimeout(g_timeoutEvtId);
9931
9936
  clearTimeout(g_timeoutEvtResultId);
9932
- }, {
9933
- w: g_sWidth / 4, h: C_BTN_HEIGHT * 5 / 4,
9934
- animationName: `smallToNormalY`, resetFunc: _ => titleInit(),
9935
- }, g_cssObj.button_Back),
9937
+ }, Object.assign(_posObj, { resetFunc: _func }), _cssClass);
9938
+
9939
+ // ボタン描画
9940
+ multiAppend(divRoot,
9941
+
9942
+ // タイトル画面へ戻る
9943
+ resetCommonBtn(`btnBack`, g_lblNameObj.b_back, g_lblPosObj.btnRsBack, titleInit, g_cssObj.button_Back),
9936
9944
 
9937
9945
  // リザルトデータをクリップボードへコピー
9938
9946
  createCss2Button(`btnCopy`, g_lblNameObj.b_copy, _ => {
9939
9947
  copyTextToClipboard(resultText, g_msgInfoObj.I_0001);
9940
- }, {
9941
- x: g_sWidth / 4,
9942
- w: g_sWidth / 2,
9943
- h: C_BTN_HEIGHT * 5 / 8, siz: 24,
9944
- animationName: `smallToNormalY`,
9945
- }, g_cssObj.button_Setting),
9948
+ }, g_lblPosObj.btnRsCopy, g_cssObj.button_Setting),
9946
9949
 
9947
9950
  // リザルトデータをTwitterへ転送
9948
- createCss2Button(`btnTweet`, g_lblNameObj.b_tweet, _ => true, {
9949
- x: g_sWidth / 4, y: g_sHeight - 100 + C_BTN_HEIGHT * 5 / 8,
9950
- w: g_sWidth / 4, h: C_BTN_HEIGHT * 5 / 8, siz: 24,
9951
- animationName: `smallToNormalY`, resetFunc: _ => openLink(tweetResult),
9952
- }, g_cssObj.button_Tweet),
9951
+ createCss2Button(`btnTweet`, g_lblNameObj.b_tweet, _ => true, Object.assign(g_lblPosObj.btnRsTweet, {
9952
+ resetFunc: _ => openLink(tweetResult),
9953
+ }), g_cssObj.button_Tweet),
9953
9954
 
9954
9955
  // Gitterへのリンク
9955
- createCss2Button(`btnGitter`, g_lblNameObj.b_gitter, _ => true, {
9956
- x: g_sWidth / 2, y: g_sHeight - 100 + C_BTN_HEIGHT * 5 / 8,
9957
- w: g_sWidth / 4, h: C_BTN_HEIGHT * 5 / 8, siz: 24,
9958
- animationName: `smallToNormalY`, resetFunc: _ => openLink(`https://gitter.im/danonicw/freeboard`),
9959
- }, g_cssObj.button_Default),
9956
+ createCss2Button(`btnGitter`, g_lblNameObj.b_gitter, _ => true, Object.assign(g_lblPosObj.btnRsGitter, {
9957
+ resetFunc: _ => openLink(`https://gitter.im/danonicw/freeboard`),
9958
+ }), g_cssObj.button_Default),
9960
9959
 
9961
9960
  // リトライ
9962
- createCss2Button(`btnRetry`, g_lblNameObj.b_retry, _ => {
9963
- if (g_finishFlg) {
9964
- g_audio.pause();
9965
- }
9966
- clearTimeout(g_timeoutEvtId);
9967
- clearTimeout(g_timeoutEvtResultId);
9968
- }, {
9969
- x: g_sWidth / 4 * 3,
9970
- w: g_sWidth / 4, h: C_BTN_HEIGHT * 5 / 4,
9971
- animationName: `smallToNormalY`, resetFunc: _ => loadMusic(),
9972
- }, g_cssObj.button_Reset),
9961
+ resetCommonBtn(`btnRetry`, g_lblNameObj.b_retry, g_lblPosObj.btnRsRetry, loadMusic, g_cssObj.button_Reset),
9973
9962
  );
9974
9963
 
9975
9964
  // マスクスプライトを作成