“我正在参加「初夏创意投稿大赛」详情请看:初夏创意投稿大赛”
前言
夏日是炎热的酷暑,也是激昂的岁月,再有一周,青春的风暴将叩响大学之门,开启异彩纷呈的人生旅途。高考,或许你已经经历过,或许你正要经历,对这批即将登上考场的青春风暴,你是否有些祝福要讲,有些经验要谈,有些过往要忆,有些美好要述,欢迎在评论中表述你的想法和祝福,小包会及时的将你的祝福更新到墙上,同时小包也会将此网页转发给即将高考的伙伴们,更欢迎大家来转发,为高考学子加油助威。
- 码上掘金: code.juejin.cn/pen/7104172…
- 线上地址(暂未布置到国内服务器): 高考祝福墙
创意
妹妹就是今年高考大军中的一员,高考越来越近,压力也日渐增大,小包和家人也承受着同样的紧张。高考并不简单,不只是一场学习的考验,同样是一场勇气与心态的较量,作为加油助威团,小包决定实现祝福墙,为妹妹助威,也为千千万万的高考学子加油助威。
祝福墙中小包加入了很多小心思,下面先跟大家分享一下。
Case1:背景
背景小包选用"一语双关"的方式,选取入学仪式作为背景图: 这既是高中的入学仪式,希望学子们能永远的记住高中的青葱岁月;同样小包希望这也是大学的入学仪式,学子们都如愿以偿,金榜题名。
Case2:七彩祝福语
祝福语的颜色小包想了很久,最终选择了 🌈 的颜色(其中几个颜色稍微变动了一点),🌈是炫彩的,是美丽的,希望年轻的栋梁们都能见识到美丽的彩虹,也能拥有像彩虹一样七彩的大学生活。
Case3:祝福卡片的背景
精挑细选,小包最后选用了五种背景:
- 水流背景: "上善若水,水善利万物而不争",小包希望每位学子考试中,都平静如水,心态称王,顺利完成考试。
- 毕业背景: 夏日的毕业如夏花一般绚烂,夏日的繁星点点也未尝不是每个学子的过往精彩,这个夏天希望可以无怨无悔、快乐无忧的毕业。
- 远航背景: 每个人都是一艘船,你会选择远航吗?你是掌舵人,这由你决定!
- 学习背景: 这个小包没想到好的凝练,意思其实是很简单的,做书的主人,开心快乐的学习,顺利完成学习生活。
- 活力背景: 绿色,意味着生机,意味着活力,新的学子是国家未来发展的活水,希望能在疫情的岁月中注入无尽的活力。绿色,同样意味着未来,高考不是终点,是新的起点。
Case4:祝福者头像
祝福者的头像小包实现了如流水版的动效,希望你们可以感受到祝福的真挚和绵绵的支持。
实现
下面小包来讲一下项目中的亮点和总体实现。
总体设计
祝福墙由多个祝福卡片组成,当打开祝福墙后,根据用户祝福随机生成祝福卡片及其位置。祝福卡片有五种,小包预先写好了五种卡片对应的 CSS 样式,因此进入时只需根据随机生成卡片即可。
Step1: 定义卡片模板生成函数
// 项目虽然有五种模板,单核心只有三种
const hopeTemplate = function (option) {
switch (option.id) {
case 1:
return `<div class="card-wrap">
<div class="card">
<div class="card-content">
<div class="avatar">
<img src="${option.avatar}" alt="" />
</div>
<h4>${option.name}</h4>
<div class="hope">${option.hope}</div>
<div class="img-wrap img-2">
<img src="https://assets.codepen.io/1462889/sea.png" alt="" />
</div>
<div class="img-wrap img-3">
<img src="https://assets.codepen.io/1462889/water.png" alt="" />
</div>
</div>
</div>
</div>`;
case 2:
return `<div class="card-wrap">
<div class="card">
<div class="card-content">
<div class="avatar">
<img src="${option.avatar}" alt="" />
</div>
<h4 class="username">${option.name}</h4>
<div class="hope">${option.hope}</div>
<div class="img-wrap img-2">
<img src="https://assets.codepen.io/1462889/grass.png" alt="" />
</div>
<div class="img-wrap img-5">
<img src="https://assets.codepen.io/1462889/Ivy.png" alt="" />
</div>
</div>
</div>
</div>`;
default:
return `<div class="card-wrap">
<div class="card ${option.class}">
<div class="card-content">
<div class="avatar">
<img src="${option.avatar}" alt="" />
</div>
<h4 class="username">${option.name}</h4>
<div class="hope">${option.hope}</div>
</div>
</div>
</div>`;
}
};
Step2:根据祝福语插入模板
//创建祝福页
let createItem = function (hopeItem) {
// 利用随机数选择模板
const id = randomNtoM(1, 5);
const template = hopeTemplate({ id, ...hopeItem, class: background[id] });
// drag 函数定义了卡片的拖拽
$(template).appendTo(container).drag();
};
Step3: 设置卡片的位置及颜色
const $this = $(this);
const parent = $this.parent();
const hopeColor = randomNtoM(0, 6);
// 设置用户名颜色和祝福语颜色
$(this).find(".hope").css({ color: colors[hopeColor] });
$(this).find("h4").css({ color: "#000" });
const pw = parent.width();
const ph = parent.height();
// 获取卡片位置
const thisWidth =
$this.width() +
parseInt($this.css("padding-left"), 10) +
parseInt($this.css("padding-right"), 10);
const thisHeight =
$this.height() +
parseInt($this.css("padding-top"), 10) +
parseInt($this.css("padding-bottom"), 10);
let x, y, positionX, positionY;
let isDown = false;
// 设置卡片的位置
// 避免卡片显示出界
const randY = parseInt(Math.random() * (ph - thisHeight), 10);
const randX = parseInt(Math.random() * (pw - thisWidth), 10);
// 设置位置
$this.css({
top: randY,
left: randX,
});
动态头像
让头像动起来其实并不难,首先看一下最终的实现效果:
咱们来眨眼补帧一下,可以发现每帧头像都有所差异,但仔细看主要差异就是四周椭圆角的变化。
border-radius 可以来设置圆角,同样也可以来设置椭圆角,例如 border-radius: 30%/70%,则可以实现下图椭圆角效果。(图源: CSS 实现随机不规则圆角头像)
接下来我们借助基于 animation 动画效果,定义多个状态的 border-radius 椭圆角,就可以实现动态的头像效果。
@keyframes border-transform {
0%,
100% {
border-radius: 63% 37% 54% 46% / 55% 48% 52% 45%;
}
14% {
border-radius: 40% 60% 54% 46% / 49% 60% 40% 51%;
}
28% {
border-radius: 54% 46% 38% 62% / 49% 70% 30% 51%;
}
42% {
border-radius: 61% 39% 55% 45% / 61% 38% 62% 39%;
}
56% {
border-radius: 61% 39% 67% 33% / 70% 50% 50% 30%;
}
70% {
border-radius: 50% 50% 34% 66% / 56% 68% 32% 44%;
}
84% {
border-radius: 46% 54% 50% 50% / 35% 61% 39% 65%;
}
}
.card-content .avatar img {
position: absolute;
z-index: 2;
width: 36px;
height: 36px;
display: block;
left: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 6px 20px 0 rgba(16, 39, 112, 0.3);
animation: border-transform 6s linear infinite;
}
拖拽效果
拖拽效果是老生长谈了,通常需要监听三个事件: mousedown、mouseup、mousemove。
Event1:mousedown 事件:
mousedown 事件主要有下面几件事要做:
- 记录鼠标的位置
- 记录卡片的位置
- 增大当前卡片的
zIndex,避免它被遮住 - 加锁
mousedown(function (e) {
// 设置当前卡片zIndex最大
parent.children().css({
zIndex: "0",
});
$this.css({
zIndex: "1",
});
isDown = true;
x = e.pageX;
y = e.pageY;
positionX = $this.position().left;
positionY = $this.position().top;
return false;
});
Event2:mousemove 事件:
mousemove 是拖拽部分的核心,它需要处理:
- 根据新鼠标位置计算卡片新位置,修改卡片的
left与top值 - 判断临界条件,避免卡片移出页面
mousemove(function (e) {
let xPage = e.pageX;
let moveX = positionX + xPage - x;
let yPage = e.pageY;
let moveY = positionY + yPage - y;
if (isDown == true) {
$this.css({
left: moveX,
top: moveY,
});
} else {
return;
}
if (moveX < 0) {
$this.css({
left: "0",
});
}
if (moveX > pw - thisWidth) {
$this.css({
left: pw - thisWidth,
});
}
if (moveY < 0) {
$this.css({
top: "0",
});
}
if (moveY > ph - thisHeight) {
$this.css({
top: ph - thisHeight,
});
}
});
Event3:mouseup 事件:
mouseup 事件就相对简单多了,解锁即可。
mouseup(function (e) {
isDown = false;
});
🧡💛爱心捐助💚💙
昨天是六一儿童节,是全天下儿童的节日,小包不能光顾大朋友,小朋友也应当受到同样的礼待,因此小包将发起爱心捐助活动,小包将同步捐出文章的赞数 * 1 元的爱心金额(学生党,61 封顶,下限 30),希望每个儿童都能拥有幸福、快乐的童年。
后语
我是 战场小包 ,一个快速成长中的小前端,希望可以和大家一起进步。
如果喜欢小包,可以在 掘金 关注我,同样也可以关注我的小小公众号——小包学前端。
一路加油,冲向未来!!!