Random Quote Machine

前端工程展示页

项目介绍

源代码 + 效果图

See the Pen Challenges [06] by MaverickNone (@MaverickNone) on CodePen.


如果客官您觉得不够大,看着不太爽!请点击这里或者这边~


源代码解构

HTML

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test [06]</title>
<link rel="stylesheet" href="style.css">
<script src="https://kit.fontawesome.com/83ef1fc2b2.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="script.js"></script>
</head>
  1. jQuery的添加源可以从cdnjs里面找,大部分添加源都可以找到,非常方便
  2. 因为涉及对HTML元素的控制,jQuery的UI组件包也要添加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<div id="wrapper">
<div id="quote-box">
<div class="quote-text">
<i class="fas fa-angle-double-left"></i>
<span id="text"></span>
<i class="fas fa-angle-double-right"></i>
</div>
<div class="quote-author">
- <span id="author"></span>
</div>
<div class="buttons">
<a class="button" id="tweet-quote" title="Tweet this quote!" target="_blank"><i class="fab fa-twitter"></i></a>
<a class="button" id="tumblr-quote" title="Post this quote on tumblr!" target="_blank"><i class="fab fa-tumblr"></i></a>
<button class="button" id="new-quote">New quote</button>
</div>
</div>
<div class="footer">
By <a href="https://mavericknone.github.io">MaverickNone</a>
</div>
</div>
</body>
  • 稍微可以讲的也就两点
    1. <i>标签原本是作为斜体文本的标记,现在常常被用于标记图标
    2. <span>标签没有固定的格式表现,其中的文本与其他文本不会任何视觉上的差异。但是可以用于孤立文本方便CSS和JavaScript对于单独控制
1
2
<script src="https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js"></script>
</html>
  • src里面的内容是freeCodeCamp对项目的质量评测系统,如果在</body>前添加,那么就会报错Uncaught TypeError: Cannot read property 'appendChild' of null,因为HTML加载的时候是从上往下加载,也就是说,当评测系统开始评测已经加载完毕开始评测的时候,需要评测的内容尚未加载完毕,所以肯定报错

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
@import url(https://fonts.googleapis.com/css?family=Raleway:400,500);
:root {
--black: #333;
--white: #fff;
}
* {
margin: 0;
padding: 0;
list-style: none;
}

body {
background-color: var(--black);
color: var(--black);
font-family: "Raleway", sans-serif;
font-weight: 400;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.footer {
width: 450px;
text-align: center;
display: block;
margin: 15px auto 0 auto;
font-size: 0.8em;
color: var(--white);
a {
font-weight: 500;
text-decoration: none;
color: var(--white);
}
}
#quote-box {
border-radius: 20px;
width: 450px;
padding: 40px 50px;
display: table;
background-color: var(--white);
.quote-text {
i {
margin-left: 0.4em;
margin-right: 0.4em;
}
text-align: center;
width: 450px;
font-weight: 500;
font-size: 1.75em;
}
.quote-author {
width: 450px;
padding-top: 20px;
text-align: right;
}
.buttons {
width: 450px;
margin: auto;
display: block;
.button {
height: 38px;
border: none;
border-radius: 8px;
color: var(--white);
background-color: var(--black);
outline: none;
font-size: 0.85em;
padding: 8px 18px 6px 18px;
margin-top: 30px;
opacity: 1;
cursor: pointer;
&:hover {
animation: toWhite 0.5s;
animation-fill-mode: forwards;
}
@keyframes toWhite {
100% {opacity: 0.8}
}
&#tweet-quote,
&#tumblr-quote {
float: left;
padding: 8px 0 0;
text-align: center;
font-size: 1.2em;
margin-right: 5px;
height: 30px;
width: 40px;
}
&#new-quote {
float: right;
}
}
}
}
  1. <body> { height: 100vh; }这里直接将页面高度设置为整个可视页面
  2. 对于<i>标签,控制其包含的图标大小是通过调控font-size来实现的
  3. Scss中,&字符用于选择父级选择器
  4. outline: none;用于消除聚焦于按钮时出现的很难看的默认边框

JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
let quotesData,
currentQuote = "",
currentAuthor = "";

let colors = [
"#16a085",
"#27ae60",
"#2c3e50",
"#f39c12",
"#e74c3c",
"#9b59b6",
"#FB6964",
"#342224",
"#472E32",
"#BDBB99",
"#77B1A9",
"#73A857"
];

function inIframe() {
try {
return window.self !== window.top;
} catch (err) {
return true;
}
}
function openURL(url) {
window.open(url);
}

