簡體   English   中英

VueJS 砌體布局

[英]VueJS masonry layout

目前,我正在研究 VueJS 項目及其 vue cli 3。我正在嘗試將 MasonryJS 實施到我的 Vue 項目中,但我被卡住了。 我無法理解如何為我的 vue 項目實現這種磚石布局。

 ; (function(window) { /** * GridLoaderFx obj. */ function GridLoaderFx(el, options) { this.el = el; this.items = this.el.querySelectorAll('.grid__item > .grid__link'); } /** * Effects. */ GridLoaderFx.prototype.effects = { 'Shu': { lineDrawing: true, animeLineDrawingOpts: { duration: 800, delay: function(t, i) { return i * 150; }, easing: 'easeInOutSine', strokeDashoffset: [anime.setDashoffset, 0], opacity: [{ value: [0, 1] }, { value: [1, 0], duration: 200, easing: 'linear', delay: 500 } ] }, animeOpts: { duration: 800, easing: [0.2, 1, 0.3, 1], delay: function(t, i) { return i * 150 + 800; }, opacity: { value: [0, 1], easing: 'linear' }, scale: [0.5, 1] } } }; GridLoaderFx.prototype._render = function(effect) { // Reset styles. this._resetStyles(); var self = this, effectSettings = this.effects[effect], animeOpts = effectSettings.animeOpts if (effectSettings.perspective != undefined) { [].slice.call(this.items).forEach(function(item) { item.parentNode.style.WebkitPerspective = item.parentNode.style.perspective = effectSettings.perspective + 'px'; }); } if (effectSettings.origin != undefined) { [].slice.call(this.items).forEach(function(item) { item.style.WebkitTransformOrigin = item.style.transformOrigin = effectSettings.origin; }); } if (effectSettings.lineDrawing != undefined) { [].slice.call(this.items).forEach(function(item) { // Create SVG. var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'), path = document.createElementNS('http://www.w3.org/2000/svg', 'path'), itemW = item.offsetWidth, itemH = item.offsetHeight; svg.setAttribute('width', itemW + 'px'); svg.setAttribute('height', itemH + 'px'); svg.setAttribute('viewBox', '0 0 ' + itemW + ' ' + itemH); svg.setAttribute('class', 'grid__deco'); path.setAttribute('d', 'M0,0 l' + itemW + ',0 0,' + itemH + ' -' + itemW + ',0 0,-' + itemH); path.setAttribute('stroke-dashoffset', anime.setDashoffset(path)); svg.appendChild(path); item.parentNode.appendChild(svg); }); var animeLineDrawingOpts = effectSettings.animeLineDrawingOpts; animeLineDrawingOpts.targets = this.el.querySelectorAll('.grid__deco > path'); anime.remove(animeLineDrawingOpts.targets); anime(animeLineDrawingOpts); } if (effectSettings.revealer != undefined) { [].slice.call(this.items).forEach(function(item) { var revealer = document.createElement('div'); revealer.className = 'grid__reveal'; if (effectSettings.revealerOrigin != undefined) { revealer.style.transformOrigin = effectSettings.revealerOrigin; } if (effectSettings.revealerColor != undefined) { revealer.style.backgroundColor = effectSettings.revealerColor; } item.parentNode.appendChild(revealer); }); var animeRevealerOpts = effectSettings.animeRevealerOpts; animeRevealerOpts.targets = this.el.querySelectorAll('.grid__reveal'); animeRevealerOpts.begin = function(obj) { for (var i = 0, len = obj.animatables.length; i < len; ++i) { obj.animatables[i].target.style.opacity = 1; } }; anime.remove(animeRevealerOpts.targets); anime(animeRevealerOpts); } if (effectSettings.itemOverflowHidden) { [].slice.call(this.items).forEach(function(item) { item.parentNode.style.overflow = 'hidden'; }); } animeOpts.targets = effectSettings.sortTargetsFn && typeof effectSettings.sortTargetsFn === 'function' ? [].slice.call(this.items).sort(effectSettings.sortTargetsFn) : this.items; anime.remove(animeOpts.targets); anime(animeOpts); }; GridLoaderFx.prototype._resetStyles = function() { this.el.style.WebkitPerspective = this.el.style.perspective = 'none'; [].slice.call(this.items).forEach(function(item) { var gItem = item.parentNode; item.style.opacity = 0; item.style.WebkitTransformOrigin = item.style.transformOrigin = '50% 50%'; item.style.transform = 'none'; var svg = item.parentNode.querySelector('svg.grid__deco'); if (svg) { gItem.removeChild(svg); } var revealer = item.parentNode.querySelector('.grid__reveal'); if (revealer) { gItem.removeChild(revealer); } gItem.style.overflow = ''; }); }; window.GridLoaderFx = GridLoaderFx; var body = document.body, grids = [].slice.call(document.querySelectorAll('.grid')), masonry = [], currentGrid = 0, // Switch grid radio buttons. switchGridCtrls = [].slice.call(document.querySelectorAll('.control__radio')), // Choose effect buttons. fxCtrls = [].slice.call(document.querySelectorAll('.control--effects > .control__btn')), // The GridLoaderFx instances. loaders = [], loadingTimeout; function init() { // Preload images imagesLoaded(body, function() { // Initialize Masonry on each grid. grids.forEach(function(grid) { var m = new Masonry(grid, { itemSelector: '.grid__item', columnWidth: '.grid__sizer', percentPosition: true, transitionDuration: 0 }); masonry.push(m); // Hide the grid. grid.classList.add('grid--hidden'); // Init GridLoaderFx. loaders.push(new GridLoaderFx(grid)); }); // Show current grid. grids[currentGrid].classList.remove('grid--hidden'); // Init/Bind events. initEvents(); // Remove loading class from body body.classList.remove('loading'); loaders[currentGrid]._render('Shu'); }); } function initEvents() { // Switching grids radio buttons. switchGridCtrls.forEach(function(ctrl) { ctrl.addEventListener('click', switchGrid); }); // Effect selection. fxCtrls.forEach(function(ctrl) { ctrl.addEventListener('click', applyFx); }); } function applyFx(ev) { // Simulate loading grid to show the effect. clearTimeout(loadingTimeout); grids[currentGrid].classList.add('grid--loading'); loadingTimeout = setTimeout(function() { grids[currentGrid].classList.remove('grid--loading'); // Apply effect. loaders[currentGrid]._render(ev.target.getAttribute('data-fx')); }, 500); } init(); })(window);
 .js .loading::before, .js .loading::after { content: ''; position: fixed; z-index: 1000; } .loading::before { top: 0; left: 0; width: 100%; height: 100%; background: #2c2d31; } .loading::after { top: 50%; left: 50%; width: 40px; height: 40px; margin: -20px 0 0 -20px; border: 8px solid #383a41; border-bottom-color: #565963; border-radius: 50%; animation: animLoader 0.8s linear infinite forwards; } @keyframes animLoader { to { transform: rotate(360deg); } } a { text-decoration: none; color: #f2f2f2; outline: none; } .hidden { position: absolute; overflow: hidden; width: 0; height: 0; pointer-events: none; } /* Icons */ .content--side { position: relative; z-index: 100; width: 15vw; min-width: 130px; max-height: 100vh; padding: 0 1em; order: 2; } .content--center { flex: 1; max-width: 100vw; } .content--related { display: flex; flex-wrap: wrap; justify-content: center; width: 100%; padding: 8em 1em 3em; text-align: center; order: 5; } .media-related { width: 100%; } .media-item { padding: 1em; } .media-item__img { max-width: 100%; /*opacity: 0.7;*/ /*transition: opacity 0.3s;*/ } .media-item:hover .media-item__img, .media-item:focus .media-item__img { opacity: 1; } .media-item__title { font-size: 1em; max-width: 220px; padding: 0.5em; margin: 0 auto; } @keyframes octocat-wave { 0%, 100% { transform: rotate(0); } 20%, 60% { transform: rotate(-25deg); } 40%, 80% { transform: rotate(10deg); } } /* Grid */ .grid { position: relative; z-index: 1; display: block; margin: 2% 5%; } .grid--hidden { position: fixed !important; z-index: 1; top: 0; left: 0; width: 100%; pointer-events: none; opacity: 0; } .js .grid--loading::before, .js .grid--loading::after { content: ''; z-index: 1000; } .js .grid--loading::before { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: #2c2d31; } .js .grid--loading::after { position: absolute; top: calc(25vh - 20px); left: 50%; width: 40px; height: 40px; margin: 0 0 0 -20px; border: 8px solid #383a41; border-bottom-color: #565963; border-radius: 50%; animation: animLoader 0.8s linear forwards infinite; } .grid__sizer { margin-bottom: 0 !important; } .grid__link, .grid__img { display: block; } .grid__img { width: 100%; } .grid__deco { position: absolute; top: 0; left: 0; pointer-events: none; } .grid__deco path { fill: none; stroke: #fff; stroke-width: 2px; } .grid__reveal { position: absolute; z-index: 50; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; opacity: 0; background-color: #2c2d31; } .grid__item {} .grid__item:hover>.cm-pic-author { opacity: 1; } .grid__item:hover>.cm-pic-social { opacity: 1; } .cm-pic-social { transition: opacity 0.6s ease-in-out; position: absolute; right: 10px; top: 10px; opacity: 0; } .cm-pic-social a { color: #ffffff; font-family: 'Roboto', sans-serif; text-shadow: 0 0 2px rgba(0, 0, 0, 0.6); font-size: .9em; text-decoration: none; } .cm-pic-social a:not(:last-child) { margin-right: 1em; } .cm-pic-author { transition: opacity 0.6s ease-in-out; position: absolute; left: 10px; bottom: 10px; opacity: 0; } .cm-pic-author a { font-family: 'Roboto', sans-serif; font-size: .9em; text-decoration: none; color: #ffffff; text-shadow: 0 0 2px rgba(0, 0, 0, 0.6); } .cm-pic-author a img { width: 35px; height: 35px; object-position: center; object-fit: cover; border: 1px solid #ffffff; -webkit-border-radius: 50%; -moz-border-radius: 50%; border-radius: 50%; margin-right: 10px; } .grid .grid__item, .grid .grid__sizer { width: calc(100% - 20px); margin: 0 10px 20px; } @media only screen and (min-width: 576px) { .grid .grid__item, .grid .grid__sizer { width: calc((100% / 2) - 20px); margin: 0 10px 20px; } } /* min-width 1200px, large screens */ @media only screen and (min-width: 1200px) { .grid .grid__item, .grid .grid__sizer { width: calc((100% / 3) - 20px); margin: 0 10px 20px; } } /* min-width 1500px, xlarge screens */ @media only screen and (min-width: 1500px) { /* Grid types */ .grid-masonry .grid__item, .grid-masonry .grid__sizer { width: calc(25% - 20px); margin: 0 10px 20px; } } /* min-width 1800px, xlarge screens */ @media only screen and (min-width: 1800px) { /* Grid types */ .grid-masonry .grid__item, .grid-masonry .grid__sizer { width: calc(20% - 20px); margin: 0 10px 20px; } } /*!* min-width 2400px, xlarge screens 5k*!*/ /*@media only screen and (min-width: 2400px){*/ /*!* Grid types *!*/ /*.grid-masonry .grid__item,*/ /*.grid-masonry .grid__sizer {*/ /*width: calc(16.666666% - 20px);*/ /*margin: 0 10px 20px;*/ /*}*/ /*}*/
 <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/masonry/4.2.2/masonry.pkgd.min.js"></script> <script src="https://unpkg.com/imagesloaded@4/imagesloaded.pkgd.min.js"></script> <div class="content content--center"> <div class="grid grid-masonry"> <div class="grid__sizer"></div> <div class="grid__item"> <a class="grid__link" href="image-details.html"> <img class="grid__img" src="https://i.imgur.com/dCFlYyG.jpg" alt="Some image" /> </a> <div class="cm-pic-social d-flex"> <a href=""><span><img width="16px" src="images/add.svg" alt=""></span> Collection</a> <a href=""><span><img width="16px" src="images/love.svg" alt=""></span> 50</a> </div> <div class="cm-pic-author d-flex"> <a href="personal-profile-follow.html"><img src="images/author@2x.png" alt="">J. Alexa</a> </div> </div> <div class="grid__item"> <a class="grid__link" href="#"><img class="grid__img" src="https://i.imgur.com/Zneml4H.jpg" alt="Some image" /></a> <div class="cm-pic-social d-flex"> <a href=""><span><img width="16px" src="images/add.svg" alt=""></span> Collection</a> <a href=""><span><img width="16px" src="images/love.svg" alt=""></span> 50</a> </div> <div class="cm-pic-author d-flex"> <a href=""><img src="images/author@2x.png" alt="">J. Alexa</a> </div> </div> <div class="grid__item"> <a class="grid__link" href="#"><img class="grid__img" src="https://i.imgur.com/H4bbqpA.jpg" alt="Some image" /></a> <div class="cm-pic-social d-flex"> <a href=""><span><img width="16px" src="images/add.svg" alt=""></span> Collection</a> <a href=""><span><img width="16px" src="images/love.svg" alt=""></span> 50</a> </div> <div class="cm-pic-author d-flex"> <a href=""><img src="images/author@2x.png" alt="">J. Alexa</a> </div> </div> <div class="grid__item"> <a class="grid__link" href="#"><img class="grid__img" src="https://i.imgur.com/9Q9pgmR.jpg" alt="Some image" /></a> <div class="cm-pic-social d-flex"> <a href=""><span><img width="16px" src="images/add.svg" alt=""></span> Collection</a> <a href=""><span><img width="16px" src="images/love.svg" alt=""></span> 50</a> </div> <div class="cm-pic-author d-flex"> <a href=""><img src="https://i.imgur.com/9Q9pgmR.jpg" alt="">J. Alexa</a> </div> </div> <div class="grid__item"> <a class="grid__link" href="#"><img class="grid__img" src="https://picsum.photos/600/800" alt="Some image" /></a> <div class="cm-pic-social d-flex"> <a href=""><span><img width="16px" src="images/add.svg" alt=""></span> Collection</a> <a href=""><span><img width="16px" src="images/love.svg" alt=""></span> 50</a> </div> <div class="cm-pic-author d-flex"> <a href=""><img src="images/author@2x.png" alt="">J. Alexa</a> </div> </div> <div class="grid__item"> <a class="grid__link" href="image-details.html"> <img class="grid__img" src="https://i.imgur.com/dCFlYyG.jpg" alt="Some image" /> </a> <div class="cm-pic-social d-flex"> <a href=""><span><img width="16px" src="images/add.svg" alt=""></span> Collection</a> <a href=""><span><img width="16px" src="images/love.svg" alt=""></span> 50</a> </div> <div class="cm-pic-author d-flex"> <a href="personal-profile-follow.html"><img src="images/author@2x.png" alt="">J. Alexa</a> </div> </div> <div class="grid__item"> <a class="grid__link" href="#"><img class="grid__img" src="https://i.imgur.com/Zneml4H.jpg" alt="Some image" /></a> <div class="cm-pic-social d-flex"> <a href=""><span><img width="16px" src="images/add.svg" alt=""></span> Collection</a> <a href=""><span><img width="16px" src="images/love.svg" alt=""></span> 50</a> </div> <div class="cm-pic-author d-flex"> <a href=""><img src="images/author@2x.png" alt="">J. Alexa</a> </div> </div> <div class="grid__item"> <a class="grid__link" href="#"><img class="grid__img" src="https://i.imgur.com/H4bbqpA.jpg" alt="Some image" /></a> <div class="cm-pic-social d-flex"> <a href=""><span><img width="16px" src="images/add.svg" alt=""></span> Collection</a> <a href=""><span><img width="16px" src="images/love.svg" alt=""></span> 50</a> </div> <div class="cm-pic-author d-flex"> <a href=""><img src="images/author@2x.png" alt="">J. Alexa</a> </div> </div> <div class="grid__item"> <a class="grid__link" href="#"><img class="grid__img" src="https://i.imgur.com/9Q9pgmR.jpg" alt="Some image" /></a> <div class="cm-pic-social d-flex"> <a href=""><span><img width="16px" src="images/add.svg" alt=""></span> Collection</a> <a href=""><span><img width="16px" src="images/love.svg" alt=""></span> 50</a> </div> <div class="cm-pic-author d-flex"> <a href=""><img src="https://i.imgur.com/9Q9pgmR.jpg" alt="">J. Alexa</a> </div> </div> <div class="grid__item"> <a class="grid__link" href="#"><img class="grid__img" src="https://picsum.photos/600/800" alt="Some image" /></a> <div class="cm-pic-social d-flex"> <a href=""><span><img width="16px" src="images/add.svg" alt=""></span> Collection</a> <a href=""><span><img width="16px" src="images/love.svg" alt=""></span> 50</a> </div> <div class="cm-pic-author d-flex"> <a href=""><img src="images/author@2x.png" alt="">J. Alexa</a> </div> </div> </div> </div>

現在我試圖將它實現為一個 vue 組件,以便我可以在任何視圖頁面上呈現。

謝謝

你可以通過 npm 安裝它

npm install masonry-layout --save

然后將其導入您的組件(或全局,如果您願意)

成分

import Masonry from "masonry-layout";

export default {

    mounted: function () {

        // initialization of masonry

        var grid = document.querySelector('.masonry-grid');
        var msnry = new Masonry( grid, {
            // options...
            columnWidth: '.masonry-grid-sizer',
            itemSelector: '.masonry-grid-item',
            percentPosition: true
        });
    }
}

模板

  <template>
   <div>
    <!-- Blog Masonry Blocks -->
    <div class="container ">
        <div class="masonry-grid row ">
            <div class="masonry-grid-sizer col-sm-1"></div>

            <div class="masonry-grid-item col-lg-3">
                ...
            </div>

            <div class="masonry-grid-item col-lg-3">
                ...
            </div>

            <div class="masonry-grid-item col-lg-3">
                ...
            </div>
        </div>
    </div>
  </div>
</template>

嘗試安裝 npm install vue-masonry-css --save-dev 很容易實現。 https://github.com/paulcollett/vue-masonry-css

<masonry
  :cols="3"
  :gutter="30"
  >
  <div v-for="(item, index) in items" :key="index">Item: {{index + 1}}</div>
</masonry>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM