Skip to content

Commit

Permalink
フレーズの状態を表示する機能を追加
Browse files Browse the repository at this point in the history
  • Loading branch information
sigprogramming committed Dec 9, 2023
1 parent 46556c9 commit efb29a3
Show file tree
Hide file tree
Showing 4 changed files with 239 additions and 44 deletions.
86 changes: 65 additions & 21 deletions src/components/Sing/ScoreSequencer.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
<template>
<div class="score-sequencer">
<!-- 左上の角 -->
<div class="corner"></div>
<div class="sequencer-corner"></div>
<!-- ルーラー -->
<sequencer-ruler :offset="scrollX" :num-of-measures="numOfMeasures" />
<sequencer-ruler
class="sequencer-ruler"
:offset="scrollX"
:num-of-measures="numOfMeasures"
/>
<!-- 鍵盤 -->
<sequencer-keys :offset="scrollY" :black-key-width="30" />
<sequencer-keys
class="sequencer-keys"
:offset="scrollY"
:black-key-width="30"
/>
<!-- シーケンサ -->
<div
ref="sequencerBody"
Expand Down Expand Up @@ -95,20 +103,24 @@
@handleDragRightStart="handleDragRightStart"

Check warning on line 103 in src/components/Sing/ScoreSequencer.vue

View workflow job for this annotation

GitHub Actions / lint

v-on event '@handleDragRightStart' must be hyphenated

Check warning on line 103 in src/components/Sing/ScoreSequencer.vue

View workflow job for this annotation

GitHub Actions / build-test

v-on event '@handleDragRightStart' must be hyphenated
@handleDragLeftStart="handleDragLeftStart"

Check warning on line 104 in src/components/Sing/ScoreSequencer.vue

View workflow job for this annotation

GitHub Actions / lint

v-on event '@handleDragLeftStart' must be hyphenated

Check warning on line 104 in src/components/Sing/ScoreSequencer.vue

View workflow job for this annotation

GitHub Actions / build-test

