プロが教えるわが家の防犯対策術!

現在スマホサイトを制作中なのですが、ある画像(A)に拡大画像(B)リンクを設置して、タップすることでlightboxにて拡大画像(B)を表示させるという構造を考えています。

それは良いのですが、ここで以下のような挙動を得たいのです。。

まずその画像(A)を1回タップすると「hoge_off.jpg」「hoge_on.jpg」に差し替わり、2回目タップでhref発動(lightboxにて拡大画像(B)を表示)という挙動を得たいのですが、調べても解決できず困っています…。

とりあえず、シングルタップで画像の差し替えはできるようになったのですが、1タップでhrefが発動(lightboxにて拡大画像(B)が表示)してしまうため、ユーザーに「hoge_on.jpg」を見せることができません…。

【まとめ】
1.<解決>画像(A)をlightboxにて拡大画像(B)を表示させたい
2.<解決>画像(A)を1回タップすると「hoge_off.jpg」「hoge_on.jpg」に差し替えたい
3.<未解決>1回タップでlightboxが発動するため「hoge_on.jpg」を見せることができないため、lightbox発動をダブルタップにしたい

↑(3)の解決策を教えていただけましたら助かります。。
どうか宜しくお願い申し上げます。。

質問者からの補足コメント

  • つらい・・・

    fujillinさんに教えていただいた方法を早速試してみました…
    しかし私のスキル不足のせいで今回教えていただいた内容を実現することができませんでした…(´;ω;`)
    やはり私の考えていることを実現しようとするとそれ相応のスキルが必要なのでしょうか…
    簡単にできそうだと思い提案してしまったのをいま少し後悔しています…( ノД`)
    けど、ありがとうございました!

    No.1の回答に寄せられた補足コメントです。 補足日時:2017/04/11 11:06

A 回答 (3件)

ANo2です。



HTMLの記述がイマイチでしたので、もう少しすっきりさせてみました。
<li>
<img src="A.jpg" alt=""><img src="B.jpg" alt="">
<div class="box"><img class="large" src="C.jpg" alt=""></div>
</li>
程度ですまないものかと・・・
(都度、必要な要素を生成していますので、かわりにスクリプトは少し長くなっています)
基本的な仕組みは同じなので内容的にはほぼ同じですが、あちこちいじりました。

<!DOCTYPE HTML>
<html lang="ja">
<head><title>Sample</title>

<style type="text/css">
#testbox, #testbox *{
margin: 0; padding: 0;
}
#testbox li div.box{
display:none; position: fixed;
left: 0; top: 0;
width: 100%; height: 100%;
}
#testbox li img{
width: 150px;
}
#testbox li img:nth-child(2){
display: none;
}

/* single click時 */
#testbox li.ON img{
display: inline;
}
#testbox li.ON img:first-child{
display: none;
}

/* double click時 */
#testbox li.appear div.box{
display: table;
}
#testbox li.appear figure{
display: table-cell;
width: 100%; height: 100%;
vertical-align: middle;
}
#testbox li.appear figure img{
width: 100%;
}
#testbox figure figcaption {
display: block; margin: auto;
padding: 6px; background-color: #000;
border-radius: 10px;
position: relative;
}
#testbox figure figcaption,
#testbox figure span.marker{
max-width: 450px;
}
#testbox figure span.marker{
display: block; margin: auto;
height: 0; overflow: visible;
text-align: right;
z-index: 5001;
}

/* close marker */
#testbox figure span.marker::after {
content: "\00D7"; display: inline-block;
position: relative;
text-align: center; font-weight: bold;
right: -16px; top: -10px;
color: #ffffff;
border: 1px #ffffff solid;
border-radius: 10px;
width: 20px; height: 20px;
line-height: 20px;
background-color: #000000;
cursor: pointer;
z-index: 5002;
}

/* background layer */
#testbox figure span.marker::before {
content: ""; display: block;
position: fixed;
left: 0; top: 0;
width: 100%; height: 100%;
background-color: #000000;
opacity: 0.8;
}
</style>
</head>

<body>
<ul id="testbox">
<li>
<img src="A.jpg" alt=""><img src="B.jpg" alt="">
<div class="box"><img class="large" src="C.jpg" alt=""></div>
</li>

<li>
<img src="D.jpg" alt=""><img src="E.jpg" alt="">
<div class="box"><img class="large" src="F.jpg" alt=""></div>
</li>
</ul>