function getQuotes() {
return $.ajax({
url: "https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json",
success: function(jsonQuotes) {
quotesData = JSON.parse(jsonQuotes);
console.log("Successfully received and processed json object!!!");
}
});
}
  1. inIframe()这个函数的作用是检查当前元素是否在窗口的最顶层(是否能被看到),如果没有该函数,TwitterTumblr的图标就会在加载完后立马被刷下去
  2. 本来<a>元素本身自带打开窗口的功能,但是使用inIframe()后,图标的Link失效,需要用openURL来自己写个类似的功能来手动重新实现
  3. getQuotes()里面是jQuery自带的Ajax异步数据接收函数,本来实现类似的功能需要写一堆代码,非常繁琐,现在简化了
  4. 接收的JSON字符串数据需要用JSON.parse()来转化成JavaScript能够处理的Object
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
function getRandomQuote() {
let randomIndex = Math.floor(Math.random() * quotesData.quotes.length);
return quotesData.quotes[randomIndex];
}
function getQuote() {
let randomQuote = getRandomQuote();
currentQuote = randomQuote.quote;
currentAuthor = randomQuote.author;
console.log(currentQuote);
console.log('By '+currentAuthor);

if (inIframe()) {
$("#tweet-quote").attr(
"href",
"https://twitter.com/intent/tweet?hashtags=quotes&related=freecodecamp&text=" +
encodeURIComponent('"' + currentQuote + '" ' + currentAuthor)
);
$("#tumblr-quote").attr(
"href",
"https://www.tumblr.com/widgets/share/tool?posttype=quote&tags=quotes,freecodecamp&caption=" +
encodeURIComponent(currentAuthor) +
"&content=" +
encodeURIComponent(currentQuote) +
"&canonicalUrl=https%3A%2F%2Fwww.tumblr.com%2Fbuttons&shareSource=tumblr_share_button"
);
}

$(".quote-text").animate({ opacity: 0 }, 500, function() {
$(this).animate({
opacity: 1
}, 500);
$("#text").text(randomQuote.quote);
});
$(".quote-author").animate({ opacity: 0 }, 500, function() {
$(this).animate({
opacity: 1
}, 500);
$("#author").html(randomQuote.author);
});

let randomIndex = Math.floor(Math.random() * colors.length);
console.log(colors[randomIndex]);

$("html body").animate({
backgroundColor: colors[randomIndex],
color: colors[randomIndex]
}, 1000);
$(".button").animate({
backgroundColor: colors[randomIndex]
}, 1000);
}
  1. 记住生成固定范围的随机数的方法
  2. 如果分享按钮在顶层界面,就只动态替换分享的链接
  3. encodeURIComponent()函数可把字符串作为 URI 进行编码,实现动态分享当前quote
  4. 现在我们来仔细分析一下动画的过程发生了什么
    • 前0.5秒
      • 文字消失,从不透明到全透明,从颜色A变成透明
      • <body>元素和3个按钮从颜色A转到过渡颜色(AB之间的颜色)
    • 后0.5秒
      • 文字出现,从全透明到不透明,从透明变成颜色B
      • <body>元素和3个按钮从过渡颜色转到颜色B
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$(document).ready(function() {
getQuotes().then(() => {
getQuote();
});

$("#new-quote").on("click", getQuote);

$("#tweet-quote").on("click", function() {
if (!inIframe()) {
openURL(
"https://twitter.com/intent/tweet?hashtags=quotes&related=freecodecamp&text=" +
encodeURIComponent('"' + currentQuote + '" ' + currentAuthor)
);
}
});
$("#tumblr-quote").on("click", function() {
if (!inIframe()) {
openURL(
"https://www.tumblr.com/widgets/share/tool?posttype=quote&tags=quotes,freecodecamp&caption=" +
encodeURIComponent(currentAuthor) +
"&content=" +
encodeURIComponent(currentQuote) +
"&canonicalUrl=https%3A%2F%2Fwww.tumblr.com%2Fbuttons&shareSource=tumblr_share_button"
);
}
});
});
  1. then()方法保证getQuotes()先得到并处理数据,然后再通过getQuote()呈现数据
  2. on()分别绑定了3次事件,一点new quote按钮,就呈现数据(新的quote,并随机变化颜色),一点Twitter或者Tumblr按钮就分别打开各自的动态分享页面
  3. 如果分享按钮不在顶层界面,就手动打开新界面。如果在,就啥都不做,反正原来的点击就自带打开链接的功能

项目总结

  • 对于jQuery的很多使用细节仍然还是一知半解,仍然需要找专业的书籍来进阶提升
  • 对于CSS的单一特效已经有了基本认知,但是对于父元素与子元素之间的特效的组合不甚了解,也需要找专业的书籍来打好基础
  • 这次也花了很长时间才弄懂怎么添加外源,不过这次算是一次性全部弄懂了
  • 这个项目也启发了在GitHub上的Gist板块保存只读JSON的想法,用Ajax技术来传输访问

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!