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

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

新規登録して質問してみよう
ただいま回答率
85.50%
SVG

SVGは、XMLを基盤とした2Dベクター画像記述言語。画像を線・面といった図形の集合体として扱うベクター画像のため、環境に適した表示が可能です。アニメーション機能もサポートされており、簡単なインタラクティブコンテンツ作成もできます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

1回答

10369閲覧

SVGをクリックしたときにイベントを発火させたい。

kamille-mio

総合スコア24

SVG

SVGは、XMLを基盤とした2Dベクター画像記述言語。画像を線・面といった図形の集合体として扱うベクター画像のため、環境に適した表示が可能です。アニメーション機能もサポートされており、簡単なインタラクティブコンテンツ作成もできます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2019/07/05 23:25

編集2019/07/11 17:39

前提・実現したいこと

ボタンとして機能させたいSVGをIcon Transition Generatorで生成したSVG画像(アニメーション付き)をクリックした際に、jQueryでHTMLの任意のタグ(ここでは仮にid="header"の部分とする)にtoggleclassを実行し、id="gloval-nav"内のアイテムをディスプレイがMedium以下の際にこのボタンで出し入れできるようにしたい。

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

クリックしてもアニメーションは動作するが、toggleclassが実行されない。

該当のソースコード

html

1~中略~ 2 3<script> 4 $(function() { 5 $('window').on("load", function(e) { //object読み込み後に実行 6 $('#nav-toggle').on('click',function(e){ 7 $("#header").toggleClass('open'); 8 }); 9 }); 10}); 11 12</script> 13</head> 14 15 <header id="header"> 16 <button type="button" class="menuButton" aria-controls="global-nav" aria-expanded="false" id="toggle"> 17 <object type="image/svg+xml" data="Portfolio/svg/icon0001.svg" width="48" height="48" id="nav-toggle"> 18 </object> 19 </button> 20 <div id="g-nav"> 21 <nav class="navbar navbar-expand-lg navbar-default navbar-light navbar-custom bg-info"> 22 <div class="header-logo"> 23 <h1 class="top-logo"><a href="#" class="navbar-brande"><img src="Portfolio/img/brand.png" alt="AirTrip"></a></h1> 24 </div> 25 <div class="search-wrapper"> 26 <div class="input-holder"> 27 <input type="text" class="search-input" placeholder="Type to search" /> 28 <button class="search-icon" onclick="searchToggle(this, event);"><span></span></button> 29 </div> 30 <div> 31 <span class="close" onclick="searchToggle(this, event);"></span> 32 </div> 33 </div> 34 <div class="header-item ml-auto" id="global-nav"> 35 <ul class="nav nav-pills navbar-nav"> 36 <li class="nav-item dropdown"> 37 <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" id="navbarDropdownMenuLink"> <span>旅を始める</span> 38 </a> 39 <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink"> 40 <a href="#" class="dropdown-item">旅行会社から探す</a> 41 <a href="#" class="dropdown-item">当会社と提携している旅行会社一覧</a> 42 <a href="#" class="dropdown-item">行きたい国から探す</a> 43 </div> 44 </li> 45 <li class="nav-item dropdown"> 46 <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">ヘルプ</a> 47 <div class="dropdown-menu pt-3"> 48 <div class="form-group"> 49 <input type="text" class="form-control" placeholder="Search"> 50 </div> 51 <a href="#" class="dropdown-item">アカウントを作成したい</a> 52 <a href="#" class="dropdown-item">パスワードを忘れてしまいました</a> 53 <div class="dropdown-divider"></div> 54 <a href="#" class="btn btn-default dropdown-item" role="button">ヘルプセンターへ</a> 55 </div> 56 </li> 57 <li class="nav-item">登録する</li> 58 <li class="nav-item">ログイン</li> 59 </ul> 60 </div> 61 </nav> 62 </div> 63

svg

1<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" height="48" width="48" id="toggle-b"> 2 <g class="nc-icon-wrapper js-transition-icon" data-effect="rotate" data-event="click" id="hoge"> 3 <g class="js-transition-icon__state" fill="#111111" style="" id="toggle"> 4 <path d="M24 16L12 28l2.83 2.83L24 21.66l9.17 9.17L36 28z" id="up"></path> 5 </g> 6 <g class="js-transition-icon__state" fill="#111111" style="display: none;" aria-hidden="true"> 7 <path d="M33.17 17.17L24 26.34l-9.17-9.17L12 20l12 12 12-12z" id="down"></path> 8 </g> 9 </g> 10 <script>!function(){"use strict";if(!window.requestAnimationFrame){var a=null;window.requestAnimationFrame=function(t,i){var e=(new Date).getTime();a||(a=e);var s=Math.max(0,16-(e-a)),n=window.setTimeout(function(){t(e+s)},s);return a=e+s,n}}function r(t,i,e,s){return 1&gt;(t/=s/2)?e/2*t*t*t*t+i:-e/2*((t-=2)*t*t*t-2)+i}function e(t){return t?[1,0]:[0,1]}function t(t){this.element=t,this.svg=function t(i){var e=i.parentNode;if("svg"!==e.tagName)e=t(e);return e;}(this.element),this.getSize(),this.states=this.element.querySelectorAll(".js-transition-icon__state"),this.time={start:null,total:200},this.status={interacted:!1,animating:!1},this.animation={effect:this.element.getAttribute("data-effect"),event:this.element.getAttribute("data-event")},this.init()}t.prototype.getSize=function(){var t=this.svg.getAttribute("viewBox");this.size=t?{width:t.split(" ")[2],height:t.split(" ")[3]}:this.svg.getBoundingClientRect()},t.prototype.init=function(){var t=this;this.svg.addEventListener(t.animation.event,function(){t.status.animating||(t.status.animating=!0,window.requestAnimationFrame(t.triggerAnimation.bind(t)))})},t.prototype.triggerAnimation=function(t){var i=this.getProgress(t);this.animateIcon(i),this.checkProgress(i)},t.prototype.getProgress=function(t){return this.time.start||(this.time.start=t),t-this.time.start},t.prototype.checkProgress=function(t){if(this.time.total&gt;t)window.requestAnimationFrame(this.triggerAnimation.bind(this));else{this.status={interacted:!this.status.interacted,animating:!1},this.time.start=null;var i=e(this.status.interacted);this.states[i[0]].removeAttribute("aria-hidden"),this.states[i[1]].setAttribute("aria-hidden","true")}},t.prototype.animateIcon=function(t){if(t&gt;this.time.total){t=this.time.total;}if(0&gt;t){t=0;};var i=e(this.status.interacted);this.states[i[0]].style.display=t&gt;this.time.total/2?"none":"block",this.states[i[1]].style.display=t&gt;this.time.total/2?"block":"none","scale"==this.animation.effect?this.scaleIcon(t,i[0],i[1]):this.rotateIcon(t,i[0],i[1])},t.prototype.scaleIcon=function(t,i,e){var s=r(Math.min(t,this.time.total/2),1,-.2,this.time.total/2).toFixed(2),n=r(Math.max(t-this.time.total/2,0),.2,-.2,this.time.total/2).toFixed(2);this.states[i].setAttribute("transform","translate("+this.size.width*(1-s)/2+" "+this.size.height*(1-s)/2+") scale("+s+")"),this.states[e].setAttribute("transform","translate("+this.size.width*n/2+" "+this.size.height*n/2+") scale("+(1-n)+")")},t.prototype.rotateIcon=function(t,i,e){var s=r(t,0,180,this.time.total).toFixed(2);this.states[i].setAttribute("transform","rotate(-"+s+" "+this.size.width/2+" "+this.size.height/2+")"),this.states[e].setAttribute("transform","rotate("+(180-s)+" "+this.size.width/2+" "+this.size.height/2+")")};var i=document.querySelectorAll(".js-transition-icon");if(i)for(var s=0;i.length&gt;s;s++)new t(i[s])}();</script> 11 12 13</svg>

試したこと

svg内の各所にidを設定し、それらを.onのトリガーに虱潰しに指定したが効果がない。
JavaScriptで同じようなコードを書いても効果がない。

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

jQueryのバーション→ 3.4.1

https://www.airbnb.jp/gift

当方、コーディング初中級者で以下のページのようなサイトをコーディングできるようになるというのを課題として独学でやっているのですが、このサイトのウィンドウサイズを縮めて出てくるのボタンがハンバーガーメニューボタンではなく、このようなボタンを実装をするにはどうすればいいのか、調べるとsvgというものを用いていることと、ハンバーガーメニューボタン自体もそのsvgを用いて作るほうが良いという情報を散見し、後学のために挑戦したところ壁にぶつかってしまい、今回質問させていただきました。

Illustrator等のソフトは持っておらず、最初からsvg描画はハードルが高いのでまずは実装をしてみようとIcon Transition Generatorで生成したものを表示させられたは良いものの、クリックイベントの発火がどうにもできずに困っています。
似たような質問があったのでそこにあった解決方法(onclickでconsole.logやalertを着火させる)も試して見ましたがやはりundifinedだったり反応無しでした。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BluOxy

2019/07/07 11:06

事象を再現させたいので、jQueryのバージョンを追記いただけますか。
guest

回答1

0

ベストアンサー

objectタグからSVGを取得する部分が問題のようです。

objectタグで取得したSVGの取得方法

SVGをobjectタグによって表示している場合は、Javascriptのオブジェクト(jQueryではない)に対して、contentDocumentプロパティを指定して取得する必要があります。

具体的には下記のように書きます。

javascript

1let svgObj = document.getElementById('nav-toggle').contentDocument;

また、contentDocumentで取得した結果をjQueryオブジェクトでラップすることで、jQueryのメソッドを利用することもできます。

javascript

1let $svgObj = $(document.getElementById('nav-toggle').contentDocument);

※ちなみに、インラインSVGの場合はkamille-mioさんが掲示したコードの通り$('#nav-toggle')で取得可能できるようです。

これでSVGを操作するための事前準備が出来ました。

しかし、実際にSVGをクリックされた時に何か処理をさせたい場合はcontentDocumentの中身にアクセスする必要があります。

contentDocumentの中身にアクセスする方法

先ほどのjQueryでラップしたオブジェクト($svgObj)に対して、jQueryのfindメソッドでアクセスすれば良いです。

javascript

1let $svg = $svgObj.find('svg'); 2$svg.on('click', function () { 3 $("#header").toggleClass('open'); 4});

まとめ

最終的には下記コードで動作しました。
他は特に変更を加えていないので、headタグのみ抜粋しています。
jQueryは3.4.1(現時点での最新版)を使用しています。

html

1<head> 2 <script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script> 3 <script> 4 $(window).on('load', function () { //object読み込み後に実行 5 let $svgObj = $(document.getElementById('nav-toggle').contentDocument); 6 let $svg = $svgObj.find('svg'); 7 $svg.on('click', function () { 8 $("#header").toggleClass('open'); 9 }); 10 }); 11 </script> 12</head>

Chromeでの注意点

上記コードをローカルで開くとChromeでは動作しませんでした。
$svgObjnullになります。

調べてみると、ローカルで開いた外部SVGはファイルシステムを通してアクセスするため、それがChromeでは禁止されているようです。(恐らくセキュリティ上の問題)

Chromeで動作確認をしたい場合はサーバーにアップロードしてアクセスしてください。
ローカルサーバーを立ててローカルアクセスでも大丈夫です。

参考

SVGをjQueryで操作する際にハマったので、書き留めておく。
Cannot read property 'contentDocument' of null
objectで表示したSVGの様々な値をスマートにjQueryで動かしたりする方法

投稿2019/07/07 12:31

編集2019/07/07 12:42
BluOxy

総合スコア2663

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kamille-mio

2019/07/07 19:11

vagrantでローカルサーバーを立てて、確認をしたところ無事に発火を確認できました。 findメソッドについては調べがついてて試してたりしたのですが、当方Windows環境なのでSVGのオブジェクト読み込みでの使用はChromeでしか確認環境がなく、ローカル状態で確認していたのがいけなかったのかもしれません。 ですが、JavaScriptについてはマークアップ系に比べて勉強が浅いことも事実なので、まだマークアップ系も万全とは言えない中でもこれを機会にwebページで必要になってくる猟奇に関しては参考のページ含め、勉強をしていきたいと思います。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問