【问题标题】:Toggle img src and source srcset when clicked on a picture element单击图片元素时切换 img src 和 source srcset
【发布时间】:2019-12-14 05:57:10
【问题描述】:

纯 JS 问题。

页面加载时,会加载小缩略图(webp 或 jpg)。当单击图像(图片元素)时 - 会发生两件事:图片元素将类更改为大(并且 css 调整它的大小)和小文件的 srcset 字符串被编辑以指向更大的文件('-large.webp'是字符串的结尾)。再次单击图像后,应再次编辑 srcset 字符串以指向小文件('.webp' 应该是字符串的结尾)。然而最后这件事并没有发生,而是 srcset 字符串得到另一个“-large.webp”现在指向一个不存在的文件。

一个页面有很多图像,我只需要在点击时加载大文件。延迟加载没有帮助,因为滚动不是我想要触发它们的事件。

我想我在 if else 循环中的逻辑是错误的......但它可能是别的东西?

任何帮助表示赞赏。

function toggleImages() {
    var images = document.querySelectorAll('figure picture');
    for(var i =0; i< images.length; i++){
        
        images[i].onclick = function() {

            // resize the container 
            this.classList.toggle('thumb');
            this.classList.toggle('large');

            // img and source DOM elements
            var imgtag = this.querySelector('img');
            var sourcetag = this.querySelector('source');
            
            // get urls of small image files
            var thumbsourceJpg = imgtag.getAttribute('src');
            var thumbsourceWebp = sourcetag.getAttribute('srcset');

            // strip the last 4 chars (extension and dot)
            var noJpg = thumbsourceJpg.slice(0,-4);
            var noWebp = thumbsourceWebp.slice(0,-5);
            
            // change ending of urls to point to larger image            
            var largesourceJpg = noJpg + '-large.jpg';
            var largesourceWebp = noWebp + '-large.webp';

            // if srcset points to small file
            if (sourcetag.srcset == thumbsourceWebp) {
                // make it point to a large one
                sourcetag.srcset = largesourceWebp;
                } else {
                    // otherwise point to the small file
                    sourcetag.srcset = thumbsourceWebp;
                }
            
            // do the same for jpgs (this doesnt work at all)
            if (imgtag.src == thumbsourceJpg) {
                imgtag.src = largesourceJpg;
                } else {
                    imgtag.src = thumbsourceJpg;
                }

            }
        
        }
    }
    
window.onload = function() {
toggleImages();

}
figure picture {background: gray;}

figure picture.large{
        width: 608px;
        -moz-transition: all .5s ease;
        -webkit-transition: all .5s ease;
        -o-transition: all .5s ease;
        transition: all .5s ease;  
    }
    
figure picture.thumb {
    width: 180px;
    cursor:pointer;
}
<!DOCTYPE html>
<html>
<body>
<figure>
  <picture class="thumb">
    <source type="image/webp" srcset="https://fokusgrupa.net/files/file1.webp">
    <img src="https://fokusgrupa.net/files/file1.jpg" alt="description">
  </picture>

  <picture class="thumb">
    <source type="image/webp" srcset="https://fokusgrupa.net/files/file2.webp">
    <img src="https://fokusgrupa.net/files/file2.jpg" alt="description">
  </picture>
</figure>
</body>

