master
humingxing 3 days ago
parent e02909c9df
commit 5e79b343ea
  1. 2
      assets/mx/module/merge/rules/MapPlaceRules.ts
  2. 2
      assets/mx/module/merge/types/MergeTypes.ts
  3. 41
      assets/script/battle/bag/BattleBagSession.ts
  4. 26
      assets/script/battle/map/legacy/MapAreaUnlock.ts
  5. 4
      assets/script/battle/view/CocosBagBoardView.ts
  6. 8
      assets/script/battle/view/MapDragGuideHelper.ts
  7. 20
      preview-template/index.ejs
  8. 131
      preview-template/workbench/css/workbench.css
  9. 6
      preview-template/workbench/js/host.js

@ -99,6 +99,8 @@ export function rejectReasonToMessage(reason: PlaceRejectReason): string {
return '只能放在己方区域'; return '只能放在己方区域';
case PlaceRejectReason.UnlockDrag: case PlaceRejectReason.UnlockDrag:
return ''; return '';
case PlaceRejectReason.UnlockNeedElement:
return '';
default: default:
return ''; return '';
} }

@ -57,6 +57,8 @@ export enum PlaceRejectReason {
WrongCampArea = 'WrongCampArea', WrongCampArea = 'WrongCampArea',
/** 拖文字推进当前解锁区域:字不落下,也不弹失败提示 */ /** 拖文字推进当前解锁区域:字不落下,也不弹失败提示 */
UnlockDrag = 'UnlockDrag', UnlockDrag = 'UnlockDrag',
/** 解锁区要求特定五行,拖入属性不符(文案由业务层按需求属性拼接) */
UnlockNeedElement = 'UnlockNeedElement',
} }
/** 组合英雄激活后写到每个字上的单层 Buff */ /** 组合英雄激活后写到每个字上的单层 Buff */

