質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.32%

HTML CSS Javascriptで、円周上に8方向の矢印ボタンを作りたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 554

yamekodev

score 15

前提・実現したいこと

HTML CSS Javascriptで、
・円周上に、外向きの八方向の矢印ボタンを配置
・矢印ボタンを押したイベントを取得
したいと考えております。

それぞれの実現方法、ライブラリなどについて何かご存知でしたら、教えていただけないでしょうか?

発生している問題・エラーメッセージ

以下の実現方法が見つけられません。
・矢印を円周上に配置
・矢印の領域だけをボタンとして認識
・左斜め上矢印(コード上の変数名target6)の表示位置がズレている

試したこと

下記方法で、8方向の矢印をCSSで作ることはできました。
https://migi.me/css/direction-size-flexible-arrow/

下記を参考にして円周上に8方向の外向き矢印を配置できました。
https://codepen.io/shmd966/pen/epawaQ?cf_chl_captcha_tk=72622b0b820b07f16c78e4f8c60d41f155dfff1e-1588598505-0-ATqn1ayFNQb4FfaFTo9sBuJwtLmFpuJTJDiAhkwguDvXmL1JiI7oxQEgbbVft5IKLtaYyuVciARMBSSd2LioeUzF3n5ukMo60YE38aDEURFseZDyLVCHlGd4Oo0w_h632pbx7OB1FetI6grTiXwVJJe2cUJg68i9PhfAaNDuJT2IsdZE0gfwSyDcL9SLjxApAkn3Z3aZBz_bUFyvI1uHFfxbIHTv67ofAJMMcxJhdqE-dIzXwdGlcCifVevi2w7FJhUoLUfMOiDr3THtBHOZpWRzTW21GyxsnJzxSRKfl-NTv_VRAnQGsnVXVw6J3xWNBbD6-LHNzxUidzQ8-AoQatp5FONcC3rPtJq4oWlCB6jCJwLEl9UHSJizbFPCi9lfHWI1yNDpEda4uf7rVQwussuhzyQi2oTBBdWt2F7nfMsKlaJSeGuTTvccuEqp9N01AFOmomgt8dZmsvTCjhYPmZNlVbHGyfSNCndCmpgORFRgvV6j-p1nwl0lJ_36chINxK76NpMjftiNdQ_sCWYldXrPfPMhyKRBJ-LcBJ2vo1r3ObcboPEkuSyIOyeWPDMZ5g

また下記レッスンをやることで、単純な四角形、円の領域のみをボタンとして認識させることはできました。
https://dotinstall.com/lessons/basic_javascript_v4

上記ノウハウを組み合わせて、矢印を表示しているdivにイベントリスナーclickを設定しましたが、矢印の余白をクリックしても反応してしまいます。

コード

※右矢印「=>」をクリックすると反応するようにイベントリスナーを設定しています。
コードと実行結果
https://jsfiddle.net/yamekodev/a3koyf1z/

<head>
<script type='text/javascript' src='https://code.jquery.com/jquery-3.5.1.min.js'>
</head>
  <body>
    <section class="circle-box">
    </section>
  </body>
    .circle-box{
        position: relative;
        width: 300px;
        height: 300px;
        margin: 100px auto;
        background:#eee;
        border-radius: 50%;
    }
    .item{
        position: absolute;
        background: #aaa;
        width: 25px;
        height: 25px;
        text-align: center;
        color: #fff;
        font-weight: bold;
        font-size: 25px;
    }


.arrow {
  display: inline-block;

  /* 矢印サンプルだとrelativeだったが、円周サンプルのabsoluteに変更 */
  position: absolute;
  width: 4em;
  height: 4em;
  color: #3388dd;
  font-size: 30px;
}
.arrow:before,
.arrow:after {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  content: "";

}
.arrow:before {
  right: -1em;
  width: 0px;
  height: 0px;

  /* 矢印の三角形の底辺の長さ */
  border: 1.4em solid transparent;

  /* 矢印の三角形の高さ */
  border-left: 0.7em solid currentColor;
}
.arrow:after {
  left: 0px;

  /* 矢印の長方形のタテの長さ */
  width: 3em;

  /* 矢印の長方形のヨコの長さ */
  height: 1.8em;

  background-color: currentColor;
}

/* 縦×横×斜め 8方向分のクラス */
.arrow.d_u {
  transform: rotate(270deg);
}
.arrow.d_ur {
  transform: rotate(315deg);
}
.arrow.d_r {
  transform: rotate(0deg);
}
.arrow.d_dr {
  transform: rotate(45deg);
}
.arrow.d_d {
  transform: rotate(90deg);
}
.arrow.d_dl {
  transform: rotate(135deg);
}
.arrow.d_l {
  transform: rotate(180deg);
}
.arrow.d_ul {
  transform: rotate(215deg);
}

