クランク型コネクタ

とりあえずぼちぼちと使えそうなパーツを作っておこうかなと、こんな夜中まで作業しています。
まずはツリー型プロット表示用のコネクタから。
コネクタ1本なのにけっこう重いんだけど、大丈夫かしら。※

クリックして拡大表示/縮小表示します
ドラッグ:箱を移動する
ダブルクリック:新しい箱を作る

ここクリックするとダウンロード
ここにファイルを放り込むと初期化

修正履歴
  • 箱2個とコネクター1本からスタート
  • ウインドウを広げられるように変更
  • ダブルクリックで箱を増やせるように変更
  • ファイルへの書き出し読み込み機能の追加

暫定でデータの読み書き機能もつけてみました。
スクリプトはこんな。(読み書き機能やウインドウ拡大機能は省きます)

jQuery(function(){
    var number = 1;
    // まずは箱を動かせるようにする
    jQuery('.boxes .movableBox').draggable();
    // 箱の中身を描画
    jQuery('.boxes .movableBox').each(function(){
        jQuery(this).html(jQuery(this).attr('id'));
    });
    // 箱の生成
    jQuery('.boxes').on('dblclick','.movableBox',function(){
        // ID
        var newID = "箱" + number++;
        // 箱を作る
        jQuery('.boxes').append('<div id="' + newID + '" class="movableBox" from="'+ jQuery(this).attr('id') +'">' + newID + '</div>');
        jQuery('#' + newID).offset({ top: jQuery(this).offset().top + 200, left: jQuery(this).offset().left });
        // 箱を動かせるようにする
        jQuery('#' + newID).draggable();
        // コネクタ作る
        newConnector( jQuery('#' + newID) );
        // コネクタの内部構造作る
        jQuery('.connector[to="' + newID + '"]').append('<div class="connectorTop"></div><div class="connectorBottom"></div>');
        // コネクタの座標を設定する
        connectKeep( jQuery('.connector[to="' + newID + '"]') );
    });
    // コネクタを生成
    jQuery('.boxes .movableBox[from]').each(function(){
        newConnector(this);
    });
    // コネクタに内部構造を作る
    jQuery('.boxes .connector').append('<div class="connectorTop"></div><div class="connectorBottom"></div>');
    // インターバルでコネクタを更新する
    setInterval(function(){
        jQuery('.boxes .connector').each(function(){
            connectKeep( this );
        });
    },20);
    // レシーブポストになんか届いた時の処理
    var myPost = document.getElementById('recievePost');
    // MutationObserverオブジェクトを作って監視する
    var mo = new MutationObserver(function() {
        // ポストの中身を取り出して
        var getData = jQuery('#recievePost').html();
        // 描画域に描きだして
        jQuery('#blobPost').html( getData );
        // 念のためポストの中を空にする
        jQuery('.boxes .movableBox').draggable();
    });
    var config = { childList: true };
    mo.observe(myPost, config);
});
// コネクタ生成の本体
function newConnector( target ){
    var to = jQuery(target).attr('id');
    var from = jQuery('#' + jQuery(target).attr('from') ).attr('id');
    jQuery('.boxes').prepend('<div class="connector" from="' + from + '" to="' + to + '"></div>');
}
// コネクタの線を描く
function connectKeep( target ){
    var fromID = jQuery(target).attr('from');
    var toID = jQuery(target).attr('to');
    var pos;
    var fromBox = jQuery('#' + fromID);
    var toBox = jQuery('#' + toID);
    var HDistance = getHDistance( fromBox, toBox);
    var VDistance = getVDistance( fromBox, toBox);
    var myTop, myLeft, myHeight, myWidth;
    if ( HDistance > 0 ){
        myLeft = getHCenter(fromBox);
        myWidth = HDistance;
        pos = 'LB';
        if (jQuery(target).attr('pos') != pos){
        jQuery(target).attr('pos',pos)
        jQuery(target).children('.connectorTop').addClass('rightSide');
        jQuery(target).children('.connectorTop').removeClass('leftSide');
        jQuery(target).children('.connectorBottom').addClass('leftSide');
        jQuery(target).children('.connectorBottom').removeClass('rightSide');
        }
    }else{
        myLeft = getHCenter(toBox);
        myWidth = -HDistance;
        pos = 'RB';
        if (jQuery(target).attr('pos') != pos){
        jQuery(target).attr('pos',pos)
        jQuery(target).children('.connectorTop').addClass('leftSide');
        jQuery(target).children('.connectorTop').removeClass('rightSide');
        jQuery(target).children('.connectorBottom').addClass('rightSide');
        jQuery(target).children('.connectorBottom').removeClass('leftSide');
        }
    }
    if ( VDistance > 0 ){
        myTop = getVCenter(fromBox);
        myHeight = VDistance;
        pos = 'LT';
        if (jQuery(target).attr('pos') != pos){
        jQuery(target).attr('pos',pos)
        jQuery(target).children('.connectorTop').addClass('downSide');
        jQuery(target).children('.connectorTop').removeClass('upSide');
        jQuery(target).children('.connectorBottom').addClass('upSide');
        jQuery(target).children('.connectorBottom').removeClass('downSide');
        }
    }else{
        myTop = getVCenter(toBox);
        myHeight = -VDistance;
        pos = 'RT';
        if (jQuery(target).attr('pos') != pos){
        jQuery(target).attr('pos',pos)
        jQuery(target).children('.connectorTop').addClass('upSide');
        jQuery(target).children('.connectorTop').removeClass('downSide');
        jQuery(target).children('.connectorBottom').addClass('downSide');
        jQuery(target).children('.connectorBottom').removeClass('upSide');
        }
    } 
    jQuery(target).offset({ top: myTop, left: myLeft });
    jQuery(target).css({'width': myWidth});
    jQuery(target).css({'height': myHeight});
}
function getHDistance( from, to ){
    return getHCenter( jQuery(to) ) - getHCenter( jQuery(from) );
}
function getHCenter( myTarget ){
    return jQuery(myTarget).offset().left + jQuery(myTarget).width() / 2;
}
function getVDistance( from, to ){
    return getVCenter( jQuery(to) ) - getVCenter( jQuery(from) );
}
function getVCenter( myTarget ){
    return jQuery(myTarget).offset().top + jQuery(myTarget).height() / 2;
}

