zoukankan      html  css  js  c++  java
  • vue.js 3.2.20: 用photoswipe实现图片的浏览:增加切换动画和自动播放(photoswipe@4.1.3)

    一,安装photoswipe

    liuhongdi@lhdpc:/data/vue/swipe$ npm i photoswipe --save
    
    up to date in 6s
    
    15 packages are looking for funding
      run `npm fund` for details

    另:photoswipe的官网:

    https://photoswipe.com/

    此demo项目的源码:

    https://gitee.com/liuhongdi/swipe

    说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

             对应的源码可以访问这里获取: https://github.com/liuhongdi/
             或: https://gitee.com/liuhongdi

    说明:作者:刘宏缔 邮箱: 371125307@qq.com 

    二,编写代码:

    1,components/PhotoSwipe.vue

    说明:增加了播放图片的功能

    <template>
      <!-- 这段html代码,是用来显示图片弹出层的,是由photoswipe提供的 -->
      <!-- Root element of PhotoSwipe. Must have class pswp. -->
      <div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
    
        <!-- Background of PhotoSwipe.
             It's a separate element as animating opacity is faster than rgba(). -->
        <div class="pswp__bg"></div>
    
        <!-- Slides wrapper with overflow:hidden. -->
        <div class="pswp__scroll-wrap">
    
          <!-- Container that holds slides.
              PhotoSwipe keeps only 3 of them in the DOM to save memory.
              Don't modify these 3 pswp__item elements, data is added later on. -->
          <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
          </div>
    
          <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
          <div class="pswp__ui pswp__ui--hidden">
    
            <div class="pswp__top-bar">
    
              <!--  Controls are self-explanatory. Order can be changed. -->
    
              <div class="pswp__counter"></div>
    
              <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
    
              <button class="pswp__button pswp__button--share" title="Share"></button>
    
              <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
    
              <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
              <!--
                        <button >放大</button>
                        <button >缩小</button>
                        <button >复原</button>
    
                        <button class="pswp__button" title="play">play</button>
                        -->
              <div style="color:#ffffff;float:right;margin-right:16px;margin-top:14px;" @click="play">
                  <img id="playbutton" src="/static/img/play.png" style="16px;"/>
              </div>
              <!-- Preloader demo https://codepen.io/dimsemenov/pen/yyBWoR -->
              <!-- element will get class pswp__preloader--active when preloader is running -->
              <div class="pswp__preloader">
                <div class="pswp__preloader__icn">
                  <div class="pswp__preloader__cut">
                    <div class="pswp__preloader__donut"></div>
                  </div>
                </div>
              </div>
            </div>
    
            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
              <div class="pswp__share-tooltip"></div>
            </div>
    
            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>
    
            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>
    
            <div class="pswp__caption">
              <div class="pswp__caption__center"></div>
            </div>
    
          </div>
    
        </div>
      </div>
    </template>
    <script>
    //import { getCurrentInstance } from 'vue'
    // 引入photoswipe的js和css文件
    import PhotoSwipe from 'photoswipe/dist/photoswipe'
    import PhotoSwipeUI_Default from 'photoswipe/dist/photoswipe-ui-default'
    import 'photoswipe/dist/photoswipe.css'
    import 'photoswipe/dist/default-skin/default-skin.css'
    
    export default {
      name: 'ZeroPhotoSwipe',
      data:function () {
        return {
           num:123,
           gallery:null,
           isPlaying:false,
           interval:null,
        }
      },
      methods: {
    
        //自动播放执行的内容
        autoplay:function() {
          let _self = this;
          _self.gallery.next();
        },
    
        //停止播放
        stop:function() {
          clearInterval(this.interval);
          this.isPlaying = false;
          this.cleartransition();
          document.getElementById('playbutton').src="/static/img/play.png";
        },
    
        //关闭transition
        cleartransition:function () {
          let containers = document.getElementsByClassName("pswp__container");
          let container = containers[0];
          container.style.transition = '';
        },
    
        //播放图片列表
        play:function() {
          if (this.isPlaying === true) {
              this.stop();
          } else {
              this.isPlaying = true;
              //console.log(this.gallery);
            document.getElementById('playbutton').src="/static/img/stop.png";
              this.interval = setInterval(this.autoplay,2000);
          }
        },
    
       //判断是否移动端的函数
        isMobileFunc:function() {
          let flag = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i);
          if (flag === null) {
            return 0;
          } else {
            return 1;
          }
        },
    
        /**
         * 父组件调用初始化图片弹出层
         * photoswipe提供的方法,这里没有做任何修改,直接拿来用了
         * @param gallerySelector
         */
        initPhotoSwipeFromDOM:function(gallerySelector) {
          let _self = this;
          console.log('_self');
          console.log(_self);
          // parse slide data (url, title, size ...) from DOM elements
          // (children of gallerySelector)
          var parseThumbnailElements = function (el) {
            var thumbElements = el.childNodes,
                numNodes = thumbElements.length,
                items = [],
                figureEl,
                linkEl,
                //divEl,
                size,
                item;
    
            for (var i = 0; i < numNodes; i++) {
    
              figureEl = thumbElements[i]; // <figure> element
    
              // include only element nodes
              if (figureEl.nodeType !== 1) {
                continue;
              }
    
              linkEl = figureEl.children[0]; // <a> element
              //divEl = linkEl.children[0];
    
    
    
              console.log("linkEl:");
              console.log(linkEl);
    
              if(typeof(linkEl)=="undefined"){
                //alert("没有定义");
                //autoAddLine(formId);
                continue;
              }
    
              size = linkEl.getAttribute('data-size').split('x');
    
              console.log("size:w:"+size[0]);
              console.log("size:h:"+size[1]);
    
              let w = window.innerWidth;
              let dest_width = w;
    
               if (size[0] == 10 || size[1] == 10) {
                 let imgEl = linkEl.children[0];
                 let rect = imgEl.getBoundingClientRect();
                 console.log(rect);
    
                 let dest_height = dest_width * rect.height / rect.width;
    
                 size[0] = dest_width;
                 size[1] = dest_height;
    
               } else {
    
                 let dest_height = dest_width * size[1] / size[0];
    
                 size[0] = dest_width;
                 size[1] = dest_height;
               }
    
              console.log('w:'+size[0]+";h:"+size[1]);
              item = {
                src: linkEl.getAttribute('href'),
                w: parseInt(size[0], 10),
                h: parseInt(size[1], 10)
              };
    
              if (figureEl.children.length > 1) {
                // <figcaption> content
                item.title = figureEl.children[1].innerHTML;
              }
    
              if (linkEl.children.length > 0) {
                // <img> thumbnail element, retrieving thumbnail url
                item.msrc = linkEl.children[0].getAttribute('src');
              }
    
              item.el = figureEl; // save link to element for getThumbBoundsFn
              items.push(item);
            }
    
            return items;
          };
    
          // find nearest parent element
          var closest = function closest(el, fn) {
            return el && ( fn(el) ? el : closest(el.parentNode, fn) );
          };
    
          // triggers when user clicks on thumbnail
          var onThumbnailsClick = function (e) {
            e = e || window.event;
            e.preventDefault ? e.preventDefault() : e.returnValue = false;
    
            var eTarget = e.target || e.srcElement;
    
            // find root element of slide
            var clickedListItem = closest(eTarget, function (el) {
              return (el.tagName && el.tagName.toUpperCase() === 'FIGURE');
            });
    
            if (!clickedListItem) {
              return;
            }
    
            // find index of clicked item by looping through all child nodes
            // alternatively, you may define index via data- attribute
            var clickedGallery = clickedListItem.parentNode,
                childNodes = clickedListItem.parentNode.childNodes,
                numChildNodes = childNodes.length,
                nodeIndex = 0,
                index;
    
            for (var i = 0; i < numChildNodes; i++) {
              //console.log("i:"+i);
              //console.log("nodeType:"+childNodes[i].nodeType);
              //console.log(childNodes[i].nodeName);
              if (childNodes[i].nodeType !== 1) {
                continue;
              }
              if (childNodes[i].nodeName !== 'FIGURE') {
                continue;
              }
    
              if (childNodes[i] === clickedListItem) {
                index = nodeIndex;
                break;
              }
              nodeIndex++;
            }
    
    
            if (index >= 0) {
              // open PhotoSwipe if valid index found
              //console.log('begin openPhotoSwipe 1');
    
              //const instance = getCurrentInstance()
              //const _this= instance.appContext.config.globalProperties;
              //console.log('_self:');
              //console.log(_self);
              _self.gallery = openPhotoSwipe(index, clickedGallery);
              //console.log('this gallery');
              //console.log(_self.gallery);
    
              _self.gallery.listen('destroy', function() {
                if (_self.isPlaying) {
                    _self.stop();
                }
                //alert('is destroy');
              });
    
            }
            return false;
          };
    
          // parse picture index and gallery index from URL (#&pid=1&gid=2)
          var photoswipeParseHash = function () {
            var hash = window.location.hash.substring(1),
                params = {};
    
            if (hash.length < 5) {
              return params;
            }
    
            var vars = hash.split('&');
            for (var i = 0; i < vars.length; i++) {
              if (!vars[i]) {
                continue;
              }
              var pair = vars[i].split('=');
              if (pair.length < 2) {
                continue;
              }
              params[pair[0]] = pair[1];
            }
    
            if (params.gid) {
              params.gid = parseInt(params.gid, 10);
            }
    
            return params;
          };
    
          var openPhotoSwipe = function (index, galleryElement, disableAnimation, fromURL) {
    
            console.log('openPhotoSwipe');
    
            var pswpElement = document.querySelectorAll('.pswp')[0],
                gallery,
                options,
                items;
    
            items = parseThumbnailElements(galleryElement);
    
            /*
            *
                getThumbBoundsFn:function(){
                    return {x:$self.left,y:$self.top,w:self[0].naturalWidth};
                    //动画开始时从对应的图片放大到全屏,返回对应图片相对于窗口的实际坐标和自己的宽度
                },
                maxSpreadZoom:2.5,//手势放大图片最大倍数
                allowPanToNext:true,//图片处于放大状态是否允许滑动到下一张
                getDoubleTapZoom:function(){
                    return 1;//双击后图片缩放到的倍数//1表示缩放到原始大小
                },
                loop:false,//滑动到最后一张是否可以继续循环到第一张
                history: false,
                focus: false,
                //closeOnVerticalDrag:false,//垂直拖动图片关闭弹层
                spacing:0.03,
                showAnimationDuration: 430,//显示大图动画时间
                hideAnimationDuration: 430,//隐藏大图动画时间
                showHideOpacity:true,//动画时淡出逐渐变透明
                index: index // 从哪一张图片开始
            * */
    
    
            // define options (if needed)
            options = {
              shareButtons: [
                {id:'wechat', label:'分享微信', url:'#'},
                {id:'weibo', label:'新浪微博', url:'#'},
                {id:'download', label:'保存图片', url:'{{raw_image_url}}', download:true}
              ],
              // define gallery index (for URL)
              galleryUID: galleryElement.getAttribute('data-pswp-uid'),
              maxSpreadZoom:2.5,
              getThumbBoundsFn: function (index) {
                // See Options -> getThumbBoundsFn section of documentation for more info
                var thumbnail = items[index].el.getElementsByTagName('img')[0], // find thumbnail
                    pageYScroll = window.pageYOffset || document.documentElement.scrollTop,
                    rect = thumbnail.getBoundingClientRect();
    
                return {x: rect.left, y: rect.top + pageYScroll, w: rect.width};
              }
    
            };
    
            // PhotoSwipe opened from URL
            if (fromURL) {
              if (options.galleryPIDs) {
                // parse real index when custom PIDs are used
                // http://photoswipe.com/documentation/faq.html#custom-pid-in-url
                for (var j = 0; j < items.length; j++) {
                  if (items[j].pid == index) {
                    options.index = j;
                    break;
                  }
                }
              } else {
                // in URL indexes start from 1
                options.index = parseInt(index, 10) - 1;
              }
            } else {
              options.index = parseInt(index, 10);
            }
    
            // exit if index not found
            if (isNaN(options.index)) {
              return;
            }
    
            if (disableAnimation) {
              options.showAnimationDuration = 0;
            }
    
            //options.
            // Pass data to PhotoSwipe and initialize it
            gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options);
            gallery.init();
            return gallery;
          };
    
          // loop through all gallery elements and bind events
          var galleryElements = document.querySelectorAll(gallerySelector);
    
          for (var i = 0, l = galleryElements.length; i < l; i++) {
            galleryElements[i].setAttribute('data-pswp-uid', i + 1);
            galleryElements[i].onclick = onThumbnailsClick;
          }
    
          // Parse URL and open gallery if it contains #&pid=3&gid=1
          var hashData = photoswipeParseHash();
          if (hashData.pid && hashData.gid) {
            console.log('begin openPhotoSwipe 2');
            _self.gallery = openPhotoSwipe(hashData.pid, galleryElements[hashData.gid - 1], true, true);
            //this.gallery = gallery;
    
            _self.gallery.listen('destroy', function() {
              if (_self.isPlaying) {
                _self.stop();
              }
              //alert('is destroy');
            });
    
          }
        }
      },
    }
    </script>

    2,components/Home.vue

    <template>
      <div>
        <zero-photo-swipe ref="zeroPhoto"></zero-photo-swipe>
        <div class="my-gallery">
    
          <figure style="float:left;margin-inline-start:0px;margin-inline-end:0px;">
            <a href="/static/img/b.jpg" data-size="10x10">
              <img @mouseover="imgMouseOver(1)"  id="img1" src="/static/img/b.jpg"  style="max-100%;float:left;height:250px;border-radius: 5px;"  v-on:load="loadImgSize($event)"/>
              <div id="mask1" @mouseout="imgMouseOut(1)" style="display:none;100%;height:100%;background: #ffffff;opacity: 0.4;position: absolute;top:0px;left: 0px;">
                  <img id="mag1" src="@/assets/img/mag.png" style="60px;height:60px;"/>
              </div>
            </a>
          </figure>
          <!--<div style="30px;height:100px;margin-left:30px;float:left;background: #ff0000;"></div>-->
          <figure style="float:left;margin-inline-start:0px;margin-inline-end:0px;">
            <a href="/static/img/c.jpg" data-size="10x10">
              <img @mouseover="imgMouseOver(2)"  id="img2" src="/static/img/c.jpg" style="max-100%;float:left;height:250px;margin-left: 20px;border-radius: 5px;"  v-on:load="loadImgSize($event)"/>
              <div id="mask2" @mouseout="imgMouseOut(2)" style="display:none;100%;height:100%;background: #ffffff;opacity: 0.4;position: absolute;top:0px;left: 0px;">
                <img id="mag2" src="@/assets/img/mag.png" style="60px;height:60px;"/>
              </div>
            </a>
          </figure>
          <figure style="float:left;margin-inline-start:0px;margin-inline-end:0px;">
            <a href="/static/img/tbh.jpeg" data-size="10x10">
              <img @mouseover="imgMouseOver(3)"  id="img3" src="/static/img/tbh.jpeg" style="max-100%;float:left;height:250px;margin-left: 20px;border-radius: 5px;"  v-on:load="loadImgSize($event)"/>
              <div id="mask3" @mouseout="imgMouseOut(3)" style="display:none;100%;height:100%;background: #ffffff;opacity: 0.4;position: absolute;top:0px;left: 0px;">
                <img id="mag3" src="@/assets/img/mag.png" style="60px;height:60px;"/>
              </div>
            </a>
          </figure>
    
          <figure style="float:left;margin-inline-start:0px;margin-inline-end:0px;">
            <a href="/static/img/qx.jpeg" data-size="10x10">
              <img @mouseover="imgMouseOver(4)"  id="img4" src="/static/img/qx.jpeg" style="max-100%;float:left;height:250px;margin-left: 20px;border-radius: 5px;"  v-on:load="loadImgSize($event)"/>
              <div id="mask4" @mouseout="imgMouseOut(4)" style="display:none;100%;height:100%;background: #ffffff;opacity: 0.4;position: absolute;top:0px;left: 0px;">
                <img id="mag4" src="@/assets/img/mag.png" style="60px;height:60px;"/>
              </div>
            </a>
          </figure>
    
          <figure style="float:left;margin-inline-start:0px;margin-inline-end:0px;">
            <a href="/static/img/lb.jpeg" data-size="10x10">
              <img @mouseover="imgMouseOver(5)"  id="img5" src="/static/img/lb.jpeg" style="max-100%;float:left;height:250px;margin-left: 20px;border-radius: 5px;"  v-on:load="loadImgSize($event)"/>
              <div id="mask5" @mouseout="imgMouseOut(5)" style="display:none;100%;height:100%;background: #ffffff;opacity: 0.4;position: absolute;top:0px;left: 0px;">
                <img id="mag5" src="@/assets/img/mag.png" style="60px;height:60px;"/>
              </div>
            </a>
          </figure>
          
          <figure style="float:left;margin-inline-start:0px;margin-inline-end:0px;">
            <a href="/static/img/gy.jpeg" data-size="10x10">
              <img @mouseover="imgMouseOver(6)"  id="img6" src="/static/img/gy.jpeg" style="max-100%;float:left;height:250px;margin-left: 20px;border-radius: 5px;"  v-on:load="loadImgSize($event)"/>
              <div id="mask6" @mouseout="imgMouseOut(6)" style="display:none;100%;height:100%;background: #ffffff;opacity: 0.4;position: absolute;top:0px;left: 0px;">
                <img id="mag6" src="@/assets/img/mag.png" style="60px;height:60px;"/>
              </div>
            </a>
          </figure>
    
        </div>
      </div>
    </template>
    <script>
    import ZeroPhotoSwipe from "../components/PhotoSwipe.vue";
    export default {
      name: 'Gallery',
      components: {
        ZeroPhotoSwipe
      },
    
      mounted(){
        // 调用初始化图片photoswipe
        this.$refs.zeroPhoto.initPhotoSwipeFromDOM('.my-gallery')
      },
      methods:{
        /**
         * 加载图片结束时自动添加photoswipe需要的data-size
         * @param e
         */
        loadImgSize(e) {
          var target = e.currentTarget
          var x = target.clientWidth
          var y = target.clientHeight
    
          target.dataSize = `${x}x${y}`
          target.parentNode.setAttribute('data-size', `${x}x${y}`)
        },
        imgMouseOver(id) {
          //alert(id);
          //let idmask="mask"+id;
          let rect = document.getElementById("img"+id).getBoundingClientRect();
          console.log(rect);
    
          let mask = document.getElementById("mask"+id);
          mask.style.left = rect.left +'px';
          mask.style.top = rect.top +'px';
          mask.style.width = rect.width +'px';
          mask.style.height = rect.height +'px';
          //mask.style.lineHeight = rect.height +'px';
    
          let mag = document.getElementById("mag"+id);
          mag.style.marginTop = (rect.height-60)/2 +'px';
          mask.style.display = "";
        },
        imgMouseOut(id) {
          let mask = document.getElementById("mask"+id);
          mask.style.display = "none";
        },
      }
    }
    </script>

    三,修改photoswipe.js的代码

    说明:主要是为了切换图片时的动画效果:

    只修改next()和prev()两个方法即可

        next: function() {
            console.log('next');
            let tf = self.container.style.transform;
            //设置目标位置
            let  arr1 = tf.split("(");
            let str1 = arr1[1];
            //console.log("str1:"+str1);
            let arr2 = str1.split("px");
            let curleft = arr2[0];
    
            let w = _slideSize.x;
            let dest_left = parseInt(curleft)-w;
            self.container.style.transform = 'translate3d(' + dest_left + 'px, 0px, 0px)';
            self.container.style.transition = 'all 0.5s ease-in-out';
            setTimeout(function(){
                console.log('setTimeout begin');
                self.container.style.transition = 'all 0s ease-in-out';
                self.goTo( _currentItemIndex + 1);
            },550);
        },
        prev: function() {
            console.log('prev');
    
            let tf = self.container.style.transform;
            //设置目标位置
            let  arr1 = tf.split("(");
            let str1 = arr1[1];
            //console.log("str1:"+str1);
            let arr2 = str1.split("px");
            let curleft = arr2[0];
    
            let w = _slideSize.x;
            console.log("curleft:"+curleft+";w:"+w);
            let dest_left = parseInt(curleft)+w;
            console.log("dest_left:"+dest_left);
            self.container.style.transform = 'translate3d(' + dest_left + 'px, 0px, 0px)';
            self.container.style.transition = 'all 0.5s ease-in-out';
            setTimeout(function(){
                console.log('setTimeout begin');
                self.container.style.transition = 'all 0s ease-in-out';
                 self.goTo( _currentItemIndex - 1);
            },550);
    
        },

    四,查看效果:

    五,查看版本:

    查看vue的版本:
    liuhongdi@lhdpc:/data/vue/swipe$ npm list vue
    swipe@0.1.0 /data/vue/swipe
    ├─┬ @vue/cli-plugin-babel@4.5.13
    │ └─┬ @vue/babel-preset-app@4.5.13
    │   └── vue@3.2.20 deduped
    └─┬ vue@3.2.20
      └─┬ @vue/server-renderer@3.2.20
        └── vue@3.2.20 deduped
    查看photoswipe的版本:
    liuhongdi@lhdpc:/data/vue/swipe$ npm list photoswipe
    swipe@0.1.0 /data/vue/swipe
    ├── photoswipe@4.1.3 
  • 相关阅读:
    dll反编译工具(ILSpy)的使用
    织梦CMS进入自定义表单界面查看数据
    SQL -注释方法
    SQL之CASE WHEN用法详解
    Windows Installer Clean Up 软件卸载工具下载
    【精华合辑】金蝶云BOS资料合辑
    报表二次开发添加自定义字段的指导方案
    怎样选购笔记本内存条?
    SQL Server 2008修改sa密码的详细方法
    VS 2015 2019注册码
  • 原文地址:https://www.cnblogs.com/architectforest/p/15424812.html
Copyright © 2011-2022 走看看