1
0
mirror of https://github.com/robonen/eulerian-cycle.git synced 2026-03-20 02:44:47 +00:00

Fixed displaying steps in the player

This commit is contained in:
2021-12-16 15:14:59 +07:00
parent 098d020105
commit 24abf2c840
4 changed files with 108 additions and 73 deletions

View File

@@ -509,15 +509,15 @@ p {
font-size: 14px; font-size: 14px;
} }
.fade-enter-active { .fade-up-enter-active {
animation: fade-in 0.5s; animation: fade-up 0.5s;
} }
.fade-leave-active { .fade-up-leave-active {
animation: fade-in 0.5s reverse; animation: fade-up 0.5s reverse;
} }
@keyframes fade-in { @keyframes fade-up {
from { from {
transform: translateY(-40px); transform: translateY(-40px);
opacity: 0; opacity: 0;

View File

@@ -131,6 +131,16 @@ export default {
}); });
}; };
const checkGraph = () => {
euler.loadLinks(Object.values(links.value));
if (links.value.length > 0 && euler.check()) {
emit("hasEuler", euler.find());
} else {
emit("hasEuler", null);
}
};
// Nodes // Nodes
const activateNodes = (ids) => const activateNodes = (ids) =>
ids.forEach((e) => (nodes.value[e].selected = true)); ids.forEach((e) => (nodes.value[e].selected = true));
@@ -149,6 +159,7 @@ export default {
if (hasntIntersections(newNode)) { if (hasntIntersections(newNode)) {
nodes.value.push(newNode); nodes.value.push(newNode);
emit("hasVertices", nodes.value.length);
} }
}; };
@@ -167,7 +178,8 @@ export default {
nodes.value = nodes.value.filter((_, idx) => idx !== id); nodes.value = nodes.value.filter((_, idx) => idx !== id);
emit("isEuler", []); checkGraph();
emit("hasVertices", nodes.value.length);
}; };
const selectNode = (id) => { const selectNode = (id) => {
@@ -245,10 +257,7 @@ export default {
target, target,
}); });
euler.loadLinks(Object.values(links.value)); checkGraph();
if (euler.check()) emit("isEuler", euler.find());
else emit("isEuler", []);
}); });
const removeLink = (id) => { const removeLink = (id) => {

View File

@@ -25,16 +25,25 @@ export default {
components: { components: {
Popup, Popup,
}, },
props: {
steps: {
type: Array,
required: true,
},
},
setup(props, { emit }) { setup(props, { emit }) {
// Const
const steps = [
{
name: "Создание вершин",
content:
"Для создания новой вершины необходимо дважды нажать левую кнопку мыши",
video: "/video/create.mp4",
},
{
name: "Связывание вершин",
content:
"Чтобы связать вершины, необходимо кликнуть левой кнопкой мыши по вершине, которую необходимо связать. Далее выбираются вершины, с которыми необходимо связать",
video: "/video/linking.mp4",
},
];
// Reactive // Reactive
const currentStep = ref(0); const currentStep = ref(0);
// Methods // Methods
const stepDown = () => { const stepDown = () => {
if (currentStep.value <= 0) return; if (currentStep.value <= 0) return;
@@ -43,7 +52,7 @@ export default {
}; };
const stepUp = () => { const stepUp = () => {
if (currentStep.value + 1 >= props.steps.length) { if (currentStep.value + 1 >= steps.length) {
close(); close();
return; return;
} }
@@ -57,6 +66,7 @@ export default {
}; };
return { return {
steps,
currentStep, currentStep,
stepDown, stepDown,
stepUp, stepUp,

View File

@@ -1,5 +1,5 @@
<template> <template>
<guide v-show="showGuide" :steps="guide" @close="showGuide = false"></guide> <guide v-show="showGuide" @close="showGuide = false"></guide>
<popup v-show="showInfo" @close="showInfo = false"> <popup v-show="showInfo" @close="showInfo = false">
<template v-slot:title> <template v-slot:title>
Циклы в эйлером графе Циклы в эйлером графе
@@ -28,33 +28,41 @@
</div> </div>
<div class="wrapper"> <div class="wrapper">
<header> <header>
<transition name="fade"> <transition name="fade-up">
<div v-if="errorText" class="error" @click="errorText = ''"> <div v-if="errorText" class="error" @click="errorText = ''">
{{ errorText }} {{ errorText }}
</div> </div>
</transition> </transition>
<div class="header-step-cont inaccessible"> <transition name="fade-up">
<div class="header-step-text"> <div v-if="stepExists" class="header-step-cont">
<div class="header-vertex"> <div class="header-step-text">
{{ stepExists ? steps[currentStep].source : "-" }} <div class="header-vertex">
{{ currentStepData.source ?? "-" }}
</div>
<div class="header-arrow"></div>
<div class="header-vertex">
{{ currentStepData.target ?? "-" }}
</div>
</div> </div>
<div class="header-arrow"></div> <div class="header-step-description">
<div class="header-vertex"> шаг {{ stepExists ? currentStepNumber + 1 : "-" }} /
{{ stepExists ? steps[currentStep].target : "-" }} {{ stepExists ? stepsTotal : "-" }}
</div> </div>
</div> </div>
<div class="header-step-description"> </transition>
шаг {{ stepExists ? currentStep + 1 : "-" }} /
{{ stepExists ? stepsCount : "-" }}
</div>
</div>
</header> </header>
<div class="graph-cont"> <div class="graph-cont">
<div class="empty-graph-cont"> <div v-if="!vertexExists" class="empty-graph-cont">
Нажмите ЛКМ дважды, чтобы добавить вершину Нажмите ЛКМ дважды, чтобы добавить вершину
</div> </div>
<graph @isEuler="getSteps" :stepData="currentStepData"></graph> <graph
<div class="hints">Чтобы удалить вершину, нажмите ПКМ по ней</div> :stepData="currentStepData"
@hasEuler="loadSteps"
@hasVertices="setVertices"
></graph>
<div v-if="vertexExists" class="hints">
Чтобы удалить вершину, нажмите ПКМ по ней
</div>
</div> </div>
<div class="control-cont"> <div class="control-cont">
<div class="control-button" id="previous-step" @click="prevStep"> <div class="control-button" id="previous-step" @click="prevStep">
@@ -77,7 +85,6 @@
> >
<div class="prompt">Продолжить</div> <div class="prompt">Продолжить</div>
</div> </div>
<div class="control-button" id="next-step" @click="nextStep"> <div class="control-button" id="next-step" @click="nextStep">
<div class="prompt">Следующий шаг</div> <div class="prompt">Следующий шаг</div>
</div> </div>
@@ -85,14 +92,14 @@
</div> </div>
<div class="addition-cont"> <div class="addition-cont">
<div class="step-cont"> <div class="step-cont">
<div <!-- <div
class="step" class="step"
v-for="cs in stepsCount" v-for="cs in stepsCount"
:key="cs" :key="cs"
:class="{ 'active-step last-active-step': cs - 1 === currentStep }" :class="{ 'active-step last-active-step': cs - 1 === currentStep }"
> >
{{ cs }} {{ cs }}
</div> </div> -->
<!-- <div class="step active-step">2</div> <!-- <div class="step active-step">2</div>
<div class="step active-step last-active-step">3</div> <div class="step active-step last-active-step">3</div>
<div class="step">1</div> <div class="step">1</div>
@@ -117,26 +124,16 @@ export default {
setup() { setup() {
// Const // Const
let timer = null; let timer = null;
const guide = [ const ANIMATION_DELAY = 1500;
{ const ERROR_DELAY = 5000;
name: "Создание вершин",
content:
"Для создания новой вершины необходимо дважды нажать левую кнопку мыши",
video: "/video/create.mp4",
},
{
name: "Связывание вершин",
content:
"Чтобы связать вершины, необходимо кликнуть левой кнопкой мыши по вершине, которую необходимо связать. Далее выбираются вершины, с которыми необходимо связать",
video: "/video/linking.mp4",
},
];
// Reactive // Reactive
const vertices = ref(0);
const steps = ref([]); const steps = ref([]);
const currentStep = ref(0); const currentStepNumber = ref(0);
const currentStepData = ref({}); const currentStepData = ref({});
const played = ref(false); const played = ref(false);
const showInfo = ref(false); const showInfo = ref(false);
const showGuide = ref(false); const showGuide = ref(false);
const errorText = ref(""); const errorText = ref("");
@@ -152,44 +149,58 @@ export default {
}); });
// Computed // Computed
const vertexExists = computed(() => {
return vertices.value > 0;
});
const stepExists = computed(() => { const stepExists = computed(() => {
return steps.value.length > 0; return steps.value.length > 0;
}); });
const stepsCount = computed(() => { const stepsTotal = computed(() => {
return steps.value.length; return steps.value.length;
}); });
// Methods // Methods
const log = () => { const showError = (msg) => {
showInfo.value = true; errorText.value = msg;
setTimeout(() => (errorText.value = false), ERROR_DELAY);
}; };
const getSteps = (data) => { const setVertices = (data) => {
steps.value = data; vertices.value = data;
currentStep.value = 0; };
currentStepData.value = steps.value[currentStep.value];
const loadSteps = (data) => {
steps.value = data ?? [];
currentStepNumber.value = 0;
currentStepData.value = steps.value[currentStepNumber.value] ?? {};
}; };
const nextStep = () => { const nextStep = () => {
if (currentStep.value >= stepsCount.value - 1) currentStep.value = 0; if (currentStepNumber.value >= stepsTotal.value - 1)
else currentStep.value++; currentStepNumber.value = 0;
else currentStepNumber.value++;
currentStepData.value = steps.value[currentStep.value]; currentStepData.value = steps.value[currentStepNumber.value];
}; };
const prevStep = () => { const prevStep = () => {
if (currentStep.value <= 0) currentStep.value = stepsCount.value - 1; if (currentStepNumber.value <= 0)
else currentStep.value--; currentStepNumber.value = stepsTotal.value - 1;
else currentStepNumber.value--;
currentStepData.value = steps.value[currentStep.value]; currentStepData.value = steps.value[currentStepNumber.value];
}; };
const play = () => { const play = () => {
if (!stepExists.value) return; if (!stepExists.value) {
showError("Эйлеров цикл не найден!");
return;
}
played.value = true; played.value = true;
timer = setInterval(nextStep, 1000); timer = setInterval(nextStep, ANIMATION_DELAY);
}; };
const stop = () => { const stop = () => {
@@ -199,21 +210,26 @@ export default {
}; };
return { return {
// Player properties
vertexExists,
steps, steps,
stepsCount, stepsTotal,
stepExists, stepExists,
currentStep, currentStepNumber,
currentStepData, currentStepData,
played, played,
getSteps,
// Player methods
setVertices,
loadSteps,
nextStep, nextStep,
prevStep, prevStep,
play, play,
stop, stop,
log,
// Helpers
showInfo, showInfo,
showGuide, showGuide,
guide,
errorText, errorText,
}; };
}, },