ちなみに、jquery-ui.min.js がないと動きません。
CSSはこんな。

<style>
.boxes{
    position: relative;
    padding-top: 42px;
}
.movableBox{
    border-radius: 20px;
    border: solid 6px #444444;
    background-color: rgba(255,255,255,1);
    width: 120px;
    height: 120px;
    position: absolute;
    text-align: center;
    line-height: 30px;
    z-index: 1;
    cursor: pointer;
}
.connector{
    position: absolute;
    width: 0px;
    height: 0px;
    z-index: 0;
}
.connectorTop{
    border-bottom: 3px solid #444444;
    width: 100%;
    height: 50%;
}
.connectorBottom{
    border-top: 3px solid #444444;
    width: 100%;
    height: 50%;
}
.connectorTop.rightSide.upSide, .connectorTop.leftSide.downSide{ border-right: 6px solid #444444;}
.connectorTop.rightSide.downSide, .connectorTop.leftSide.upSide{ border-left: 6px solid #444444;}
.connectorBottom.rightSide.upSide, .connectorBottom.leftSide.downSide{ border-left: 6px solid #444444;}
.connectorBottom.rightSide.downSide, .connectorBottom.leftSide.upSide{ border-right: 6px solid #444444;}
#aboard{
    position:relative;
    background-color: #ccccdd;
    border: solid 2px #ccccee; 
    width: 100%;
    box-sizing: border-box;
    height: 500px;
    overflow: clip;
}
#bboard{
    position:absolute;
    background-color: #ffffff;
    width: 100%;
    height: 100%;
    overflow: clip;
    z-index: 2000;
}
.topBar{
    position: absolute;
    background-color: rgba(20,20,80,0.4);
    height: 42px;
    width:100%;
    top: 0;
    font-weight: 700;
    color: #ffffff;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
    z-index: 100;
}
.centerBox{
    width: 100%;
    height: 100%;
    overflow: scroll;
}
.bottomBar{
    position: absolute;
    background-color: rgba(20,20,80,0.4);
    width: 100%;
    bottom: 16px;
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 100;
}
#sendPost {
    height: 50px;
    min-width: 200px;
    display: inline-block;
    border: #888888 2px dashed;
    box-sizing: border-box;
    border-radius: 10px;
    background-color: #ffffff;
    font-weight: 800;
    padding: 10px;
    margin: 10px;
}
#sendPost:hover {
    background-color: #ffeedd;
}
.button{
    height: 50px;
    min-width: 200px;
    display: inline-block;
    border: #555555 2px solid;
    box-sizing: border-box;
    border-radius: 10px;
    background-color: #a8b0f0;
    font-weight: 800;
    padding: 10px;
    margin: 10px;
    cursor: pointer;
}
.button:hover{
    background-color: #c2ccff;
}
#recievePost{
    display: none;
}
</style>

重要なとこだけ抜き出そうかとも思ったけど、もはやどこが重要なのやら。
#aboard,#bboard,openBar はウインドウを広げる機能用です。
HTMLはこんな。

<div id='aboard'>
    <div id='bboard'>
        <div class="topBar">クリックして拡大表示/縮小表示します</div>
        <div class='centerBox'>
            <div class="boxes" style="min-height: 100%;" id="blobPost">
                ドラッグ:箱を移動する
                ダブルクリック:新しい箱を作る
                <div id="ひらがな" class="movableBox" style="left:250px; top: 50px;"></div>
                <div id="あ行" class="movableBox" from="ひらがな" style="left:50px; top: 250px;"></div>
                <div id="か行" class="movableBox" from="ひらがな" style="left:250px; top: 250px;"></div>
                <div id="さ行" class="movableBox" from="ひらがな" style="left:450px; top: 250px;"></div>
            </div>
        </div>
        <div class="bottomBar">
            <div class="button blobToFile" id="MyGreatTree">ここクリックするとダウンロード</div>
            <div class="dashed" id="sendPost">ここにファイルを放り込むと初期化</div>
            <div id="recievePost"></div>
        </div>
    </div>
</div>

こちらも、id=aboard,id=#bboard,class=openBar あたりはウインドウ機能用です。
 

Follow me!

コメントは受け付けていません。