MotoJapan's Tech-Memo

技術めも

【Javascript / CSS】divタグでcanvas等のレイアウトを重ねる方法 【お家IT#13】


本件の実装の一部  
motojapan.hateblo.jp

前回の続き  
motojapan.hateblo.jp

目次

前回は、カメラ撮影枠を作成するために、カメラリソースの切り替えによるVideo要素のサイズ変化を検出した。
今回は、実際にカメラ撮影枠を作るためのレイアウトの重ね合わせ方法についてまとめる。

完成イメージ

こんなものを作りたい。
f:id:motojapan:20171029201525p:plain
カメラのプレビュー上に、撮影領域と撮影ボタンを配置したい。

基本方針

  • 基本的な枠組みは、HTMLのdiv要素CSSでレイアウトの重ね合わせ。
  • 動的なレイアウトプロパティの変更は、JavascriptからCSSの設定を変更。

div要素で重ねわせ方法と実装

ポイント

重ねわせで重要なのはCSSのposition。
下記の設定を行う。

外側のparent position: relativeに設定。
内側のl1~l3 特定の位置に置きたい場合、position: absoluteに設定。

特に今回は、

  • l1は、video要素があり、動画ストリームが確定すると自動的にサイズが決まる
  • l2は、l1のサイズのサイズに応じて、動的にサイズが決まる

となる。

実装

動的にCSSプロパティを操作する場合、2つの方法がある(style / setAttribute)
実装は下記の通り。

//**************** html **********************

<div class="parent" width="720px">
    <div class="l1">
        <video id="camera" width="720px" autoplay></video>
    </div>
    <div class="l2">
        <canvas id="camera_record_box"></canvas>
    </div>
    <div class="l3">
        <a id="take_picture" href="#" class="my_btn">TAKE PICTURE</a>
    </div>
</div>

//**************** css ***********************

<style type="text/css">
.parent {
    width: 720px;
    height: 0px;
    position: relative; /*relativeに設定*/
    border: 3px solid black;
    padding: 0em 0em;
    margin:0;
}
.l1 { /*前回の話の通り、動画ストリームが確定してから自動的にサイズが決まる*/
    top: 0px;
    left: 0px;
    width: 720px; 
    padding: 0em 0em;
}
.l2 {
    top: 0px;   /*動的に変更されるので適当*/
    left: 0px;  /*動的に変更されるので適当*/
    width: 400px; /*撮影枠サイズ*/ 
    height: 60px; /*撮影枠サイズ*/
    position: absolute; /*absoluteに設定*/
    padding: 0em 0em;
}
.l3 {
    bottom: 0px; /*下端に配置*/
    position: absolute; /*absoluteに設定*/
    padding: 0em 0em;
}
#camera_record_box{
    position: absolute; /*absoluteに設定*/
    border: 1px solid red; /*赤い撮影枠*/
    padding: 0em 0em;
}
</style>

//************ javascript ********************

//関数でCSSの設定を操作する
//(前回に追記)

<script type="text/javascript">
function notify_change_size() {
    video_layout_width  = video.clientWidth
    video_layout_height = video.clientHeight

    var element_parent = document.getElementsByClassName('parent');
    var element_l2  = document.getElementsByClassName('l2');
    var element_box = document.getElementById('camera_record_box');

    box_width  = 400 //box size
    box_height = 60  //box size

    left = (video_layout_width - box_width) / 2
    top = (video_layout_height - box_height) / 2

    //parentへの設定
    for(var i=0, l=element_parent.length; i<l; i++){
        element_parent[i].style.width   =  String(video_layout_width)  + "px";
        element_parent[i].style.height  =  String(video_layout_height) + "px";
    }

    //l2への設定
    for(var i=0, l=element_l2.length; i<l; i++){
        //今回はi=0のみ
        element_l2[i].style.left =  String(left)  + "px";
        element_l2[i].style.top  =  String(top)   + "px";
        element_l2[i].style.width   =  String(box_width)  + "px";
        element_l2[i].style.height  =  String(box_height) + "px";
    }

    //camera_record_boxへの設定
    element_box.setAttribute("width",  String(box_width)  + "px");
    element_box.setAttribute("height", String(box_height) + "px");
}

videoElement.onresize = notify_change_size;

</script>

結果

上手くいった。
f:id:motojapan:20171029200239j:plain


以上。

次回はボタンを透過したい。