<script type="text/javascript">
(function(elm, evt1, evt2){

// lightbox風表示用要素の準備
var addBox = function(p){
var d = p.querySelector('div.box'), img = d.querySelector('img');
var html = '<figure><span class="marker"></span><figcaption></figcaption></figure>';
d.insertAdjacentHTML('afterbegin', html);
d.querySelector('figcaption').appendChild(img);
}

// lightbox風表示用要素の削除
var removeBox = function(p){
var d = p.querySelector('div.box'), img = d.querySelector('img');
while(d.firstChild) d.removeChild(d.firstChild);
d.appendChild(img);
}

// LI要素にクラスを設定
var setClass = function(t, cls){
var p = t.parentNode;
while(p.nodeName != 'LI' && p != elm) p = p.parentNode;
if(p != elm){
var f = p.classList.contains('appear');
if(cls == 2 && !f) addBox(p);
else if(cls == 0 && f) removeBox(p);
p.classList.remove('ON');
p.classList.remove('appear');
if(cls>0) p.classList.add(',ON,appear'.split(',')[cls]);
}
}

// シングルクリック処理(evt1)
var SingleEvt = function(e){
var t = e.target, n = t.nodeName;
if(n=='IMG' && !t.classList.contains('large')) setClass(t, 1);
else if(n == 'SPAN' && t.classList.contains('marker')) setClass(t, 0);
}

// ダブルクリック処理(evt2)
var DoubleEvt = function(e){
var t = e.target, n = t.nodeName;
if(n == 'IMG' && !t.classList.contains('large')) setClass(t, 2);
}

// イベント設定
elm.addEventListener(evt1, SingleEvt, false);
elm.addEventListener(evt2, DoubleEvt, false);

})(document.getElementById('testbox'), 'click', 'dblclick');
</script>
</body>
</html>
    • good
    • 0
この回答へのお礼

