Javascript - 仅在 DOM 中可见 div 时播放音频

Posted

技术标签:

【中文标题】Javascript - 仅在 DOM 中可见 div 时播放音频【英文标题】:Javascript - Play audio only when a div is visible in the DOM 【发布时间】:2019-04-30 21:32:16 【问题描述】:

我的脚本有问题,我想在单击.bbp 按钮时播放音频,但此按钮位于隐藏的 div 中,然后被克隆。

仅当克隆的 div 在 DOM 中可见时,我想在单击 .bbp 时播放音频,但它对我不起作用。

SEE DEMO LIVE (Codepen) - 代码段不在 *** 上运行

注意如果你评论#products,分配给.bbpyes的音频会播放,否则不会播放,因为音频 脚本无法识别 #products 在 DOM 中是否可见。

所以,首先我需要知道.bbp 是可见的,我不知道该怎么做。

有什么想法吗...?

提前致谢!

//-----------------

HTML 和 CSS

#products display:none
#derecha display:none

<div class="comprar">Clone 1</div> <!--Clone the div from "products" to "derecha"-->

<div class="bbp">X</div> <!--Delete the cloned div placed into "derecha"--> 

SCRIP(播放音频)

let audioHolderComprar = ;
$('.comprar').click(()=>
  let tempIdentifier = Date.now();
  audioHolderComprar[tempIdentifier] = new Audio('comprar.mp3');
  audioHolderComprar[tempIdentifier].play();

  setTimeout(() => 
    delete audioHolderComprar[tempIdentifier];
  , audioHolderComprar[tempIdentifier].duration + 1200);
);

//------------------

let audioHolderBorrar = ;
$('.bbp').click(()=>
  let tempIdentifier = Date.now();
  audioHolderBorrar[tempIdentifier] = new Audio('borrar.mp3');
  audioHolderBorrar[tempIdentifier].play();

  setTimeout(() => 
    delete audioHolderBorrar[tempIdentifier];
  , audioHolderBorrar[tempIdentifier].duration + 1200);
);

【问题讨论】:

