整合p5页面的级联选择
<script setup>
import { ref, onUnmounted, nextTick, readonly } from "vue";
import { ElMessage, ElLoading } from "element-plus";
import { isClient } from "@vueuse/core";
import * as p5MainFunc from "@scripts/p5Funcs";
import { allMethods,singleList } from "@scripts/p5Funcs/p5FantasticMethod";
const props = defineProps({ type: String ,outpage:Boolean});
const funcs = {};
for (let p5MainFuncItem in p5MainFunc) {
funcs[`${p5MainFuncItem}`] = p5MainFunc[`${p5MainFuncItem}`];
}
const singlePage = ref(props.type && funcs[props.type]);
const selectMethhod = ref([]);
let defaultMethod = props.type || "defaultFunc";
if (props.type && props.type === 'random') {
let namArr = []
for (const key in funcs) {
if (Object.hasOwnProperty.call(funcs, key)) {
namArr.push(key)
}
}
const randomName = namArr[Math.floor(Math.random() * 100) % namArr.length]
defaultMethod = randomName
singlePage.value = props.type
}
const methods = readonly(allMethods);
const fullList = ["quickSort", "bubbleSort", "rayCast", "lorenzSystem", "chenShiSystem", "waveFunctionCollapse",...singleList];
const soundList = ["delaySound"];
const loading = () => {
return ElLoading.service({
lock: true,
text: "加载中",
fullscreen: true,
background: "rgba(0, 0, 0, 0.7)",
});
};
let loadInstance;
let dom;
const clearFunc = () => {
dom = document.querySelector("#p5-start")
if (dom) dom.innerHTML = "";
};
const loadP5Func = () => {
clearFunc();
p5 = window['p5'];
new p5(p5MainFunc[defaultMethod], "p5-start");
window["p5DrawLoop"] = defaultMethod;
}
let p5;
if (isClient)
nextTick(() => {
if (soundList.includes(defaultMethod)) {
if (p5?.Oscillator)
loadP5Func()
else {
loadInstance = loading()
import("https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/addons/p5.sound.min.js").then(() => {
loadInstance.close()
loadP5Func()
})
}
} else
loadP5Func()
});
onUnmounted(() => {
window["p5DrawLoop"] = "";
});
const loadMethod = arr => {
if (p5 && typeof p5 === "function") {
let funcName = arr[arr.length - 1];
window["p5DrawLoop"] = singlePage.value || funcName;
//清除之前的
clearFunc();
//新建计算和canvas
dom = document.querySelector("#p5-start");
if (fullList.includes(funcName) && dom) {
dom.requestFullscreen().then(() => {
new p5(funcs[funcName] || p5MainFunc.defaultFunc, "p5-start");
});
} else
new p5(singlePage.value || funcs[funcName] || p5MainFunc.defaultFunc, "p5-start");
}
}
const handleChange = (arr) => {
try {
if (soundList.includes(arr[arr.length - 1])) {
if (p5?.Oscillator)
loadMethod(arr)
else {
loadInstance = loading()
import("https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/addons/p5.sound.min.js").then(() => {
loadInstance.close()
loadMethod(arr)
})
}
} else {
loadMethod(arr)
}
} catch (e) {
ElMessage.warning("可能cdn的p5还没有加载好");
}
};
</script>
<template>
<div :class="['p5-start', props.type === 'random' ? 'random-p5' : '']">
<el-cascader-panel v-model="selectMethhod" :options="methods" @change="handleChange" v-if="!singlePage"
class="cascader" size="large">
<template #default="{ node, data }">
<span>{{ data.label }}</span>
<span v-if="!node.isLeaf">({{ data.children.length }})</span>
</template>
</el-cascader-panel>
<div id="p5-start" :class="[props.outpage ? 'singlepage' : 'container']"></div>
</div>
</template>
<style scoped lang="scss">
#p5-start {
overflow: hidden;
display: flex;
place-items: center;
flex-direction: column;
justify-content: center;
align-items: center;
flex: 1;
&.singlepage {
:deep(canvas) {
position:absolute;
width: 100vw;
height: 100vh;
left: 0;
top: 0;
}
}
}
.p5-start {
display: flex;
gap: 20px;
margin-top: 20px;
min-height: 80vh;
max-height: 90vh;
}
.random-p5{
max-height: 100vh;
}
@media screen and (max-width: 900px) {
.p5-start {
flex-direction: column;
}
}
:deep(.cascader .el-cascader-menu) {
color: var(--c-text) !important;
}
:deep(.el-cascader-menu__wrap.el-scrollbar__wrap) {
height: 100%;
}
</style>