【问题讨论】:

    标签: javascript html image srcset


    【解决方案1】:

    您实际上是在每次单击图像时将-large 添加到您的路径中。 作为一种解决方案,您可以使用IFEE 将您的图像路径变量存储在外部范围中,这样您就不必每次单击它时都从 html 元素中获取它的值。

    function toggleImages() {
        var images = document.querySelectorAll('figure picture');
        for(var i =0; i< images.length; i++){
            
            images[i].onclick = ((image) => {
                var imgtag = image.querySelector('img');
                var sourcetag = image.querySelector('source');
    
                var thumbsourceJpg = imgtag.getAttribute('src');
                var thumbsourceWebp = sourcetag.getAttribute('srcset');
                
                return function() {
    
                    // resize the container 
                    this.classList.toggle('thumb');
                    this.classList.toggle('large');
    
                    // strip the last 4 chars (extension and dot)
                    var noJpg = thumbsourceJpg.slice(0,-4); // getting from outer scope instead of html element
                    var noWebp = thumbsourceWebp.slice(0,-5);
    
                    // change ending of urls to point to larger image            
                    var largesourceJpg = noJpg + '-large.jpg';
                    var largesourceWebp = noWebp + '-large.webp';
    
                    // if srcset points to small file
                    if (sourcetag.srcset == thumbsourceWebp) {
                        // make it point to a large one
                        sourcetag.srcset = largesourceWebp;
                        } else {
                            // otherwise point to the small file
                            sourcetag.srcset = thumbsourceWebp;
                        }
    
                    // do the same for jpgs (this doesnt work at all)
                    if (imgtag.src == thumbsourceJpg) {
                        imgtag.src = largesourceJpg;
                        } else {
                            imgtag.src = thumbsourceJpg;
                        }
    
                }
            
            })(images[i]);
        }
    }
        
    window.onload = function() {
    toggleImages();
    
    }
    figure picture {background: gray;}
    
    figure picture.large{
            width: 608px;
            -moz-transition: all .5s ease;
            -webkit-transition: all .5s ease;
            -o-transition: all .5s ease;
            transition: all .5s ease;  
        }
        
    figure picture.thumb {
        width: 180px;
        cursor:pointer;
    }
    <!DOCTYPE html>
    <html>
    <body>
    <figure>
      <picture class="thumb">
        <source type="image/webp" srcset="https://fokusgrupa.net/files/file1.webp">
        <img src="https://fokusgrupa.net/files/file1.jpg" alt="description">
      </picture>
    
      <picture class="thumb">
        <source type="image/webp" srcset="https://fokusgrupa.net/files/file2.webp">
        <img src="https://fokusgrupa.net/files/file2.jpg" alt="description">
      </picture>
    </figure>
    </body>

    【讨论】:

    • 感谢@guijob,这很好用:) 但是 jpgs 的问题仍然存在,当我检查代码时,webp 的 url 会随着点击而改变,但 img 不会。对我来说,任何一个的代码看起来都相同,但一个有效,另一个无效。有什么想法吗?
    • @ecvis17,jpgwebpimages 在单击后检查时都很大:&lt;source srcset=".../file1-large.webp"&gt;&lt;img src="..../file1-large.jpg"&gt;.. 只需检查我的 sn-p
    • 所以我将 sn-p (HTML, CSS, JS) 的确切内容复制到我的桌面,但它在那里不起作用。消除了一些问题,我唯一意识到的是,如果 src 字符串包含包含域的绝对路径(例如 example.com/images ...),那么它可以工作。 srcset 正如人们所期望的那样与相对的一起工作,但 src 不是?!?!当然,我所有的内部链接和 src 字符串都是相对的……不是绝对的。 :/ 困惑
    【解决方案2】:

    由于您需要根据单击时srcsrcset 的属性值来切换文件名是否包含“-large”,因此您需要在添加之前检查这些字符串或删除该子字符串。您可以使用URL constructor 和一些基本的字符串操作来处理插入或删除子字符串。

    const toggleURL = (srcset) => {
      const url = new URL(srcset);
      const path = url.pathname.split('/');
      let filename = path[path.length - 1];
      let index = filename.lastIndexOf('-large');
      if (index !== -1) {
        filename = filename.slice(0, index) + filename.slice(index + 6);
      } else {
        index = filename.lastIndexOf('.');
        filename = filename.slice(0, index) + '-large' + filename.slice(index);
      }
      
      path[path.length - 1] = filename;
      url.pathname = path.join('/');
      return url.href;
    };
    
    window.onload = () => {
      const pictures = document.querySelectorAll('figure picture');
      for (const picture of pictures) {
        picture.addEventListener('click', (event) => {
          const pic = event.currentTarget;
          const img = pic.querySelector('img');
          const source = pic.querySelector('source');
          img.src = toggleURL(img.src);
          source.srcset = toggleURL(source.srcset);
          pic.classList.toggle('thumb');
          pic.classList.toggle('large');
        });
      }
    };
    figure picture {
      background: gray;
      cursor: pointer;
    }
    
    figure picture.large {
      width: 608px;
      -moz-transition: all .5s ease;
      -webkit-transition: all .5s ease;
      -o-transition: all .5s ease;
      transition: all .5s ease;
    }
    
    figure picture.thumb {
      width: 180px;
    }
    <figure>
      <picture class="thumb">
        <source type="image/webp" srcset="https://fokusgrupa.net/files/file1.webp">
        <img src="https://fokusgrupa.net/files/file1.jpg" alt="description">
      </picture>
      <picture class="thumb">
        <source type="image/webp" srcset="https://fokusgrupa.net/files/file2.webp">
        <img src="https://fokusgrupa.net/files/file2.jpg" alt="description">
      </picture>
    </figure>

    【讨论】:

    • 感谢 benvc,我看到你在这里制作的代码可以工作,但如果我将它包含在我的文件中,它就不起作用?!您编辑之前的 Previos 版本,产生了一个错误,但现在没有错误,只是没有做任何事情......我做错了什么? :) PS url 并不完全相同,因为这应该适用于不同的目录等。
    • @ecvis17 - 只能猜测您的文件中发生了什么。为什么不在代码中添加一对console.log() 行(可能一个检查单击事件是否正在注册,另一个检查toggleURL() 函数中的return 语句是否在每次单击后返回您期望的url)?
    猜你喜欢
    • 2019-04-04
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    • 2018-03-17
    • 2018-08-09
    相关资源
    最近更新 更多