大家好,我是寒草😈,一只草系码猿🐒。间歇性热血🔥,持续性沙雕🌟
如果喜欢我的文章,可以关注➕ 点赞,与我一同成长吧~
微信:hancao97,加我微信免费看前端早早聊 10.23 日vue
专场直播
小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
前奏 🎵
前几天在知乎看到了一些代码情书,就像这种:
#倘若你回首看看我
ifyou.turn_round_aguang()
#我永远在你背后
I.behind(you).forever()
#关注着你
see(you)
其实萌生了总结前端示爱方式的想法,可是看了半天,觉得也就普普通通,甚至有很多示爱小程序给我一种 2000 年代的感觉,比如这个:
于是我就有了一个想法,自己动手做一个,寒草设计并动手实现的前端工程师特制。
间奏 🎵
本章涵盖以下内容:
- 从效果看设计
- 讲述效果的实现方式
下面,我们开始本文的主要内容。
设计 🤔
页面分为两部分:
- 左侧的类终端窗口
- 右侧的效果显示区
类终端窗口:
- 要有彩蛋
- 要和右侧效果区呼应
效果显示区:
- 倒计时 ⏰
- 心 ❤️
- 奇特的弹幕 📖
- 月亮 🌛
- 雨落在水面的涟漪 🌧️
- 彩色的雨 🌈
开发 😪
将事件串联起来 —— Deferred
首先,我需要把事件串联起来,而这个动画中的事件比较复杂,需要把这些事件串联起来,总不能用 setTimeout 回调函数进行嵌套,那样会十分恶心并且不利于管理,于是我使用了 Deferred:
function Deferred() {
if (typeof (Promise) != 'undefined' && Promise.defer) {
return Promise.defer();
} else if (this && this instanceof Deferred) {
this.resolve = null;
this.reject = null;
const _this = this;
this.promise = new Promise((resolve, reject) => {
_this.resolve = resolve;
_this.reject = reject;
});
Object.freeze(this);
} else {
throw new Error();
}
}
说白了就是把 promise 中的 resolve 和 reject 拿出来,用了之后我这套事件顺序就会比较连贯:
stepWord('致 9.15', 'rgb(228, 231, 12)')
.then(() => stepWord('开始倒计时', '#c1e8fa'))
.then(() => stepWord('start the countdown', '#db61ac'))
.then(() => stepSpace())
.then(() => stepWord('🌟🌟🌟🌟🌟🌟'))
.then(() => stepSpace())
.then(() => stepTime())
.then(() => stepWord('心跳加速,藏獒开始进化', '#c1e8fa'))
.then(() => stepWord('The heart rate quickens and the Tibetan mastiff begins to evolve.', '#db61ac'))
.then(() => stepSpace())
.then(() => stepWord('🐶🐶🐶🐶🐶🐶'))
.then(() => stepSpace())
.then(() => stepDown())
.then(() => stepWord('致 9.21', 'rgb(228, 231, 12)'))
.then(() => stepWord('但愿人长久,千里共婵娟', '#c1e8fa'))
.then(() => stepWord('you are my fairy forever', 'red'))
.then(() => stepSpace())
.then(() => stepWord('🌛🌛🌛🌛🌛🌛'))
.then(() => stepSpace())
.then(() => stepMoon())
.then(() => stepWord('大崽崽', '#c1e8fa'))
.then(() => stepWord('big zaizai', '#db61ac'))
.then(() => stepSpace())
.then(() => stepWord('☀️☀️☀️☀️☀️☀️'))
.then(() => stepSpace())
.then(() => stepRemove())
.then(() => stepWord('但盼风雨来,能留你在此', '#c1e8fa'))
.then(() => stepWord("Don't leave me!", '#db61ac'))
.then(() => stepSpace())
.then(() => stepWord('🌧️🌧️🌧️🌧️🌧️🌧️'))
.then(() => stepSpace())
.then(() => stepRain())
.then(() => stepWord('留你在此,赏彩色的雨', '#c1e8fa'))
.then(() => stepWord("I'll create more surprises for you", 'red'))
.then(() => stepSpace())
.then(() => stepWord('🌈🌈🌈🌈🌈🌈'))
.then(() => stepColorFulRain())
.then(() => stepHanzi())
从前到后一口气写下来,为后面的一大串动画衔接做了铺垫。
终端文案统一处理方法 —— stepWord & stepSpace
stepWord 方法可以配置终端的文案和字体颜色
function stepWord(str, color) {
const step = str;
const deferred = new Deferred();
const len = step.length;
let site = 0;
content.appendChild(document.createElement('div'));
const child = content.children[content.children.length - 1];
if (color) {
child.style.color = color;
}
const timer = setInterval(() => {
child.innerHTML = step.slice(0, site + 1);
if (site == len) {
clearInterval(timer);
deferred.resolve();
} else {
site++;
}
}, 100)
return deferred.promise;
}
stepSpace 方法可以加入空白行
function stepSpace() {
content.appendChild(document.createElement('br'));
return Promise.resolve();
}
倒计时 —— stepTime
很简单的替换 dom 元素的内容,并让文字颜色逐渐加深。
function stepTime() {
const deferred = new Deferred();
const time = document.getElementsByClassName('time')[0];
time.style.opacity = 1;
const number = time.children[3];
const list = ['二', '三', '四', '五'];
let site = 0;
const timer = setInterval(() => {
if (site == list.length) {
document.getElementsByClassName('heart')[0].style.opacity = 1;
clearInterval(timer);
time.style.opacity = 0;
deferred.resolve();
} else {
number.innerHTML = list[site];
number.style.color = `rgba(233, 62, 59, ${(site + 2) * 0.2})`;
site++;
}
}, 1000)
return deferred.promise;
}
彩色的雨 —— stepColorFulRain
这里其实这个涟漪的扩散就是简单的帧动画,之后通过 js 在随机位置生成 dom 元素。
css
@keyframes rain {
from {
transform: scale(1, 1);
opacity: 1;
}
50% {
opacity: 1;
}
to {
transform: scale(100, 100);
opacity: 0;
}
}
.rain {
height: 3px;
width: 3px;
background: radial-gradient(rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.1), rgba(0, 0, 0, 0.3));
border-radius: 50%;
transform-origin: 50% 50%;
opacity: 0;
animation: rain 5s linear;
position: absolute;
z-index: 999;
}
js
function stepColorFulRain() {
const deferred = new Deferred();
view.style.background = '#0E2744';
view.style.overflow = 'auto';
function Rain() {
this.rain = document.createElement('div');
this.rain.className = 'rain';
this.rain.style.top = Math.random() * window.innerHeight * 0.9 + 0.1 * window.innerHeight + 'px';
this.rain.style.left = Math.random() * window.innerWidth * 0.9 + 0.1 * window.innerWidth + 'px';
this.rain.style.background = `radial-gradient(rgba(255, 255, 255, 0.1), rgba(${Math.random() * 155 + 100}, ${Math.random() * 155 + 100}, ${Math.random() * 155 + 100}, 0.5))`;
this.rain.style.animation = 'rain 6s linear'
document.body.appendChild(this.rain);
const timer2 = setTimeout(() => {
clearTimeout(timer2);
document.body.removeChild(this.rain);
}, 6000)
}
let starTimer = setInterval(() => {
new Rain();
}, 300)
setTimeout(() => {
deferred.resolve();
}, 2000)
return deferred.promise;
}
其他的代码
其他的代码都是很简单的 css。
其中这个心形的背景用到了 codepen 的 心❤️
文案彩蛋
致 9.15
开始倒计时
start the countdown
🌟🌟🌟🌟🌟🌟
心跳加速,藏獒开始进化
The heart rate quickens and the Tibetan mastiff begins to evolve.
🐶🐶🐶🐶🐶🐶
致 9.21
但愿人长久,千里共婵娟
you are my fairy forever
🌛🌛🌛🌛🌛🌛
大崽崽
big zaizai
☀️☀️☀️☀️☀️☀️
但盼风雨来,能留你在此
Do not leave me!
🌧️🌧️🌧️🌧️🌧️🌧️
留你在此,赏彩色的雨
I will create more surprises for you
🌈🌈🌈🌈🌈🌈
寒草的示爱宣言 📖
本章的图片来自电影《侧耳倾听》
因为你,我愿意成为一个更好的人,不想成为你的包袱,因此发奋努力,只是为了想要证明我足以与你相配。
其实小的时候就会被无数作品塑造爱情观,无论是《数码宝贝3》中懵懂的喜欢,启人为救出树莉与基尔兽进化为真红莲形态的红莲骑士兽,还是《食梦者》中各自约定「完成梦想就结婚」后各自的努力拼搏(现实不要这样,否则...我国结婚率又要...),再到最近看《侧耳倾听》中上面的那句话,在我眼里都十分美好而纯粹。
我曾陷入迷茫困惑,也曾陷入焦虑不安,不停的向前,却不知路在何方,被琐事与噩梦缠身又无法自拔。
而现在,距离 2021 年结束还有 84 天,距离新的五年,新的十年规划开启还有 84 天,可以斩旧日枷锁,屠梦魇恶龙,踏七彩祥云,持定海神针...啧,咋感觉越说越不对劲...
咳,重来
而现在,距离 2021 年结束还有 84 天,距离新的五年,新的十年规划开启还有 84 天,可以收拾行囊,整理自己,整装待发,以期未来~
我想我是否可以改写一下上面的话:
因为你,我渴望成为更好的人,想予你炙热的心,想予你艳丽的羽,想呈现更朝气的自己。因此不仅想发奋努力,又想驻足停留,只是为了想证明我是唯一正确的选择,只为传达我想做你想拥抱的人。
尾奏 🎵
爱情很珍贵,寒草要努力🌿
深知自己不够优秀
却想要《食梦者》中那般纯粹的梦想与爱情:完成梦想就结婚
以及《侧耳倾听》中:因为你,我愿意成为更好的人。
以及知乎中看到的这句话:
我想,最好的感情是两个人都用力的活,一起体验人生的种种趣味,也能包容与鼓励对方。当对方为你打开新的世界,你就没有因为喜欢一个人而拒绝了整个世界。
-正文完,Hancao design,to be continued-
写在最后
如果神明肯听一听我的愿望,
那么我想你晚安,愿你的梦里总有星星。
这山长水远的路,我想陪你走下去
啊,呼,寒草加油,辛向阳光,怦然辛动。
加我微信:hancao97,邀你进群,一起学习交流前端,成为更优秀的工程师~ 也可以免费看前端早早聊 10.23 日
vue
专场直播,有尤大的分享哦~