@ -41,7 +41,7 @@ import { buildGmWeaponPresetQueue } from '../debug/GmBattlePreset';
import type { ProjectBattleHandle } from '../runtime/BattleRuntime'; import type { ProjectBattleHandle } from '../runtime/BattleRuntime';
import { TableNames } from '../../game/ConfigTableData'; import { TableNames } from '../../game/ConfigTableData';
import { RankDataManager } from '../../manager/RankDataManager'; import { RankDataManager } from '../../manager/RankDataManager';
import type { AreaUnlockHero } from '../map/legacy/MapAreaUnlock'; import { unlockHeroTypeName, type AreaUnlockHero } from '../map/legacy/MapAreaUnlock';
import type { DailyShopParsed } from '../../manager/DailyShopTypes'; import type { DailyShopParsed } from '../../manager/DailyShopTypes';
import { import {
resolveCarriedAttrCardSpawnWan, resolveCarriedAttrCardSpawnWan,
@ -89,6 +89,8 @@ export class BattleBagSession {
private _skipOpenEffect = false; private _skipOpenEffect = false;
/** 最近一次区域解锁打开的格(供对端 merge 对齐) */ /** 最近一次区域解锁打开的格(供对端 merge 对齐) */
private _lastUnlockOpened: number[] = []; private _lastUnlockOpened: number[] = [];
/** UnlockNeedElement 动态提示(take 后清空) */
private _unlockFailToast = '';
/** /**
* 寻金尺飞币回调(入账后通知表现层)。 * 寻金尺飞币回调(入账后通知表现层)。
* @param gridIndex 解锁锚点格 * @param gridIndex 解锁锚点格
@ -972,6 +974,29 @@ export class BattleBagSession {
return this._map.areaUnlock.canDrag(grid, this._heroOfGlyph({ weapon2Id, level: lv })); return this._map.areaUnlock.canDrag(grid, this._heroOfGlyph({ weapon2Id, level: lv }));
} }
/**
* 落点所属阵营当前解锁区需求 herotype;0=任意或非待解锁。
* @param gridIndex 落点
*/
currentUnlockNeedHeroType(gridIndex: number): number {
const grid = this.validator.getGridByIndex(gridIndex);
if (!grid?.waitingUnlock) return 0;
return this._map.areaUnlock.currentNeedHeroType(grid.CampAreaID | 0);
}
/**
* 拒绝原因文案;UnlockNeedElement 用动态属性提示。
* @param reason 拒绝原因
*/
formatRejectMessage(reason: PlaceRejectReason): string {
if (reason === PlaceRejectReason.UnlockNeedElement) {
const tip = this._unlockFailToast;
this._unlockFailToast = '';
return tip;
}
return rejectReasonToMessage(reason);
}
/** /**
* 五行字拖到当前解锁区域:类型/显示等级符合则整区可放置并播 openSpine,随后字落在当前格。 * 五行字拖到当前解锁区域:类型/显示等级符合则整区可放置并播 openSpine,随后字落在当前格。
* @param source 拖拽源 * @param source 拖拽源
@ -986,9 +1011,19 @@ export class BattleBagSession {
const w2Type = Math.floor(WeaponComposeConfigProvider.instance.getWeapon2Type(piece.weapon2Id)); const w2Type = Math.floor(WeaponComposeConfigProvider.instance.getWeapon2Type(piece.weapon2Id));
if (w2Type < 1 || w2Type > 5) return 'skip'; if (w2Type < 1 || w2Type > 5) return 'skip';
const hit = this._map.areaUnlock.tryDrag(grid, this._heroOfGlyph(piece)); const hero = this._heroOfGlyph(piece);
const hit = this._map.areaUnlock.tryDrag(grid, hero);
if (hit === 'skip') return 'skip'; if (hit === 'skip') return 'skip';
if (hit === 'blocked') return PlaceRejectReason.WrongCellKind; if (hit === 'blocked') {
const camp = grid.CampAreaID | 0;
const needType = this._map.areaUnlock.currentNeedHeroType(camp);
const name = unlockHeroTypeName(needType);
if (grid.waitingUnlock && needType > 0 && name && (!hero || hero.heroType !== needType)) {
this._unlockFailToast = `需要用${name}属性数字解锁`;
return PlaceRejectReason.UnlockNeedElement;
}
return PlaceRejectReason.WrongCellKind;
}
const camp = grid.CampAreaID | 0; const camp = grid.CampAreaID | 0;
const opened = this._map.areaUnlock.gridsOf(grid.unlockAreaId, camp); const opened = this._map.areaUnlock.gridsOf(grid.unlockAreaId, camp);
this._lastUnlockOpened = []; this._lastUnlockOpened = [];

@ -25,9 +25,19 @@ const LOCK_Y_WITH_BOX = -15;
const _tipWorld = new Vec3(); const _tipWorld = new Vec3();
/** 气泡本地坐标复用 */ /** 气泡本地坐标复用 */
const _tipLocal = new Vec3(); const _tipLocal = new Vec3();
/** herotype → 五行图标名(1金 2木 3水 4火 5土) */ /** herotype → 五行名(1金 2木 3水 4火 5土) */
const HERO_TYPE_ICON: string[] = ['', '金', '木', '水', '火', '土']; const HERO_TYPE_ICON: string[] = ['', '金', '木', '水', '火', '土'];
/**
* herotype 对应五行名;非法或 0 返回空串。
* @param heroType Hero.herotype / unlockland 属性类型
*/
export function unlockHeroTypeName(heroType: number): string {
const type = Math.floor(Number(heroType) || 0);
if (type <= 0 || type >= HERO_TYPE_ICON.length) return '';
return HERO_TYPE_ICON[type];
}
/** /**
* 拖英雄推进区域解锁的结果。 * 拖英雄推进区域解锁的结果。
* skip:不是解锁格,走原落子。 * skip:不是解锁格,走原落子。
@ -166,6 +176,20 @@ export class MapAreaUnlock {
return n; return n;
} }
/**
* 某阵营当前待解锁区需求 herotype;0=任意属性或无可解锁区。
* @param campAreaId 阵营 CampAreaID
*/
currentNeedHeroType(campAreaId: number): number {
const track = this._trackOf(campAreaId);
if (!track) return 0;
const current = this.currentId(campAreaId);
if (current <= 0) return 0;
const index = this._indexOf(current);
if (index < 0 || !track.rolled[index]) return 0;
return Math.floor(Number(track.heroTypes[index]) || 0);
}
/** /**
* 拖到当前解锁区域是否满足类型与等级(不改状态)。 * 拖到当前解锁区域是否满足类型与等级(不改状态)。
* 类型 0 表示任意 herotype,等级须达到配置等级加段位加值。 * 类型 0 表示任意 herotype,等级须达到配置等级加段位加值。

@ -3465,7 +3465,7 @@ export class CocosBagBoardView {
this._bagSession.revertType3Pickup(drag.type3Backup.gridIndex, drag.type3Backup.tile); this._bagSession.revertType3Pickup(drag.type3Backup.gridIndex, drag.type3Backup.tile);
} }
grid.restoreOrigin(); grid.restoreOrigin();
const msg = rejectReasonToMessage(reason); const msg = this._bagSession?.formatRejectMessage(reason) ?? rejectReasonToMessage(reason);
if (msg) gg.ui.showToast(msg); if (msg) gg.ui.showToast(msg);
this._disposeEphemeralDragGrid(grid, drag.source); this._disposeEphemeralDragGrid(grid, drag.source);
this._rebuildFromSession(); this._rebuildFromSession();
@ -6192,7 +6192,7 @@ if (weapon2Id === GRID_WEAPON2_ID) return true;
commitViews: (grid, target, swap) => this._commitViewsAfterSuccessfulDrop(grid, target, swap), commitViews: (grid, target, swap) => this._commitViewsAfterSuccessfulDrop(grid, target, swap),
validateBeforeDrop: opts.validateBeforeDrop, validateBeforeDrop: opts.validateBeforeDrop,
onDropRejected: (reason) => { onDropRejected: (reason) => {
const msg = rejectReasonToMessage(reason); const msg = this._bagSession?.formatRejectMessage(reason) ?? rejectReasonToMessage(reason);
if (msg) gg.ui.showToast(msg); if (msg) gg.ui.showToast(msg);
}, },
rebuildOnFailure: () => this._rebuildFromSession(), rebuildOnFailure: () => this._rebuildFromSession(),

@ -13,6 +13,7 @@ import type { BattleBagSession } from '../bag/BattleBagSession';
import { WeaponComposeConfigProvider } from '../bag/WeaponComposeConfigProvider'; import { WeaponComposeConfigProvider } from '../bag/WeaponComposeConfigProvider';
import type { MapGrid } from '../map/legacy/MapGrid'; import type { MapGrid } from '../map/legacy/MapGrid';
import type { MapManager } from '../map/legacy/MapManager'; import type { MapManager } from '../map/legacy/MapManager';
import { unlockHeroTypeName } from '../map/legacy/MapAreaUnlock';
/** 地图格在拖拽悬停中的落子语义 */ /** 地图格在拖拽悬停中的落子语义 */
export type MapDragDropState = 'valid' | 'blocked' | 'none'; export type MapDragDropState = 'valid' | 'blocked' | 'none';
@ -200,6 +201,13 @@ export class MapDragGuideHelper {
if (!session.validator.isAllowedCampForPlace(mg.Index)) { if (!session.validator.isAllowedCampForPlace(mg.Index)) {
return rejectReasonToMessage(PlaceRejectReason.WrongCampArea); return rejectReasonToMessage(PlaceRejectReason.WrongCampArea);
} }
if (mg.waitingUnlock && isElementGlyphType(w2Type)) {
const needType = session.currentUnlockNeedHeroType(mg.Index);
const name = unlockHeroTypeName(needType);
if (needType > 0 && name && Math.floor(Number(w2Type) || 0) !== needType) {
return `需要用${name}属性数字解锁`;
}
}
if (MapDragGuideHelper.hasSpiderWeb(mg) && w2Type === Weapon2TileType.Grid) { if (MapDragGuideHelper.hasSpiderWeb(mg) && w2Type === Weapon2TileType.Grid) {
return rejectReasonToMessage(PlaceRejectReason.SpiderWebBlocked); return rejectReasonToMessage(PlaceRejectReason.SpiderWebBlocked);
} }

@ -37,19 +37,27 @@
<div id="pw-toolbar" class="pw-toolbar pw-shell-only"> <div id="pw-toolbar" class="pw-toolbar pw-shell-only">
<div class="pw-toolbar-left" title="菜单"> <div class="pw-toolbar-left" title="菜单">
<span class="pw-brand">调试工作台</span> <span class="pw-brand">调试工作台</span>
<div class="pw-btn-group" role="group" aria-label="面板">
<button type="button" class="pw-btn pw-panel-btn" data-panel="hierarchy">层级</button> <button type="button" class="pw-btn pw-panel-btn" data-panel="hierarchy">层级</button>
<button type="button" class="pw-btn pw-panel-btn" data-panel="inspector">属性</button> <button type="button" class="pw-btn pw-panel-btn" data-panel="inspector">属性</button>
<button type="button" class="pw-btn pw-panel-btn" data-panel="assets">资源</button> <button type="button" class="pw-btn pw-panel-btn" data-panel="assets">资源</button>
<button type="button" class="pw-btn pw-panel-btn" data-panel="perf">性能</button> <button type="button" class="pw-btn pw-panel-btn" data-panel="perf">性能</button>
<button type="button" class="pw-btn pw-panel-btn" data-panel="console">控制台</button> <button type="button" class="pw-btn pw-panel-btn" data-panel="console">控制台</button>
</div> </div>
</div>
<div class="pw-toolbar-center" title="设备与快捷"> <div class="pw-toolbar-center" title="设备与快捷">
<select id="pw-device-select" class="pw-select" title="设备"></select> <select id="pw-device-select" class="pw-select" title="设备"></select>
<button type="button" id="pw-device-rotate" class="pw-btn" title="旋转">旋转</button> <button type="button" id="pw-device-rotate" class="pw-btn pw-btn-icon" title="旋转" aria-label="旋转">
<button type="button" id="pw-game-refresh" class="pw-btn" title="刷新并重启游戏">刷新</button> <svg class="pw-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 2a6 6 0 1 0 5.7 4.2" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M13 2v4h-4" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
<button type="button" id="pw-game-refresh" class="pw-btn pw-btn-icon" title="刷新并重启游戏" aria-label="刷新">
<svg class="pw-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M13.5 8a5.5 5.5 0 1 1-1.6-3.9" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M13.5 2.5v3.2h-3.2" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
<button type="button" id="pw-show-fps" class="pw-btn" title="显示 FPS 浮窗" aria-pressed="false">FPS</button> <button type="button" id="pw-show-fps" class="pw-btn" title="显示 FPS 浮窗" aria-pressed="false">FPS</button>
<button type="button" id="pw-game-pause" class="pw-btn">暂停</button> <button type="button" id="pw-game-pause" class="pw-btn">暂停</button>
<button type="button" id="pw-game-step" class="pw-btn" title="暂停时推进一帧">按帧执行</button> <button type="button" id="pw-game-step" class="pw-btn pw-btn-icon" title="暂停时推进一帧" aria-label="按帧执行">
<svg class="pw-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M3 3.5 10 8l-7 4.5V3.5z" fill="currentColor"/><path d="M11.5 3.5h2v9h-2z" fill="currentColor"/></svg>
</button>
<button type="button" id="pw-pure-measure" class="pw-btn" title="关闭全部探针,测真实帧率" aria-pressed="false">纯净测帧</button> <button type="button" id="pw-pure-measure" class="pw-btn" title="关闭全部探针,测真实帧率" aria-pressed="false">纯净测帧</button>
<div class="pw-mode-toggle" role="group" aria-label="输入模式"> <div class="pw-mode-toggle" role="group" aria-label="输入模式">
<button type="button" id="pw-mode-game" class="pw-btn active" data-mode="game">游戏</button> <button type="button" id="pw-mode-game" class="pw-btn active" data-mode="game">游戏</button>
@ -63,6 +71,7 @@
<span id="pw-stat-mem" class="pw-stat">内存 --</span> <span id="pw-stat-mem" class="pw-stat">内存 --</span>
</div> </div>
<span id="pw-engine-status" class="pw-status">引擎等待中…</span> <span id="pw-engine-status" class="pw-status">引擎等待中…</span>
<div class="pw-btn-group" role="group" aria-label="布局">
<select id="pw-layout-preset" class="pw-select" title="布局预设"> <select id="pw-layout-preset" class="pw-select" title="布局预设">
<option value="analyze">分析(按横竖屏)</option> <option value="analyze">分析(按横竖屏)</option>
<option value="portrait">竖屏分析</option> <option value="portrait">竖屏分析</option>
@ -70,7 +79,10 @@
<option value="scene">场景</option> <option value="scene">场景</option>
<option value="minimal">精简</option> <option value="minimal">精简</option>
</select> </select>
<button type="button" id="pw-layout-reset" class="pw-btn" title="重置布局">重置布局</button> <button type="button" id="pw-layout-reset" class="pw-btn pw-btn-icon" title="重置布局" aria-label="重置布局">
<svg class="pw-icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M3 4h10M3 8h10M3 12h6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><path d="M12.5 10.5 14 12l-1.5 1.5" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
</div>
<button type="button" id="pw-workbench-toggle" class="pw-btn active" title="开启/关闭调试工作台(关闭后仍保留设备选项)" aria-pressed="true">工作台</button> <button type="button" id="pw-workbench-toggle" class="pw-btn active" title="开启/关闭调试工作台(关闭后仍保留设备选项)" aria-pressed="true">工作台</button>
</div> </div>
</div> </div>

@ -119,6 +119,8 @@ html[data-pw='shell'] .pw-shell-dummy-canvas,
.pw-root.pw-workbench-off #pw-layout-preset, .pw-root.pw-workbench-off #pw-layout-preset,
.pw-root.pw-workbench-off #pw-layout-reset, .pw-root.pw-workbench-off #pw-layout-reset,
.pw-root.pw-workbench-off #pw-layout-preset ~ .pw-btn-group,
.pw-root.pw-workbench-off .pw-toolbar-right .pw-btn-group,
.pw-root.pw-workbench-off #pw-engine-status { .pw-root.pw-workbench-off #pw-engine-status {
display: none; display: none;
} }
@ -488,6 +490,58 @@ body {
.pw-mode-toggle .pw-btn + .pw-btn { margin-left: -1px; } .pw-mode-toggle .pw-btn + .pw-btn { margin-left: -1px; }
.pw-mode-toggle .pw-btn.active { position: relative; z-index: 1; } .pw-mode-toggle .pw-btn.active { position: relative; z-index: 1; }
/* 图标按钮 / 按钮组 */
.pw-btn-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 26px;
padding: 0;
flex-shrink: 0;
}
.pw-icon {
width: 14px;
height: 14px;
display: block;
pointer-events: none;
}
.pw-btn-group {
display: inline-flex;
align-items: center;
gap: 2px;
padding: 2px;
border: 1px solid var(--pw-border);
border-radius: 6px;
background: rgba(255, 255, 255, 0.02);
}
.pw-btn-group .pw-btn {
border-color: transparent;
background: transparent;
}
.pw-btn-group .pw-btn:hover {
background: rgba(255, 255, 255, 0.05);
border-color: transparent;
}
.pw-btn-group .pw-btn.active {
background: var(--pw-accent);
border-color: var(--pw-accent);
}
.pw-btn-group .pw-select {
border-color: transparent;
background: transparent;
}
.pw-btn-group .pw-select:hover {
background: rgba(255, 255, 255, 0.05);
}
.pw-main { .pw-main {
display: flex; display: flex;
flex: 1; flex: 1;
@ -772,7 +826,7 @@ body {
} }
.pw-summary span { color: var(--pw-muted); } .pw-summary span { color: var(--pw-muted); }
.pw-summary b { color: #fff; font-weight: 600; } .pw-summary b { color: var(--pw-text); font-weight: 600; }
.pw-pick-overlay { .pw-pick-overlay {
position: fixed; position: fixed;
@ -967,8 +1021,19 @@ body {
} }
.pw-console-empty { .pw-console-empty {
color: #9aa0a6; color: var(--pw-muted);
padding: 10px 12px; padding: 28px 16px;
text-align: center;
font-size: var(--pw-fs-sm);
line-height: 1.6;
}
.pw-console-empty::before {
content: "⌨";
display: block;
font-size: 22px;
opacity: 0.35;
margin-bottom: 8px;
} }
.pw-console-row { .pw-console-row {
@ -1239,9 +1304,19 @@ body {
} }
.pw-inspector-empty { .pw-inspector-empty {
padding: 24px 12px; padding: 32px 16px;
text-align: center; text-align: center;
color: var(--pw-muted); color: var(--pw-muted);
font-size: var(--pw-fs-sm);
line-height: 1.6;
}
.pw-inspector-empty::before {
content: "◎";
display: block;
font-size: 22px;
opacity: 0.35;
margin-bottom: 8px;
} }
.pw-insp-section { .pw-insp-section {
@ -1616,13 +1691,17 @@ body {
width: 320px; width: 320px;
height: 360px; height: 360px;
background: var(--pw-panel); background: var(--pw-panel);
border: 1px solid var(--pw-accent); border: 1px solid var(--pw-border-strong);
box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45); box-shadow: 0 12px 36px rgba(0, 0, 0, 0.5);
pointer-events: auto; pointer-events: auto;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden; overflow: hidden;
border-radius: 4px; border-radius: 6px;
}
.pw-float-win:hover {
border-color: var(--pw-accent);
} }
.pw-float-win .pw-panel-root, .pw-float-win .pw-panel-root,
@ -1639,8 +1718,7 @@ body {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
overflow: hidden; overflow: hidden;
background: background: radial-gradient(ellipse at 50% 40%, #1a1e26 0%, #0b0d10 70%);
radial-gradient(ellipse at center, #2c2c30 0%, #0e0e10 72%);
} }
.pw-device-scale { .pw-device-scale {
@ -2018,6 +2096,7 @@ body {
z-index: 20; z-index: 20;
position: relative; position: relative;
touch-action: none; touch-action: none;
transition: background 0.12s ease;
} }
.pw-splitter-h { .pw-splitter-h {
@ -2052,8 +2131,40 @@ body {
height: 12px; height: 12px;
} }
/* 中线把手 */
.pw-splitter-h::before {
content: '';
position: absolute;
left: 1px;
right: 1px;
top: 18%;
bottom: 18%;
border-radius: 1px;
background: transparent;
transition: background 0.12s ease;
}
.pw-splitter-v::before {
content: '';
position: absolute;
top: 1px;
bottom: 1px;
left: 18%;
right: 18%;
border-radius: 1px;
background: transparent;
transition: background 0.12s ease;
}
.pw-splitter:hover, .pw-splitter:hover,
.pw-splitter:active { background: var(--pw-accent); } .pw-splitter:active {
background: var(--pw-accent-soft);
}
.pw-splitter:hover::before,
.pw-splitter:active::before {
background: var(--pw-accent);
}
body.pw-split-dragging { body.pw-split-dragging {
cursor: inherit; cursor: inherit;

@ -295,7 +295,8 @@
var rotateBtn = document.getElementById('pw-device-rotate'); var rotateBtn = document.getElementById('pw-device-rotate');
if (rotateBtn && st) { if (rotateBtn && st) {
rotateBtn.classList.toggle('active', !!st.rotated); rotateBtn.classList.toggle('active', !!st.rotated);
rotateBtn.textContent = st.rotated ? '竖屏' : '旋转'; rotateBtn.title = st.rotated ? '竖屏(当前已旋转)' : '旋转';
rotateBtn.setAttribute('aria-label', st.rotated ? '竖屏' : '旋转');
} }
}).catch(function () { /* */ }); }).catch(function () { /* */ });
}; };
@ -328,7 +329,8 @@
rotateBtn.addEventListener('click', function () { rotateBtn.addEventListener('click', function () {
self.bridge.call('device.rotate').then(function (rotated) { self.bridge.call('device.rotate').then(function (rotated) {
rotateBtn.classList.toggle('active', !!rotated); rotateBtn.classList.toggle('active', !!rotated);
rotateBtn.textContent = rotated ? '竖屏' : '旋转'; rotateBtn.title = rotated ? '竖屏(当前已旋转)' : '旋转';
rotateBtn.setAttribute('aria-label', rotated ? '竖屏' : '旋转');
}); });
}); });
} }

Loading…
Cancel
Save