学习风`宇blog
- flex布局使用百分比作2栏网格布局,内部也是使用flex布局做左图右文
- 使用IntersectionObserver这个浏览器提供的Api,配合vue指令,当元素出现在可视区时,添加上移的动画效果。注意:元素的初始状态,是visibility:hidden隐藏状态的,然后达到可视区时,通过添加类名的方式,来指定动画和让visibility:visible可见。
- 图片也是通过el.getBoundingClientRect()这个api,配合vue指令,在bind初始化时候,就把src给换成data-src,src使用默认图片,然后,在inserted时,作第一次图片加载(有可能图片在未滚动时就已经在可视区了),并且监听滚动事件,当图片出现在可视区时,再把data-src的值给src
- 向下加载更多效果
<style lang="scss">
/* 封面图下移效果 */
@keyframes slidedown {
0% {
opacity: 0.3;
transform: translateY(-60px);
}
100% {
opacity: 1;
transform: translateY(0px);
}
}
.slidedown {
animation: slidedown 1s;
}
/* 内容上移效果 */
@keyframes slideup {
0% {
opacity: 0.3;
transform: translateY(60px);
}
100% {
opacity: 1;
transform: translateY(0px);
}
}
.slideup {
animation: slideup 1s;
}
/* 旋转加载效果 */
@keyframes spinLoading {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
.spinLoading {
animation: spinLoading 1s infinite;
}
.banner {
height: 400px;
background-image: url(@/assets/bg4.jpg);
background-size: cover;
background-position: center;
position: relative;
color: #eee;
.banner-content {
position: absolute;
bottom: 25%;
width: 100%;
text-align: center;
text-shadow: 0.05rem 0.05rem 0.1rem rgb(0 0 0 / 30%);
height: 108px;
font-size: 30px;
letter-spacing: 0.3em;
}
}
* {
box-sizing: border-box;
}
a {
text-decoration: none;
color: inherit;
}
p {
margin: 0;
}
@keyframes slideUpBigIn {
0% {
transform: translateY(40px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
.aniSlideUpBigIn {
animation: slideUpBigIn 1s;
visibility: visible !important;
}
.friend-link-wrapper {
display: flex;
// border: 1px solid red;
max-width: 1200px;
margin: 40px auto;
padding: 40px 30px;
border-radius: 10px;
.description {
flex-grow: 1;
line-height: 2em;
h1 {
margin: 0 20px;
margin-left: 40px;
font-weight: bold;
font-size: 20px;
position: relative;
&::before {
content: '\e888';
font-family: "iconfont";
font-weight: normal;
color: #49b1f5;
position: absolute;
left: -1.5em;
}
}
.welcome {
margin: 0 60px;
position: relative;
&::before {
content: '';
position: absolute;
width: 5px;
height: 5px;
background-color: red;
top: 1em;
left: -0.7em;
border-radius: 50%;
}
}
blockquote {
background-color: #daefff;
border-left: 4px solid #3cc1ff;
border-radius: 5px;
padding: 5px 10px;
}
}
.friends {
display: flex;
flex-wrap: wrap;
padding: 20px 40px;
.friend {
width: calc(50% - 20px);
display: flex;
margin: 10px;
border-radius: 10px;
box-shadow: 0 2px 8px 0px rgba(0, 0, 0, 0.08);
visibility: hidden;
.fl-avatar {
width: 100px;
height: 100px;
border-radius: 5px;
overflow: hidden;
margin-right: 10px;
padding: 10px;
img {
height: 100%;
width: 100%;
object-fit: cover;
border-radius: 5px;
transition: all 0.3s;
&:hover {
transform: scale(1.2);
}
}
}
.fl-info {
flex: 1;
padding-top: 8px;
padding-right: 10px;
// overflow: hidden;
a {
display: block;
color: #5abdff;
font-weight: bold;
margin-bottom: 6px;
}
p {
font-size: 14px;
color: #3e3e3e;
line-height: 1.3;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
word-break: break-all;
}
}
}
}
.load-more {
text-align: center;
color: #3e3e3e;
.more-again {
.loading-text {
cursor: pointer;
color: #5abdff;
i {
font-size: 12px;
}
}
.loading-ani {
display: flex;
color: #3e3e3e;
align-items: center;
justify-content: center;
.loading-icon {
i {
display: block;
width: 2em;
height: 2em;
font-size: 1.6em;
// border: 1px solid red;
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
.no-more {
color: #ccc;
user-select: none;
}
}
}
</style>
<template>
<div>
<navbar />
<div class="banner slidedown">
<div style="position: absolute;top: 0;left: 0;width: 100%;height: 100%;backdrop-filter: blur(5px);"></div>
<div class="banner-content">
<div>友情链接</div>
</div>
</div>
<div class="friend-link-wrapper shadow slideup">
<div class="description">
<h1>本站信息</h1>
<blockquote>
<p>名称: Halo world</p>
<p>简介: 热爱技术一点点的学习</p>
<p>头像: http://xxxx</p>
</blockquote>
<h1>申请方法</h1>
<p class="welcome">需要交换友链的可在本页留言</p>
<blockquote>
处于信息需要,大佬你的信息格式要包含:网站名称、网站链接、头像链接、网站介绍、名称颜色
</blockquote>
<h1>小伙伴们</h1>
<div>
<div class="friends">
<div class="friend" v-slideUp>
<a href="#" class="fl-avatar">
<img v-lazy1 style="" src="@/assets/fl/fl1.png" alt="">
</a>
<div class="fl-info">
<a href="#" class="fl-link">冰箱主人のBlog</a>
<p>冰箱里什么都没有呢</p>
</div>
</div>
<div class="friend" v-slideUp>
<a href="#" class="fl-avatar">
<img v-lazy1 style="" src="@/assets/fl/fl2.png" alt="">
</a>
<div class="fl-info">
<a href="#" class="fl-link">優萌初華</a>
<p>琉璃的医学 & 编程笔记</p>
</div>
</div>
<div class="friend" v-slideUp>
<a href="#" class="fl-avatar">
<img v-lazy1 style="" src="@/assets/fl/fl3.png" alt="">
</a>
<div class="fl-info">
<a href="#" class="fl-link">Sady'Blog</a>
<p>永远年轻,永远热泪盈眶.</p>
</div>
</div>
<div class="friend" v-slideUp>
<a href="#" class="fl-avatar">
<img v-lazy1 style="" src="@/assets/fl/fl4.png" alt="">
</a>
<div class="fl-info">
<a href="#" class="fl-link">漫漫</a>
<p>漫漫即慢慢啊~</p>
</div>
</div>
<div class="friend" v-slideUp>
<a href="#" class="fl-avatar">
<img v-lazy1 style="" src="@/assets/fl/fl5.png" alt="">
</a>
<div class="fl-info">
<a href="#" class="fl-link">2T的固态</a>
<p>DaVan的个人博客</p>
</div>
</div>
<div class="friend" v-slideUp>
<a href="#" class="fl-avatar">
<img v-lazy1 style="" src="@/assets/fl/fl6.png" alt="">
</a>
<div class="fl-info">
<a href="#" class="fl-link">八尺妖剑</a>
<p>惟有热爱,可抵岁月漫长!</p>
</div>
</div>
<div class="friend" v-slideUp>
<a href="#" class="fl-avatar">
<img v-lazy1 style="" src="@/assets/fl/fl7.png" alt="">
</a>
<div class="fl-info">
<a href="#" class="fl-link">花未眠的个人博客</a>
<p>一个疯狂的coder</p>
</div>
</div>
<div class="friend" v-slideUp>
<a href="#" class="fl-avatar">
<img v-lazy1 style="" src="@/assets/fl/fl8.png" alt="">
</a>
<div class="fl-info">
<a href="#" class="fl-link">Big_fw</a>
<p>Try the best</p>
</div>
</div>
<div class="friend" v-slideUp>
<a href="#" class="fl-avatar">
<img v-lazy1 style="" src="@/assets/fl/fl9.png" alt="">
</a>
<div class="fl-info">
<a href="#" class="fl-link">皮皮龙</a>
<p>一位无所事事的大学码农</p>
</div>
</div>
<div class="friend" v-slideUp>
<a href="#" class="fl-avatar">
<img v-lazy1 style="" src="@/assets/fl/fl10.png" alt="">
</a>
<div class="fl-info">
<a href="#" class="fl-link">忻辰</a>
<p>忻辰</p>
</div>
</div>
<div class="friend" v-for="friend, idx in friendList" :key="idx" v-slideUp>
<a href="#" class="fl-avatar">
<img v-lazy1 style="" :src="friend.avatar" alt="">
</a>
<div class="fl-info">
<a href="#" class="fl-link">{{ friend.name }}</a>
<p>{{ friend.bio }}</p>
</div>
</div>
</div>
<div class="load-more">
<div v-show="hasMore" class="more-again">
<div v-show="!isLoading" class="loading-text" @click="loadMore">
加载更多 <i class="iconfont icon-gengduo"></i>
</div>
<div v-show="isLoading" class="loading-ani">
<span class="loading-icon spinLoading">
<i class="iconfont icon-jiazai"></i>
</span>
</div>
</div>
<div v-show="!hasMore" class="no-more">
已经到底了~
</div>
</div>
</div>
</div>
</div>
<Footer></Footer>
</div>
</template>
<script>
import Navbar from '@/views/Navbar'
import Footer from '@/views/Footer'
let img1 = require('@/assets/fl/fl1.png')
export default {
name: 'FriendLink',
methods: {
showInfo(e) {
alert('同学你好!')
// console.log(e.target)
}, showMsg(msg) {
console.log(msg)
},
},
data() {
return {
hasMore: true,
isLoading: false,
loadingCount: 0,
friendList: []
}
},
methods: {
loadMore() {
this.isLoading = true
if (this.loadingCount <= 2) {
this.loadingCount++
setTimeout(() => {
this.isLoading = false
this.friendList.push(
{
name: 'pscool',
bio: '热爱技术,一点点的学习1',
avatar: img1
},
{
name: 'pscool2',
bio: '热爱技术,一点点的学习2',
avatar: img1
},
{
name: 'pscool3',
bio: '热爱技术,一点点的学习3',
avatar: img1
},
{
name: 'pscool4',
bio: '热爱技术,一点点的学习4',
avatar: img1
}
)
if(this.loadingCount == 2) {
this.hasMore = false
}
}, 1500)
}
}
},
directives: {
slideUp: {
inserted(el, binding) {
let observer = new IntersectionObserver((entries) => {
for (let entry of entries) {
if (entry.isIntersecting) {
console.log('出现。。。');
el.classList.add('aniSlideUpBigIn');
observer.unobserve(el)
}
}
}, { threshold: 0.5 })
observer.observe(el)
}
}
},
components: {
Navbar, Footer
}
}
</script>