5
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

html5+canvas+cssで動画再生周りを軽く作ってみた(2)

Last updated at Posted at 2017-03-09

#はじめに
前回の記事のブラッシュアップ。
当時はcanvas使って書いたといったけど、アレだとcanvas何やってんのvideoでいいじゃん、と当時の自分を問い詰めたい。
実際アレ書いて三日後くらいには今回の投稿の形にしてたけど、何やかんやあって今纏めてます。

#前回やったことと今回の展望
html上にcanvas作ってvideoの内容を複写して動画流したよ!
コントローラー的なもの作ったよ!
##ところで前回のって
勘のいい人はお気づきだと思いますが、videoタグで"controls"オプションを付けると出てくるデフォルトのコントローラをJavaScriptで実装しただけ…これはcanvasの機能ほとんど使ってない(別にvideoタグそのものでcontrolsオプションを消して作ればcanvasに複写する必要もない)。
ちなみにさすがにコマ送りは無いので、独自実装ではあります。
###裏を返すと
JavaScriptで実装できるということは、独自のデザインのコントローラを作れるということではあります。
見た目にこだわるクライアントが来たら、ちゃんと工数計上させましょうね…(焦点の合ってない目
##というわけで今回
ちゃんとcanvasとして使いでのある実装で練習に使いましょう、と思ったのですが、長くなりそうなので
今回は「jQueryを使う」まで。ついでに諸々気に食わないところ直していきましょう。

#本題
前回からガラッと変わるけど、やること自体は大差ない…はず
前回はhoge.htmlのhead部にscriptタグ作って書いてたはずだけど、このタイミングでhoge.jsファイルに外出しする感じで。
##とりあえず既存をjQueryにする
サンプルがjQuery使ってなかったのでしょうがないけど、やはりスマートに書きたい。
###getElementByIdが許されるのは小学生までだよねー
aa略。

前回までの書き方
var video = document.getElementById("v");
var canvas = document.getElementById("c");

前回こうやってつかんでいたと思いますが、なんかきもちわるい(?)のでとっととjQueryに書き換えます。

jQueryで書くとこうなる
var video = $('#v').get(0);
var canvas = $('#c').get(0);

うん、スッキリ(個人の感想です)

##ボタン処理もスマートに
ポチっとな、でボタンに乗せたonclickイベント起動するのは私的に嫌いなので…
また個人主観か、と言われそうなので、何が嫌いかよりも何が好きかで語ろうと思います。

###再生ボタン

前回のhoge.html
(script部)
function playVideo(){
 var video = document.getElementById("v");
 if(video.paused){
		video.play();
	}else{
		video.pause();
	}
 setInterval(function(){
	 var canvas = document.getElementById("c");
	 canvas.getContext("2d").drawImage(video, 0, 0, 480, 270);
 }, 1000/30);
}
(body部)
<button onClick="playVideo()">play/stop</button>

いろいろ気に食わない部分はあるが、きれいに書き直そう。

hoge.html
<button id="play_btn">再生/停止</button>

idを設定してjs側で拾う処置。

hoge.js
var nameSpace = {}
nameSpace.FPS = 30; // サンプルの決め打ち数値がアレだったのでとりあえず外出しした
nameSpace.INTERVAL = 1000 / nameSpace.FPS;

$(document).on("click", "#play_btn", function(){
	var video = $('#v').get(0);
	if(video.paused){
		playVideo(video);
	}else{
		stopVideo(video);
	}
});

var playVideo = function(video){
	video.play()
	nameSpace.maindisp = setInterval(function(){
	var canvas = $('#c').get(0);
	canvas.getContext("2d").drawImage(video, 0, 0, 480, 270);
	}, nameSpace.INTERVAL);

}

var stopVideo = function(video){
	video.pause();
	clearInterval(nameSpace.maindisp);
}

着火イベントを拾って起動させたいタイプの僕です。
ちょっと直した部分は、止まってても再描画するの無駄だよね?というアレ。実際の処理はもっと考えましょう。
requestAnimationFrame使うとかがいいと思う、たぶん。今回はそこが本質ではないので無視。あとスクリーンの大きさが定数だけど、ここも実際は考えましょうね…

###フレーム送り

before
(script部)
function reverseFlame(){
var video = document.getElementById("v");

if(!video.paused){
        video.pause();
    }

    video.currentTime -= 1/30; // 30F/1sec前提
}

function forwardFlame(){
var video = document.getElementById("v");

if(!video.paused){
        video.pause();
    }

    video.currentTime += 1/30; // 30F/1sec前提
}
(body部)
<input type="button" value="1コマ戻す" onClick="reverseFlame()">
<input type="button" value="1コマ送る" onClick="forwardFlame()">

(そもそもなんで前回input使ってたのか謎)
こんな似た関数とかメソッドがあるとムカついちゃうタイプが僕です。しかも30F決め打ちとか設計者出てこい!60FPSの動画がきたらどうすんだ!(サンプルに文句を言っちゃう系男子)

after
<button id="frame_btn" value="-1">1コマ戻す</button>
<button id="frame_btn" value="1">1コマ送る</button>

送ると戻すは未来まで含めて1処理にまとめようかと。

hoge.js
$(document).on("click", "#frame_btn", function(){
	var video = $('#v').get(0),
	val = $(this).val();
	if(!video.paused){
		stopVideo();
	}
	video.currentTime += 1 / nameSpace.FPS * val; // 30F前提依存もこれで多少解決
});

これで両対応、さらにコマ送りボタンのval調整で好きなだけ送り/戻しができるという劇的ビフォーアフターである。
やったねたえちゃん!家族が増えなくて済むよ!(真の平和)

コミットするときにflameと綴ってしまった上に、それがコードレビューを通ってしまった現実が、ここ向けに清書していた時に発覚したことが辛くて辛い。

(追記)idがダブってる件をコメントでご指摘いただいたので、id→classへ修正。現実ではclassでいろいろ指定してます。

after
<button class="frame_btn" id="reverse_btn" value="-1">1コマ戻す</button>
<button class="frame_btn" id="forword_btn" value="1">1コマ送る</button>
hoge.js
$(document).on("click", ".frame_btn", function(){
	var video = $('#v').get(0),
	val = $(this).val();
	if(!video.paused){
		stopVideo();
	}
	video.currentTime += 1 / nameSpace.FPS * val; // 30F前提依存もこれで多少解決
});

###ミュートボタン

前回のhtml
(script部)
function changeMute(){
var video = document.getElementById("v");

if(video.muted){
        video.muted = false;
    }else{
        video.muted = true;
    }
}
(body部)
<input type="button" value="ミュート切替" onClick="changeMute()">

ここはもう簡素に書き直すだけ。

今回のhtml
<button id="mute_btn">ミュート切替</button>
hoge.js
$(document).on("click", "#mute_btn", function(){
	var video = $('#v').get(0);
if(video.muted){
        video.muted = false;
    }else{
        video.muted = true;
    }
});

##ちなみに現実
buttonは画像で作った方がいろいろ楽だし、デザイン気にして実装すると絶対そうなるよね。いや、わかってるんだけど、頼むからプログラマのでっち上げボタンのデザインに文句言いやがるなください。
言うならデザイナ雇う金をくれやがってください。同情するなら金(ry

#長くなったので
jQueryでスライダーを実装したりしたけど、それは次回送りで。
その後canvas応用編に入りたいなぁとか。

5
13
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?