new:新增技能导出
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
"@vueuse/core": "^12.8.2",
|
||||
"axios": "^1.8.2",
|
||||
"hoci": "^0.6.0",
|
||||
"html-to-image": "^1.11.13",
|
||||
"pako": "^2.1.0",
|
||||
"pinia": "^3.0.1",
|
||||
"query-string": "^9.1.1",
|
||||
|
||||
Generated
+8
@@ -17,6 +17,9 @@ importers:
|
||||
hoci:
|
||||
specifier: ^0.6.0
|
||||
version: 0.6.0(@babel/parser@7.26.9)(@vueuse/core@12.8.2(typescript@5.8.2))(rollup@4.35.0)(vue@3.5.13(typescript@5.8.2))
|
||||
html-to-image:
|
||||
specifier: ^1.11.13
|
||||
version: 1.11.13
|
||||
pako:
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0
|
||||
@@ -1547,6 +1550,9 @@ packages:
|
||||
hookable@5.5.3:
|
||||
resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
|
||||
|
||||
html-to-image@1.11.13:
|
||||
resolution: {integrity: sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==}
|
||||
|
||||
human-signals@8.0.0:
|
||||
resolution: {integrity: sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==}
|
||||
engines: {node: '>=18.18.0'}
|
||||
@@ -3877,6 +3883,8 @@ snapshots:
|
||||
|
||||
hookable@5.5.3: {}
|
||||
|
||||
html-to-image@1.11.13: {}
|
||||
|
||||
human-signals@8.0.0: {}
|
||||
|
||||
ignore@5.3.2: {}
|
||||
|
||||
@@ -28,6 +28,13 @@
|
||||
class="ml-1"
|
||||
icon="exchange"
|
||||
></calc-button>
|
||||
<calc-button
|
||||
title="技能加点导出"
|
||||
@click="exportSkillTree"
|
||||
:disabled="exportingSkillTree || !infoStore.infos"
|
||||
class="ml-1"
|
||||
icon="share"
|
||||
></calc-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -51,8 +58,16 @@ import ImportVue from './Config/import.vue'
|
||||
import ImportSkillVue from './Config/importSkill.vue'
|
||||
import ImportDnfhelper from './Config/importDnfhelper.vue'
|
||||
import Result from './Result/Index.vue'
|
||||
import SkillTree from './Skill/components/SkillTree'
|
||||
import { useDnfHelperStore } from '@/stores/dnfhelper.ts'
|
||||
import { type IHelperRoleInfo } from '@/api/info/type'
|
||||
import { useDialog } from '@/components/hooks/dialog'
|
||||
import { toPng } from 'html-to-image'
|
||||
import { h, nextTick, render } from 'vue'
|
||||
|
||||
const skillTreeExportWidth = 550
|
||||
const skillTreeExportPixelRatio = 2
|
||||
|
||||
const props = defineProps<{
|
||||
alter: string
|
||||
}>()
|
||||
@@ -63,6 +78,8 @@ const importVisible = ref(false)
|
||||
const importSkillVisible = ref(false)
|
||||
const helperStore = useDnfHelperStore()
|
||||
const toImport = ref<IHelperRoleInfo>()
|
||||
const exportingSkillTree = ref(false)
|
||||
const { alert } = useDialog()
|
||||
|
||||
// const shouldWatch = ref(true)
|
||||
|
||||
@@ -92,6 +109,79 @@ const showImportSkill = () => {
|
||||
importSkillVisible.value = true
|
||||
}
|
||||
|
||||
const waitForSkillImages = async (root: HTMLElement) => {
|
||||
const pendingImages = Array.from(root.querySelectorAll('img')).filter((image) => !image.complete)
|
||||
if (pendingImages.length === 0) return
|
||||
|
||||
await Promise.race([
|
||||
Promise.all(
|
||||
pendingImages.map(
|
||||
(image) =>
|
||||
new Promise<void>((resolve) => {
|
||||
image.addEventListener('load', () => resolve(), { once: true })
|
||||
image.addEventListener('error', () => resolve(), { once: true })
|
||||
}),
|
||||
),
|
||||
),
|
||||
new Promise<void>((resolve) => window.setTimeout(resolve, 3000)),
|
||||
])
|
||||
}
|
||||
|
||||
const exportSkillTree = async () => {
|
||||
if (exportingSkillTree.value || !infoStore.infos) return
|
||||
|
||||
exportingSkillTree.value = true
|
||||
const exportHost = document.createElement('div')
|
||||
exportHost.className = 'skill-tree-export-host'
|
||||
const exportRoot = document.createElement('div')
|
||||
exportRoot.className = 'skill-tree-export-root'
|
||||
exportHost.appendChild(exportRoot)
|
||||
document.body.appendChild(exportHost)
|
||||
|
||||
try {
|
||||
render(
|
||||
h(SkillTree, {
|
||||
skills: infoStore.skills,
|
||||
lvInfo: configStore.config.skills,
|
||||
bindAwake: configStore.config.bindAwake,
|
||||
alter: infoStore.infos.alter,
|
||||
}),
|
||||
exportRoot,
|
||||
)
|
||||
|
||||
await nextTick()
|
||||
await document.fonts.ready
|
||||
await waitForSkillImages(exportRoot)
|
||||
|
||||
const exportHeight = exportRoot.scrollHeight
|
||||
const dataUrl = await toPng(exportRoot, {
|
||||
width: skillTreeExportWidth,
|
||||
height: exportHeight,
|
||||
canvasWidth: skillTreeExportWidth,
|
||||
canvasHeight: exportHeight,
|
||||
pixelRatio: skillTreeExportPixelRatio,
|
||||
backgroundColor: '#101012',
|
||||
cacheBust: true,
|
||||
})
|
||||
|
||||
const fileName = `${infoStore.infos.name || props.alter}-技能加点.png`.replace(
|
||||
/[\\/:*?"<>|]/g,
|
||||
'-',
|
||||
)
|
||||
const downloadLink = document.createElement('a')
|
||||
downloadLink.download = fileName
|
||||
downloadLink.href = dataUrl
|
||||
downloadLink.click()
|
||||
} catch (error) {
|
||||
console.error('技能加点导出失败', error)
|
||||
await alert({ content: '技能加点导出失败,请稍后重试' })
|
||||
} finally {
|
||||
render(null, exportRoot)
|
||||
exportHost.remove()
|
||||
exportingSkillTree.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
onMounted(async () => {
|
||||
@@ -163,4 +253,19 @@ onUnmounted(() => {
|
||||
left: 0;
|
||||
background-color: rgba(50, 50, 50, 0.75);
|
||||
}
|
||||
|
||||
.skill-tree-export-host {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: -10000px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.skill-tree-export-root {
|
||||
width: 550px;
|
||||
min-width: 550px;
|
||||
overflow: visible;
|
||||
color: #e9c558;
|
||||
background: #101012;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useVModel } from '@vueuse/core'
|
||||
import CalcButton from '@/components/calc/button/index.vue'
|
||||
import './style.scss'
|
||||
|
||||
const rowPrefixes = ['通用', 1, '', 10, '', 20, '', 30, '', 40, 50, 60, 70, 80, 90, 100]
|
||||
const rowPrefixes = ['通用', 1, '', 10, '', 20, '', 30, '', 40, '', 50, 60, 70, 80, 90, 100]
|
||||
const defaultColumnCount = 11
|
||||
const altersWithoutRowPrefix = new Set(['creator', 'dark_knight'])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user