.clicked {
    /* 押されたことがわかるように矢印を赤く */
  color: red;
}
$(function(){

    //hour の arrow を .circle-box に出力
    //for( i=0; i<8; i++){
      $('.circle-box').append('<div class="arrow" id="target1"></div>');
      $('.circle-box').append('<div class="arrow" id="target2"></div>');
      $('.circle-box').append('<div class="arrow" id="target3"></div>');
      $('.circle-box').append('<div class="arrow" id="target4"></div>');
      $('.circle-box').append('<div class="arrow" id="target5"></div>');
      $('.circle-box').append('<div class="arrow" id="target6"></div>');
      $('.circle-box').append('<div class="arrow" id="target7"></div>');
      $('.circle-box').append('<div class="arrow" id="target8"></div>');
    //}

    const target1 = document.getElementById('target1');
    const target2 = document.getElementById('target2');
    const target3 = document.getElementById('target3');
    const target4 = document.getElementById('target4');
    const target5 = document.getElementById('target5');
    const target6 = document.getElementById('target6');
    const target7 = document.getElementById('target7');
    const target8 = document.getElementById('target8');

    target1.classList.add('d_r');    // →
    target2.classList.add('d_dr');    // →↓
    target3.classList.add('d_d');    // ↓
    target4.classList.add('d_dl');    // ←↓
    target5.classList.add('d_l');    // ←
    target6.classList.add('d_ul');    // ←↑
    target7.classList.add('d_u');    // ↑
    target8.classList.add('d_ur');    // ↑→

    //arrowの親要素の半径を計算
    var r = $('.circle-box').width()/2;

    //arrow要素数から角度を計算
    var angle = 360/$('.arrow').length;

    //arrow要素の幅,高さの2分の1を取得
    var l = $('.arrow').width()/2;
    var h = $('.arrow').height()/2;

    //指定
    $(".arrow").each(function(i, elem) {

        var deg = angle * i;
        //console.log(deg);

        //x,y座標の取得
        var x = Math.cos(deg*Math.PI/180)*r+r;
        var y = Math.sin(deg*Math.PI/180)*r+r;

        //円周上を中心に配置されるよう位置を指定
        $(".arrow").eq(i).css("left",x-l);
        $(".arrow").eq(i).css("top",y-h);

    });

    //hour 1が先頭に来るようにする    
//    $(".arrow").each(function(i) {
//        $(this).text(i+3);
//            var a = $(this).text();
//
//            if( a > 8){
//            $(this).text(a - 8);
//            }
//    });

    target1.addEventListener('click', () => {
        target1.textContent = "clicked";
        target1.classList.toggle('clicked');
    });
//    target1.classList.add('d_r');    // →
//    target2.classList.add('d_dr');    // →↓
//    target3.classList.add('d_d');    // ↓
//    target4.classList.add('d_dl');    // ←↓
//    target5.classList.add('d_l');    // ←
//    target6.classList.add('d_ul');    // ←↑
//    target7.classList.add('d_u');    // ↑
//    target8.classList.add('d_ur');    // ↑→


});

補足情報(FW/ツールのバージョンなど)

chrome
ここにより詳細な情報を記載してください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kei344

    2020/05/04 21:30 編集

    https://jsfiddle.net/jks8a75g/ 提示のコードについて、クリックイベントについても設定がないので、どこについて言っているかがわかりません。(修正:円形については質問文を読めていませんでした)

    キャンセル

  • yamekodev

    2020/05/04 22:32

    更新したソースコードで、右矢印をクリックしたときにイベントを追加しました。
    jsfiddleに入力してURLをお伝えしようと思ったのですが、実行しても矢印が表示されませんでした(ローカルだと出ます)。
    申し訳ありません。

    キャンセル

  • yamekodev

    2020/05/05 10:30

    https://jsfiddle.net/yamekodev/a3koyf1z/
    jqueryを読み込んだらjsfiddle上でも動作確認できたのでurlをご連絡します。

    キャンセル

回答 1

checkベストアンサー

+1

円形に配置するのは

https://qiita.com/hirokishirai/items/938c4341b0647766d8dc

こんなのが参考になりそうです。

div要素にonclickイベントを設定したら、divの形の部分だけ有効になりませんか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/05/05 16:39

    あまりいい案が思い付かず、、、

    https://jsfiddle.net/x5vfzwd0/

    例えばこれだとかなり近くはなりますが、矢印の先の三角形の部分はやはり周囲もクリックが有効になってしまいます。

    調べてみるので少し時間をください。

    キャンセル

  • 2020/05/05 16:48

    https://jsfiddle.net/tq4fv5sc/

    clip-pathで切り抜く方法で実現しました。結構めんどくさいですが、arrow1が棒部分、arrow2が三角形部分になっていますので、サイズはそれで調整してください。

    キャンセル

  • 2020/05/07 20:09

    お礼が遅くなり申し訳ありません。
    大変助かりました。
    今回はありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.32%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る