v-on event '@handleDragLeftStart' must be hyphenated
/>
</div>
<div class="sequencer-overlay">
<sequencer-phrase-indicator
v-for="phraseInfo in phraseInfos"
:key="phraseInfo.key"
:phrase-key="phraseInfo.key"
class="sequencer-phrase-indicator"
:style="{
width: `${phraseInfo.width}px`,
transform: `translateX(${phraseInfo.x - scrollX}px)`,
}"
/>
<div
class="sequencer-body-playhead-wrapper"
class="sequencer-playhead"
:style="{
width: `${gridWidth}px`,
height: `${gridHeight}px`,
transform: `translateX(${playheadX - scrollX}px)`,
}"
>
<div
class="sequencer-body-playhead"
:style="{
transform: `translateX(${playheadX}px)`,
}"
></div>
</div>
></div>
</div>
<!-- NOTE: スクロールバー+ズームレンジ仮 -->
<input
Expand Down Expand Up @@ -152,6 +164,7 @@ import { useStore } from "@/store";
import SequencerRuler from "@/components/Sing/SequencerRuler.vue";
import SequencerKeys from "@/components/Sing/SequencerKeys.vue";
import SequencerNote from "@/components/Sing/SequencerNote.vue";
import SequencerPhraseIndicator from "@/components/Sing/SequencerPhraseIndicator.vue";
import {
getMeasureDuration,
getNoteDuration,
Expand All @@ -171,6 +184,7 @@ export default defineComponent({
SequencerRuler,
SequencerKeys,
SequencerNote,
SequencerPhraseIndicator,
},
setup() {
const ZOOM_X_MIN = 0.2;
Expand Down Expand Up @@ -274,6 +288,15 @@ export default defineComponent({
return Math.floor(baseX * zoomX.value);
});
const selectedNoteIds = computed(() => state.selectedNoteIds);
const phraseInfos = computed(() => {
return Object.entries(state.phrases).map(([key, phrase]) => {
const startBaseX = tickToBaseX(phrase.startTicks, tpqn.value);
const endBaseX = tickToBaseX(phrase.endTicks, tpqn.value);
const startX = startBaseX * zoomX.value;
const endX = endBaseX * zoomX.value;
return { key, x: startX, width: endX - startX };
});
});
const sequencerBody = ref<HTMLElement | null>(null);
Expand Down Expand Up @@ -753,6 +776,7 @@ export default defineComponent({
scrollX,
scrollY,
playheadX,
phraseInfos,
sequencerBody,
setZoomX,
setZoomY,
Expand Down Expand Up @@ -782,13 +806,26 @@ export default defineComponent({
grid-template-columns: 48px 1fr;
}
.corner {
.sequencer-corner {
grid-row: 1;
grid-column: 1;
background: #fff;
border-bottom: 1px solid #ccc;
border-right: 1px solid #ccc;
}
.sequencer-ruler {
grid-row: 1;
grid-column: 2;
}
.sequencer-keys {
grid-row: 2;
grid-column: 1;
}
.sequencer-body {
grid-row: 2;
grid-column: 2;
backface-visibility: hidden;
overflow: auto;
position: relative;
Expand All @@ -798,15 +835,23 @@ export default defineComponent({
}
}
.sequencer-body-playhead-wrapper {
position: absolute;
top: 0;
left: 0;
.sequencer-overlay {
grid-row: 2;
grid-column: 2;
position: relative;
overflow: hidden;
pointer-events: none;
}
.sequencer-body-playhead {
.sequencer-phrase-indicator {
position: absolute;
top: -2px;
left: 0;
height: 6px;
border-radius: 2px;
}
.sequencer-playhead {
position: absolute;
top: 0;
left: -2px;
Expand All @@ -815,7 +860,6 @@ export default defineComponent({
background: colors.$primary;
border-left: 1px solid rgba(colors.$background-rgb, 0.83);
border-right: 1px solid rgba(colors.$background-rgb, 0.83);
pointer-events: none;
}
.sequencer-grid {
Expand Down
83 changes: 83 additions & 0 deletions src/components/Sing/SequencerPhraseIndicator.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<template>
<div :class="`${className}`"></div>
</template>

<script lang="ts">
import { defineComponent, computed } from "vue";
import { useStore } from "@/store";
import { PhraseState } from "@/store/type";
export default defineComponent({
name: "SingSequencerPhraseIndicator",
props: {
phraseKey: { type: String, required: true },
},
setup(props) {
const store = useStore();
const className = computed(() => {
const phrase = store.state.phrases[props.phraseKey];
const classNames: Record<PhraseState, string> = {
WAITING_TO_BE_RENDERED: "waiting-to-be-rendered",
NOW_RENDERING: "now-rendering",
COULD_NOT_RENDER: "could-not-render",
PLAYABLE: "playable",
};
return classNames[phrase.state];
});
return {
className,
};
},
});
</script>

<style scoped lang="scss">
@use '@/styles/variables' as vars;
@use '@/styles/colors' as colors;
.waiting-to-be-rendered {
background-color: colors.$background;
background-image: linear-gradient(
to right,
rgba(colors.$primary-rgb, 0.8),
rgba(colors.$primary-rgb, 0.8)
);
}
.now-rendering {
border: 1px solid rgba(colors.$primary-rgb, 0.7);
background-color: colors.$background;
background-size: 28px 28px;
background-image: linear-gradient(
-45deg,
colors.$primary,
colors.$primary 25%,
rgba(colors.$primary-rgb, 0.36) 25%,
rgba(colors.$primary-rgb, 0.36) 50%,
colors.$primary 50%,
colors.$primary 75%,
rgba(colors.$primary-rgb, 0.36) 75%,
rgba(colors.$primary-rgb, 0.36) 100%
);
animation: stripes-animation 0.7s linear infinite;
}
@keyframes stripes-animation {
from {
background-position-x: 0;
}
to {
background-position-x: 28px;
}
}
.could-not-render {
background-color: colors.$background;
background-image: linear-gradient(to right, #ef5d58, #ef5d58);
}
.playable {
visibility: hidden;
}
</style>
Loading

0 comments on commit efb29a3

Please sign in to comment.