)
前言需要实现一个图片视频的瀑布流效果使用了vue3Masonry库进行实现这是一个关于调用AI提供接口聚合起来再实现一个二次AI的平台效果模板一模板二开始1.安装npm install masonry-layout2.代码1实现script setup langts import { reactive, ref, watch, onMounted, nextTick } from vue; import Masonry from masonry-layout; /** * 图片瀑布流 */ const gridRef ref(null); let msnry null; // 初始化 Masonry const initMasonry async () { console.log(initMasonry); await nextTick(); if (!gridRef.value) return; msnry new Masonry(gridRef.value, { itemSelector: .i-c-card, columnWidth: 224, gutter: 5, fitWidth: false, // 水平排序 horizontalOrder: true, // 取消掉左上角动画 transitionDuration: 0, }); }; // 监听数据变化[更新布局] watch( () dataImgArr.value, async () { await nextTick(); if (msnry) { msnry.reloadItems(); msnry.layout(); } }, { deep: true }, ); // 图片|视频加载好调用msnry.layout const relayout () { if (msnry) { msnry.layout(); } }; // 页面渲染完执行initMasonry onMounted(() { initMasonry(); }); /script template div classmy-container !-- 图片瀑布流 -- div classimg-container scrollhandleScroll div classimg-content refgridRef template v-for(item, key) in dataArr :keyitem.id div classi-c-card refcardRef div styleposition: relative img v-ifitem.chat_type image :srcitem.chat_message[0] altImage loadrelayout / video v-ifitem.chat_type video :srcitem.chat_message[0] loadedmetadatarelayout /video div classi-c-nav-content div style display: flex; justify-content: center; align-items: center; div classlogo img :srcitem.userinfo.avatar alt / /div div classtitle span{{ item.userinfo.nickname }}/span /div /div div v-ifitem.glsquare style display: flex; justify-content: center; align-items: center; div classbtn div classcontent img srcassets/icons/white-watch.svg alt / span{{ item.glsquare.views }}/span /div /div div classbtn stylemargin-left: 10px div classcontent img srcassets/icons/collect.svg alt / span{{ item.glsquare.likes }}/span /div /div /div /div /div div classi-c-nan-title-content v-iffalse div classtitle span{{ item.glsquare.title }}/span /div /div /div /template /div /div !-- end 图片瀑布流 -- /div /template style scoped langscss .img-container { height: calc(100vh - 60px); overflow-y: auto; margin-left: 20px; .img-content { width: 100%; display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 2px; padding: 0px 0px; padding-bottom: 100px; // 滚动条 .ready { opacity: 1; } .i-c-card::after { content: ; position: absolute; inset: 0; background: rgba(0, 0, 0, 0); transition: all 0.25s ease; pointer-events: none; } .i-c-card:hover::after { background: rgba(0, 0, 0, 0.4); } .i-c-card:hover { // transform: translateY(-6px); box-shadow: 0 12px 30px rgba(0, 0, 0, 0.18), 0 4px 10px rgba(0, 0, 0, 0.12); } .i-c-card:hover .i-c-nav-content { z-index: 9; } .i-c-card:hover .i-c-nan-title-content { z-index: 9; } .i-c-card { overflow: hidden; display: flex; flex-direction: column; //width: 100%; width: 224px; // width: calc((100vw - 280px) / 8); border-radius: 8px; margin-bottom: 10px; //background-color: red; //height: auto; img { cursor: pointer; width: 100%; height: auto; display: block; object-fit: cover; } video { cursor: pointer; width: 100%; height: auto; display: block; object-fit: cover; } .i-c-nan-title-content { padding: 10px 20px; display: flex; align-items: center; border: 1px solid rgba(38, 38, 38, 1); border-top: 0; background-color: rgba(23, 23, 23, 1); color: rgba(196, 199, 200, 1); font-size: 12px; .title { width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } } .i-c-nav-content { width: 100%; position: absolute; bottom: 5px; padding: 0px 20px; display: flex; align-items: center; justify-content: space-between; .i-c-n-li { flex: 1; } .logo { width: 24px; img { width: 24px; height: 24px; border-radius: 100%; } } .title { width: 80px; margin-left: 4px; margin-right: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 10px; color: rgba(255, 253, 253, 1); } .btn { //background-color: rgba(217, 217, 217, 0.8); border-radius: 10px; padding: 5px 5px; img { width: 12px; height: 12px; margin-right: 2px; } .content { display: flex; justify-content: center; align-items: center; span { margin-left: 5px; font-size: 14px; } } } } } } media (max-width: 1600px) { .img-content { grid-template-columns: repeat(5, 1fr); } } media (max-width: 1400px) { .img-content { grid-template-columns: repeat(4, 1fr); } } media (max-width: 1100px) { .img-content { grid-template-columns: repeat(3, 1fr); } } media (max-width: 768px) { .img-content { grid-template-columns: repeat(2, 1fr); } } media (max-width: 480px) { .img-content { grid-template-columns: repeat(1, 1fr); } } } /style代码2实现script setup langts import { ref, watch, onMounted, nextTick } from vue; const list ref([ { id: 0, chat_type: image, chat_message: [https://picsum.photos/id/10/1200/675], orientation: 横, }, { id: 1, chat_type: image, chat_message: [https://picsum.photos/id/11/675/1200], orientation: 竖, }, { id: 2, chat_type: image, chat_message: [https://picsum.photos/id/12/1920/1080], orientation: 横, }, { id: 3, chat_type: image, chat_message: [https://picsum.photos/id/13/1080/1920], orientation: 竖, }, { id: 4, chat_type: image, chat_message: [https://picsum.photos/id/14/1440/900], orientation: 横, }, { id: 5, chat_type: image, chat_message: [https://picsum.photos/id/15/900/1440], orientation: 竖, }, { id: 6, chat_type: image, chat_message: [https://picsum.photos/id/16/1600/900], orientation: 横, }, { id: 7, chat_type: image, chat_message: [https://picsum.photos/id/17/900/1600], orientation: 竖, }, { id: 8, chat_type: image, chat_message: [https://picsum.photos/id/18/1280/720], orientation: 横, }, { id: 9, chat_type: image, chat_message: [https://picsum.photos/id/19/720/1280], orientation: 竖, }, { id: 10, chat_type: image, chat_message: [https://picsum.photos/id/20/1920/1080], orientation: 横, }, { id: 11, chat_type: image, chat_message: [https://picsum.photos/id/21/1080/1920], orientation: 竖, }, { id: 12, chat_type: image, chat_message: [https://picsum.photos/id/22/1440/900], orientation: 横, }, { id: 13, chat_type: image, chat_message: [https://picsum.photos/id/23/900/1440], orientation: 竖, }, { id: 14, chat_type: image, chat_message: [https://picsum.photos/id/24/1600/900], orientation: 横, }, { id: 15, chat_type: image, chat_message: [https://picsum.photos/id/25/900/1600], orientation: 竖, }, { id: 16, chat_type: image, chat_message: [https://picsum.photos/id/26/1280/720], orientation: 横, }, { id: 17, chat_type: image, chat_message: [https://picsum.photos/id/27/720/1280], orientation: 竖, }, { id: 18, chat_type: image, chat_message: [https://picsum.photos/id/28/1920/1080], orientation: 横, }, { id: 19, chat_type: image, chat_message: [https://picsum.photos/id/29/1080/1920], orientation: 竖, }, { id: 20, chat_type: image, chat_message: [https://picsum.photos/id/30/1440/900], orientation: 横, }, { id: 21, chat_type: image, chat_message: [https://picsum.photos/id/31/900/1440], orientation: 竖, }, { id: 22, chat_type: image, chat_message: [https://picsum.photos/id/32/1600/900], orientation: 横, }, { id: 23, chat_type: image, chat_message: [https://picsum.photos/id/33/900/1600], orientation: 竖, }, { id: 24, chat_type: image, chat_message: [https://picsum.photos/id/34/1280/720], orientation: 横, }, { id: 25, chat_type: image, chat_message: [https://picsum.photos/id/35/720/1280], orientation: 竖, }, { id: 26, chat_type: image, chat_message: [https://picsum.photos/id/36/1920/1080], orientation: 横, }, { id: 27, chat_type: image, chat_message: [https://picsum.photos/id/37/1080/1920], orientation: 竖, }, { id: 28, chat_type: image, chat_message: [https://picsum.photos/id/38/1440/900], orientation: 横, }, { id: 29, chat_type: image, chat_message: [https://picsum.photos/id/39/900/1440], orientation: 竖, }, ]); const gridRef refHTMLElement | null(null); let msnry: Masonry | null null; import Masonry from masonry-layout; /** 初始化 Masonry */ const initMasonry async () { await nextTick(); if (!gridRef.value) return; msnry new Masonry(gridRef.value, { itemSelector: .i-c-card, gutter: 5, fitWidth: false, horizontalOrder: true, transitionDuration: 0, }); }; /** 重新布局图片/视频加载后调用 */ const relayout () { msnry?.layout(); }; onMounted(initMasonry); // 数据变化后重新计算布局 watch( () list.value, async () { await nextTick(); if (msnry) { msnry.reloadItems(); msnry.layout(); } }, { deep: true }, ); /script template div classimg-container div classimg-content refgridRef template v-foritem in list :keyitem.id div classi-c-card div img v-ifitem.chat_type image :srcitem.chat_message[0] altImage loadrelayout / /div div !--其他元素-- /div /div /template /div /div /template style langscss scoped .img-container { height: calc(100vh - 60px); overflow-y: auto; margin-left: 20px; .img-content { width: 100%; display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 2px; padding: 0px 0px; padding-bottom: 200px; // 滚动条 .i-c-card::after { content: ; position: absolute; inset: 0; background: rgba(0, 0, 0, 0); transition: all 0.25s ease; pointer-events: none; } .i-c-card:hover::after { background: rgba(0, 0, 0, 0.4); } .i-c-card:hover { transform: translateY(-3px); box-shadow: 0 12px 30px rgba(0, 0, 0, 0.18), 0 4px 10px rgba(0, 0, 0, 0.12); } .i-c-card { overflow: hidden; display: flex; flex-direction: column; width: 224px; border-radius: 2px; margin-bottom: 6px; transition: transform 0.3s ease; img { cursor: pointer; width: 100%; height: auto; display: block; object-fit: cover; } } } } /style只能提供大概得代码模板仅供参考总结1.先安装npm install masonry-layout2.查看它的配置参数3.代码实现