最初コミット
このコミットが含まれているのは:
コミット
5e5becb592
|
@ -0,0 +1,103 @@
|
|||
[
|
||||
{ "id": 1, "timestamp": 0, "text": "くねくね" },
|
||||
{ "id": 1, "timestamp": 0, "text": "アンダイン" },
|
||||
{ "id": 1, "timestamp": 0, "text": "2号兄貴リスペクト" },
|
||||
{ "id": 1, "timestamp": 1, "text": "カミナリ" },
|
||||
{ "id": 1, "timestamp": 1, "text": "あー生き返れ生き返れ" },
|
||||
{ "id": 2, "timestamp": 2, "text": "サイコキネシス" },
|
||||
{ "id": 3, "timestamp": 3, "text": "バッグマン" },
|
||||
{ "id": 3, "timestamp": 3, "text": "パ ッ ク マ ン" },
|
||||
{ "id": 3, "timestamp": 3, "text": "ドンキーコング" },
|
||||
{ "id": 3, "timestamp": 3, "text": "ビンビンビンビン" },
|
||||
{ "id": 3, "timestamp": 3, "text": "7 8 7 B" },
|
||||
{ "id": 3, "timestamp": 4, "text": "ビュインビュインビュインビュインビュイン" },
|
||||
{ "id": 3, "timestamp": 4, "text": "787B" },
|
||||
{ "id": 3, "timestamp": 5, "text": "wwwwwwwwwwwwww" },
|
||||
{ "id": 3, "timestamp": 5, "text": "ここすき" },
|
||||
{ "id": 3, "timestamp": 5, "text": "ワカメ" },
|
||||
{ "id": 3, "timestamp": 5, "text": "草" },
|
||||
{ "id": 3, "timestamp": 6, "text": "草" },
|
||||
{ "id": 3, "timestamp": 7, "text": "チ↑クッ↓" },
|
||||
{ "id": 3, "timestamp": 7, "text": "デクナッツで草" },
|
||||
{ "id": 3, "timestamp": 7, "text": "アロアロアロアロアロアロアロアロアロアロアロアロアロアロ" },
|
||||
{ "id": 3, "timestamp": 8, "text": "wwwwwwwwwwwww" },
|
||||
{ "id": 3, "timestamp": 8, "text": "サルディニア訛りは草" },
|
||||
{ "id": 3, "timestamp": 8, "text": "デクナッツ" },
|
||||
{ "id": 3, "timestamp": 9, "text": "wwwwwwwwwwwwwwwwwwwwwwww" },
|
||||
{ "id": 3, "timestamp": 9, "text": "デカクサン" },
|
||||
{ "id": 3, "timestamp": 9, "text": "ここ怪盗ヒマラ" },
|
||||
{ "id": 4, "timestamp": 11, "text": "呪物やめろ" },
|
||||
{ "id": 4, "timestamp": 11, "text": "ムウマージ確認してたらちょっと似てた" },
|
||||
{ "id": 4, "timestamp": 11, "text": "草" },
|
||||
{ "id": 4, "timestamp": 11, "text": "残念!はずれだヨ!" },
|
||||
{ "id": 4, "timestamp": 11, "text": "???????????????????????????????????????????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 12, "text": "???????????????????????????????????????????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 12, "text": "???????????????????????????????????????????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 12, "text": "???????????????????????????????????????????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 12, "text": "ワ ソ チ 〜 ユ ン グ ?" },
|
||||
{ "id": 4, "timestamp": 12, "text": "???????????????????????????????????????????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 12, "text": "???????????????????????????????????????????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 12, "text": "学校などの教育用機械のクイズではずれた音" },
|
||||
{ "id": 4, "timestamp": 12, "text": "???????????????????????????????????????????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 12, "text": "へっぽこBGM" },
|
||||
{ "id": 4, "timestamp": 12, "text": "?????????" },
|
||||
{ "id": 4, "timestamp": 12, "text": "???????????????????????????????????????????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 12, "text": "ウンチーコングって知ってる?" },
|
||||
{ "id": 4, "timestamp": 12, "text": "???????????????????????????????????????????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 12, "text": "ウ ン チ ー コ ン グ ?" },
|
||||
{ "id": 4, "timestamp": 12, "text": "???????????????????????????????????????????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 12, "text": "チョイーン" },
|
||||
{ "id": 4, "timestamp": 12, "text": "ウ ン チ ~ コ ン グ ?" },
|
||||
{ "id": 4, "timestamp": 12, "text": "草" },
|
||||
{ "id": 4, "timestamp": 12, "text": "クソザコナメクジ" },
|
||||
{ "id": 4, "timestamp": 12, "text": "へな ち ょ こ ん ぐ" },
|
||||
{ "id": 4, "timestamp": 12, "text": "????????????" },
|
||||
{ "id": 4, "timestamp": 12, "text": "くっそw" },
|
||||
{ "id": 4, "timestamp": 12, "text": "草" },
|
||||
{ "id": 4, "timestamp": 12, "text": "ここすき" },
|
||||
{ "id": 4, "timestamp": 12, "text": "ポョヨヨヨヨ~ン" },
|
||||
{ "id": 4, "timestamp": 12, "text": "情けない音で草" },
|
||||
{ "id": 4, "timestamp": 12, "text": "ブレインスキャン開始" },
|
||||
{ "id": 4, "timestamp": 12, "text": "ぽよよ~ん" },
|
||||
{ "id": 4, "timestamp": 13, "text": "√33-√4" },
|
||||
{ "id": 4, "timestamp": 13, "text": "チュイーン(笑)" },
|
||||
{ "id": 4, "timestamp": 13, "text": "??????????" },
|
||||
{ "id": 4, "timestamp": 13, "text": "?????????????????" },
|
||||
{ "id": 4, "timestamp": 13, "text": "???????????????????????????????????????????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 13, "text": "??????????????????????????????????????????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 13, "text": "???????????????????????????????????????????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 13, "text": "????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 13, "text": "????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 13, "text": "草" },
|
||||
{ "id": 4, "timestamp": 13, "text": "????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 13, "text": "ちょい~~んwwww" },
|
||||
{ "id": 4, "timestamp": 14, "text": "????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 14, "text": "????????????????????????????????????????????????????" },
|
||||
{ "id": 4, "timestamp": 14, "text": "音で草" },
|
||||
{ "id": 4, "timestamp": 14, "text": "へ な ち ょ こ" },
|
||||
{ "id": 4, "timestamp": 14, "text": "ギーグ" },
|
||||
{ "id": 4, "timestamp": 13, "text": "草" },
|
||||
{ "id": 4, "timestamp": 15, "text": "ここすき" },
|
||||
{ "id": 4, "timestamp": 15, "text": "????????????????????" },
|
||||
{ "id": 4, "timestamp": 15, "text": "ハピ森の家具動かすときに鳴るSE" },
|
||||
{ "id": 4, "timestamp": 15, "text": "どう森の家具置けない音" },
|
||||
{ "id": 4, "timestamp": 15, "text": "旗" },
|
||||
{ "id": 4, "timestamp": 15, "text": "くねくね" },
|
||||
{ "id": 4, "timestamp": 15, "text": "文字ノリノリでワロタ" },
|
||||
{ "id": 4, "timestamp": 15, "text": "わかめ" },
|
||||
{ "id": 4, "timestamp": 16, "text": "いや、コンブ" },
|
||||
{ "id": 4, "timestamp": 16, "text": "ワカメ" },
|
||||
{ "id": 4, "timestamp": 16, "text": "文字左右にいってるの草" },
|
||||
{ "id": 4, "timestamp": 17, "text": "マイクラでフグ食べたときになるやつ" },
|
||||
{ "id": 4, "timestamp": 17, "text": "ここで耐えられなかった" },
|
||||
{ "id": 4, "timestamp": 17, "text": "ここで耐えられなかった" },
|
||||
{ "id": 4, "timestamp": 17, "text": "こわE" },
|
||||
{ "id": 4, "timestamp": 17, "text": "男すき" },
|
||||
{ "id": 4, "timestamp": 18, "text": "wwwwww" },
|
||||
{ "id": 4, "timestamp": 19, "text": "どう森マジわかるwwwww" },
|
||||
{ "id": 4, "timestamp": 19, "text": "草" },
|
||||
{ "id": 4, "timestamp": 19, "text": "頭おかしなるで" },
|
||||
{ "id": 4, "timestamp": 19, "text": "薬 物 中 毒 者" },
|
||||
{ "id": 4, "timestamp": 21, "text": "サルディニア訛り" },
|
||||
{ "id": 4, "timestamp": 22, "text": "マリカでサンダー食らうとこんなんなるよね" }
|
||||
]
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>動画</title>
|
||||
<script src="vue.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="root">
|
||||
<div ref="videoContainer" class="video-container">
|
||||
<video ref="videoPlayer" @timeupdate="updateComments" controls>
|
||||
<source :src="videoOgv" type="video/ogg" />
|
||||
<source :src="videoWebm" type="video/webm" />
|
||||
このブラウザは<video>タグが対応していません。
|
||||
</video>
|
||||
<div class="comments-overlay" v-if="comments.length">
|
||||
<div v-for="comment in visibleComments" :key="comment.id" class="comment" :style="{ top: comment.yPos + 'px', animation: comment.animationStyle }">
|
||||
{{ comment.text }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,130 @@
|
|||
const player = Vue.createApp({
|
||||
data() {
|
||||
return {
|
||||
videoOgv: 'video.ogv',
|
||||
videoWebm: 'video.webm',
|
||||
commentJson: 'comments.json',
|
||||
comments: [],
|
||||
visibleComments: [],
|
||||
containerWidth: 0
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async loadComments() {
|
||||
try {
|
||||
const resp = await fetch("comments.json");
|
||||
if (!resp.ok) {
|
||||
throw new Error(`HTTPエラー: ${resp.status}`);
|
||||
}
|
||||
const data = await resp.json();
|
||||
this.comments = data.map((comment, index) => {
|
||||
return { ...comment, yPos: (index % 10) * 30 };
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("コメントを受取に失敗:", error);
|
||||
}
|
||||
},
|
||||
updateComments() {
|
||||
const currentTime = this.$refs.videoPlayer.currentTime;
|
||||
let yPos = 0;
|
||||
|
||||
this.visibleComments = this.comments.filter(comment => {
|
||||
const isVisible = currentTime >= comment.timestamp && currentTime <= (comment.timestamp + 5);
|
||||
|
||||
if (isVisible && typeof comment.yPos === 'undefined') {
|
||||
comment.yPos = yPos;
|
||||
yPos += 30;
|
||||
}
|
||||
|
||||
return isVisible;
|
||||
});
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.animateComments();
|
||||
});
|
||||
},
|
||||
animateComments() {
|
||||
const commentsElements = this.$refs.videoContainer.querySelectorAll('.comment');
|
||||
|
||||
commentsElements.forEach(el => {
|
||||
const commentWidth = el.offsetWidth;
|
||||
let totalDistance = this.containerWidth + commentWidth;
|
||||
totalDistance -= (100-commentWidth);
|
||||
|
||||
el.style.transition = 'transform 5s linear';
|
||||
el.style.transform = `translateX(-${totalDistance}px)`;
|
||||
});
|
||||
},
|
||||
updateContainerWidth() {
|
||||
const container = this.$refs.videoContainer;
|
||||
this.containerWidth = container ? container.offsetWidth : 0;
|
||||
},
|
||||
calculateCommentWidth(text) {
|
||||
const tempDiv = document.createElement("div");
|
||||
tempDiv.style.position = "absolute";
|
||||
tempDiv.style.whiteSpace = "nowrap";
|
||||
tempDiv.style.fontSize = "50px";
|
||||
tempDiv.textContent = text;
|
||||
document.body.appendChild(tempDiv);
|
||||
const width = tempDiv.clientWidth;
|
||||
document.body.removeChild(tempDiv);
|
||||
|
||||
return width;
|
||||
},
|
||||
createAnimationKeyframes() {
|
||||
const styleSheet = document.createElement("style");
|
||||
styleSheet.type = "text/css";
|
||||
styleSheet.innerHTML = `
|
||||
@keyframes scrollComment {
|
||||
from { transform: translateX(${this.containerWidth}px); }
|
||||
to { transform: translateX(-${this.containerWidth}px); }
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(styleSheet);
|
||||
},
|
||||
pauseComments() {
|
||||
const commentsElements = this.$refs.videoContainer.querySelectorAll('.comment');
|
||||
commentsElements.forEach(el => {
|
||||
const computedStyle = window.getComputedStyle(el);
|
||||
const transform = computedStyle.transform || computedStyle.webkitTransform;
|
||||
el.style.transform = transform;
|
||||
el.style.transition = 'none';
|
||||
});
|
||||
},
|
||||
playComments() {
|
||||
this.animateComments();
|
||||
},
|
||||
attachVideoEventListeners() {
|
||||
const videoPlayer = this.$refs.videoPlayer;
|
||||
videoPlayer.addEventListener('play', this.playComments);
|
||||
videoPlayer.addEventListener('pause', this.pauseComments);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadComments();
|
||||
this.createAnimationKeyframes();
|
||||
window.addEventListener('resize', () => {
|
||||
this.updateContainerWidth();
|
||||
this.createAnimationKeyframes();
|
||||
});
|
||||
this.updateContainerWidth();
|
||||
this.attachVideoEventListeners();
|
||||
window.addEventListener('resize', this.updateContainerWidth);
|
||||
},
|
||||
beforeUnmount() {
|
||||
window.removeEventListener('resize', this.updateContainerWidth);
|
||||
},
|
||||
computed: {
|
||||
commentAnimationStyle() {
|
||||
return `
|
||||
<style>
|
||||
@keyframes scrollComment {
|
||||
from { transform: translateX(0%); }
|
||||
to { transform: translateX(-${this.containerWidth}px); }
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
}
|
||||
}
|
||||
});
|
||||
player.mount("#root");
|
|
@ -0,0 +1,35 @@
|
|||
.video-container {
|
||||
position: relative;
|
||||
max-width: 900px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
video {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.comments-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.comment {
|
||||
color: #fcfcfc;
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
right: 0;
|
||||
font-size: 50px;
|
||||
text-shadow: -1px 1px 0 #232629, 1px 1px 0 #232629, 1px -1px 0 #232629, -1px -1px 0 #232629;
|
||||
}
|
||||
|
||||
@keyframes scrollComment {
|
||||
from { transform: translateX(1800px); }
|
||||
to { transform: translateX(-1800px); }
|
||||
}
|
バイナリファイルは表示されません。
読み込み中…
新しいイシューから参照