お礼が遅れてしまって申し訳ありませんでした( ノД`)
すごく参考になるご回答、ありがとうございました!!

お礼日時:2017/05/23 16:57

ANo1です。



>それ相応のスキルが必要なのでしょうか…
全体にあちこち関連があるので、少し気を付けないとならないのは確かです。
個々の部分に関しては、通常のイベント処理と同様なので、その程度のことができれば可能と思います。

実際にどのようなものをイメージなさっているのかがわかりませんが、ご参考までに、勝手なイメージで適当に作成してみました。
とはいっても、残念ながら当方にはスマホでのテスト環境がありませんので、#1の最初に述べたイベントの判定処理と振り分けに関しては含んでいません。
(要は、通常のPC閲覧での対応になっています)
スマホへの対応の際には、eventオブジェクトを引数として、シングルタップの処理はSingleEvtに、ダブルタップの処理はDoubleEvtに渡すようにすれば同様の結果になるはずと思います。


サンプルの仕組みとしては、#1の最後に挙げた、CSSでlightbox風に表示する例を、要素のクラス設定に応じて行えるように変えたものを利用しています。
(ですので、javascriptライブラリ等は不要です)
・切り替えで使用する画像は全てHTML内に記す方式にしてあります。
・仮にUL-LIのリスト形式とし、LI要素を最小単位にしています。
・LI要素のクラス設定で、以下の表示が切り替わります。
  なし:通常表示(LI内の最初の画像を表示)(A.jpg、A2.jpg)
  ON : 二番目の画像を表示(B.jpg、B2.jpg)
  appear:lightbox風表示で拡大画像を表示(C.jpg、C3.jpg)
上記の表示分けをCSSでできるようにした上で、スクリプトはLI要素のクラスの変更だけを受け持つという仕組みです。

<!DOCTYPE HTML>
<html lang="ja">
<head><title>Sample</title>

<style type="text/css">
#testbox, #testbox *{
margin: 0; padding: 0;
}
#testbox li>div{
display:none; position: fixed;
left: 0; top: 0;
width: 100%; height: 100%;
}
#testbox li img{
width: 150px;
}
#testbox li img:nth-child(2){
display: none;
}

/* single click時 */
#testbox li.ON img{
display: inline;
}
#testbox li.ON img:first-child{
display: none;
}

/* double click時 */
#testbox li.appear>div{
display: table;
}
#testbox li.appear figure{
display: table-cell;
width: 100%; height: 100%;
vertical-align: middle;
}
#testbox li.appear figure img{
width: 100%;
}
#testbox figure figcaption {
display: block; margin: auto;
padding: 6px; background-color: #000;
border-radius: 10px;
position: relative;
}
#testbox figure figcaption,
#testbox figure span.marker{
max-width: 450px;
}
#testbox figure span.marker{
display: block; margin: auto;
height: 0; overflow: visible;
text-align: right;
z-index: 5001;
}

/* close marker */
#testbox figure span.marker::after {
content: "\00D7"; display: inline-block;
position: relative;
text-align: center; font-weight: bold;
right: -16px; top: -10px;
color: #ffffff;
border: 1px #ffffff solid;
border-radius: 10px;
width: 20px; height: 20px;
line-height: 20px;
background-color: #000000;
cursor: pointer;
z-index: 5002;
}

/* background layer */
#testbox figure span.marker::before {
content: ""; display: block;
position: fixed;
left: 0; top: 0;
width: 100%; height: 100%;
background-color: #000000;
opacity: 0.8;
}
</style>
</head>

<body>

<ul id="testbox">
<li>
<img src="A.jpg" alt="">
<img src="B.jpg" alt="">
<div><figure><span class="marker"></span>
<figcaption>
<img class="large" src="C.jpg" alt="">
</figcaption></figure></div>
</li>

<li>
<img src="A2.jpg" alt="">
<img src="B2.jpg" alt="">
<div><figure><span class="marker"></span>
<figcaption>
<img class="large" src="C2.jpg" alt="">
</figcaption></figure></div>
</li>
</ul>

<script type="text/javascript">
(function(elm, evt1, evt2){

// LI要素にクラスを設定
var setClass = function(t, cls){
var p = t.parentNode;
while(p.nodeName != 'LI' && p != elm) p = p.parentNode;
if(p != elm) p.className = cls;
}

// シングルクリック処理(evt1)
var SingleEvt = function(e){
var t = e.target, n = t.nodeName;
if(n=='IMG' && !t.classList.contains('large')) setClass(t, 'ON');
else if(n == 'SPAN' && t.classList.contains('marker')) setClass(t, '');
}

// ダブルクリック処理(evt2)
var DoubleEvt = function(e){
var t = e.target, n = t.nodeName;
if(n == 'IMG' && !t.classList.contains('large')) setClass(t, 'appear');
}

// イベント設定
elm.addEventListener(evt1, SingleEvt, false);
elm.addEventListener(evt2, DoubleEvt, false);

})(document.getElementById('testbox'), 'click', 'dblclick');
</script>
</body>
</html>
    • good
    • 0

こんにちは



スマホはよく解りませんが、ダブルタップ時のイベントが無いようですので、まず、これに対処しておく必要があります。
シングルタップのイベント間の時間が一定時間以下ならダブルタップと判定して、ダブルタップのイベント(または、dblclickイベントなど)としてスクリプトから発火させる必要があります。
(イベントを発火させずに、そのまま処理を行っても良いですが)
https://syncer.jp/javascript-reverse-reference/d …

上記の対処ををセットできたとした上で、以下はdblclickイベントの場合に処理できるようにするいくつかのアイデアです。

◇lightbox利用の場合
lightboxではユーザに開放されているのは、動作のオプションだけのようです。
http://lokeshdhakar.com/projects/lightbox2/#opti …
それなのでスクリプトを修正してカスタマイズするしかなさそうです。
変更点はclick→dblclickとはっきりしているため、検索して変更することが可能なので、比較的に楽とは言えますが、lightboxで利用しているイベントはトリガーの時だけではないので(次の画像表示や閉じるなどでも利用)、それぞれの処理がどの操作に対応しているかを確認した上で修正する必要があります。
あるいは、いっそのこと全て修正してしまい、操作を全部ダブルタップにしてしまうとか…(笑)

◇他のlightbox系ライブラリを利用する方法
lightbox系の他のライブラリでもよいのであれば、ユーザにメソッドを開放しているものがありますので、それらを利用することで、カスタマイズの必要はなくなります。一例として、
http://www.jacklmoore.com/colorbox/
を例とするなら、$.colorbox(~~) で指定の対象をlightbox風に表示してくれますので、dblclick時に対象を指定する部分だけ自作すれば、ご質問の機能を実現できることになります。
メソッドを開放しているライブラリは数多くありますので、お好みのものを選定なされば良いでしょう。

◇CSSでlightbox風表示をする方法
上記はlightbox(風ライブラリ)に、表示処理だけを受け持たせる方法と言えますが、単純なlightbox風の表示だけであれば、CSSだけでも実現できますので、これをうまく応用すればライブラリそのものが必要がなくなるでしょう。
(:targetの項ですが、下の方の例に出ています)
https://developer.mozilla.org/ja/docs/Web/CSS/:t …
この回答への補足あり
    • good
    • 0
この回答へのお礼

お礼が遅くなってしまい大変失礼いたしました…('◇';;)ゞ
非常にご丁寧にありがとうございます!!
一度試してみてまたここにご報告させていただきます!!

お礼日時:2017/04/11 10:40

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!