我刚刚看了你的笔。实际上,您有两个地方可以处理点击事件。在您的 html 窗格中有 document.addEventListener('click', (event) =&gt; 删除 .bpp 和您在 JS 窗格中定义的单击侦听器,如 $('.bbp').click(()=&gt; 这样您就不会听到声音。也许将它们合二为一? @obscure ...我20天前正在学习JS(你评论的很多脚本不是我的),事实是我没有知道在“.bbp”的点击事件中添加音频的位置 【参考方案1】:

正如我在评论中提到的,您有两个地方可以处理 .bpp 的点击事件 - 它们相互干扰。 此外,您正在混合应该添加 html 和 javascript 代码的地方。虽然有效,但有点乱。

将左侧 HTML 窗格中的所有内容替换为:

<div id="container">
<div id="productos">
            <!-- =============== -->
<div id="cont-p1" class="cont-p">
<div id="producto-1">
<div class="img-prod"><img src="https://upload.wikimedia.org/wikipedia/commons/3/39/Lichtenstein_img_processing_test.png"></div>cont-p1 cloned!<br><br>Input Value = 1</div>

<input class="add-prod" type="num" value="1">

<div class="bbp">X</div></div>

</div> <!-- // productos -->

<div class="derecha" id="derecha"></div> <!-- // div derecha -->

<div id="comp-p1" data-clone="cont-p1" class="comp-clone comprar">Clone 1</div>

<div class="cont-num" id="clicks">0</div>
<div class="cont-num" id="clicksdos">0</div>

<div id="cont-resultado">
<input name="total" id="total">
</div>

  <div id="cont-note">How to play the audio on the button to close the cloned div <span>.bbp</span><br>( <span class="red">X</span> ),<br>if the audio script can not know that it has been cloned...?
<br><br>
Note the CSS (line 3) that the div container of the all div´s that must be cloned is in <span>display=none</span>, but if you comment this line it can reproduce the audio onclick in the X button</div>

</div> <!-- // container -->

以下所有内容都进入右侧的 JS 窗格:

/*
https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js
*/

let audioHolderComprar = ;
$('.comprar').click(()=>
  let tempIdentifier = Date.now();
  audioHolderComprar[tempIdentifier] = new Audio('https://notificationsounds.com/soundfiles/8b16ebc056e613024c057be590b542eb/file-sounds-1113-unconvinced.mp3');
  audioHolderComprar[tempIdentifier].play();

  // removing after play process gets over so if won't consume memory
  setTimeout(() => 
    delete audioHolderComprar[tempIdentifier];
  , audioHolderComprar[tempIdentifier].duration + 1200 /* you can remove threshold value if you wants to */);
);

//------------------

let audioHolderBorrar = ;

let clicks = 0;
let clicksdos = 0;

const safeInt = (key) => 
  let value = parseInt(getValue(key));
  return (isNaN(value) || value < 0) ? 0 : value;


// This loads our clicks from the LocalStorage
const loadClicks = () => 
  clicks = safeInt('clicks');
  clicksdos = safeInt('clicksdos');


const loadHTML = () => 
  return getValue('html', '');


const loadFromStorage = () => 
  let html = loadHTML();
  if (html !== '') 
    loadClicks();
  
  displayClicks();
  document.querySelector(".derecha").innerHTML = html;


// Display the clicks on the screen
const displayClicks = () => 
  clicks = (clicks === NaN) ? 0 : clicks;
  clicksdos = (clicksdos === NaN) ? 0 : clicksdos;
  document.querySelector('#clicks').innerHTML = clicks;
  document.querySelector('#clicksdos').innerHTML = clicksdos;
  // Hide / Show Result 
  let display = (clicks > 0) ? 'block' : 'none';
  document.querySelector('#cont-resultado').style.display = display;
  document.querySelector('.derecha').style.display = display;
  //document.querySelector('#aviso-producto-agregado').style.display = "block";


const adjustClicks = (value) => 
  clicks += value;
  clicksdos += value;
  storeValue('clicks', clicks);
  storeValue('clicksdos', clicksdos);
  displayClicks();

const addClick = () => adjustClicks(1);
const removeClick = () => adjustClicks(-1);


// Manage localStorage
const storeValue = (key, value) => (localStorage) ? localStorage.setItem(key, value) : '';
const getValue = (key, defaultValue) => (localStorage) ? localStorage.getItem(key) : defaultValue;
const storeHTML = () => storeValue("html", document.getElementsByClassName("derecha")[0].innerHTML);

// Add a node to the Derecha
const addToDerecha = (nodeId) => 
  let node = document.querySelector(`#$nodeId`);
  document.querySelector('.derecha').appendChild(node.cloneNode(true));
  storeHTML();
  displaySuma();
;

// Monitor ALL click events 
document.addEventListener('click', (event) => 
  let target = event.target;
  // Add
  if (target.matches('.comp-clone')) 
    addClick();
    addToDerecha(event.target.dataset.clone);
  
  // Remove
  if (target.matches('.bbp')) 
  let tempIdentifier = Date.now();
  audioHolderBorrar[tempIdentifier] = new Audio('https://notificationsounds.com/soundfiles/99c5e07b4d5de9d18c350cdf64c5aa3d/file-sounds-1110-stairs.mp3');
  audioHolderBorrar[tempIdentifier].play();

  // removing after play process gets over so if won't consume memory
  setTimeout(() => 
    delete audioHolderBorrar[tempIdentifier];
  , audioHolderBorrar[tempIdentifier].duration + 1200 /* you can remove threshold value if you wants to */);
    getParent('.derecha', target).removeChild(target.parentNode);
    removeClick();
    storeHTML();
    displaySuma();
  
);

// This is just a helper function.
const getParent = (match, node) => (node.matches(match)) ? node : getParent(match, node.parentNode);

// New Script for sum inputs
//const displaySuma = () => document.getElementById("total").value = suma();
const displaySuma=()=>document.getElementById("total").value=suma().toLocaleString("es-ES");

const suma = function() 
  return Array.from(document.querySelectorAll(".derecha div .add-prod"))
    .reduce((a, v) => a + parseFloat(v.value), 0);


// Code to run when the document loads.
document.addEventListener('DOMContentLoaded', () => 
  if (localStorage) 
    loadFromStorage();
  

  displaySuma();

);
</script>

<script>
  // Displays the new product alert added when the scroll is detected in the div #derecha
  var displaced = document.getElementById('derecha')
      if (displaced.scrollHeight > displaced.offsetHeight) 
      document.getElementById("notice-product-added").style.display = "block";
  ;

  // LocalStorage for the div #notice-product-added
  const showMsgCart=localStorage.getItem('showMsgCarrito');if(showMsgCart==='false')$('#notice-product-added').hide();$('#notice-product-added').on('click',function()$('#notice-product-added').fadeOut('slow');localStorage.setItem('showMsgCarrito','false'););

之后你应该会听到关闭的声音。

【讨论】:

@obscure ... 是的,现在它可以工作了,并且.bbp 音频播放(谢谢),但是当你擦除最后一个克隆的 div 时,会发生一些事情, #derecha div 继续在 display=block 中,并且在删除最后一个克隆的 div 时隐藏了之前的更改 @obscure ...现在效果很好。您错误地删除了第 103 行 (removeClick ();)。谢谢你的时间。 +10! 呵呵,很好,Pablo_Web - 我在你打字的时候修复了我上面的示例代码。我认为 removeClick() 函数的目的是删除点击侦听器,所以我删除了它。对不起! @obscure ...快乐编码!再次感谢。问候

以上是关于Javascript - 仅在 DOM 中可见 div 时播放音频的主要内容,如果未能解决你的问题,请参考以下文章

javascript中获取dom元素高度和宽度

javascript中获取dom元素高度和宽度

JavaScript JavaScript DOM元素可见性检查器

javascript 元素可见DOM

JavaScript DOM元素可见性检查器

如何使用 JavaScript 判断 DOM 对象是不是在窗口外? [复制]