降临是等待和准备圣诞节的时期,从圣诞节前夕的四个星期日开始。 传统上,出现时间的过去是借助出现日历或出现花圈来测量的。 尽管Advent的开始日期不是固定的日期,但Advent日历通常从12月1日开始。
根据当地习俗,降临日历可以有不同的设计,但最常见的形式是大矩形卡片,带有24个窗户或门,标记着12月1日至24日之间的日子。这些门隐藏着信息,诗歌,祈祷或惊喜。
在这篇文章中,我将向您展示如何使用面向对象JavaScript制作Advent日历 。 由于它是使用普通JavaScript制作的,因此您可以轻松地将代码放入自己的网站中。
JavaScript日历设计
我们的降临日历将以圣诞节为主题的背景图片上有24个门。 每个门都将隐藏与圣诞节相关的报价, 当用户单击门时,该报价将以警报消息的形式弹出 。 门一直保持关闭,直到给定的一天到来,就像现实中的降临日历一样。 在正确的一天之前不能打开门。
已经启用的门将具有与禁用的门(浅绿色)不同的边框和背景颜色(白色)。 我们将使用HTML5,CSS3和JavaScript来准备外观如下的Advent日历:
第1步–创建文件结构和资源
首先,我们需要选择一个漂亮的背景图像。 我从png中选择了一个纵向的,所以我的日历将包含4列和6行 。
如果您更喜欢横向,那就很好。 只需在JavaScript代码中更改门的位置,因为您将拥有6列4行 。 如果您有图像,请创建一个名为/ images的文件夹并保存。
这将是我们针对该项目的唯一图像资源。
对于JavaScript文件,在根文件夹内创建一个/ scripts文件夹。 将两个空的文本文件放入其中,并分别命名为calendar.js和messages.js 。 Calendar.js将保留该功能,而messages.js将包含当用户“打开”(单击)门时弹出的消息数组。
我们还将需要一个HTML和CSS文件,因此在根文件夹中创建两个空文件,并为其命名为index.html和style.css 。
准备就绪后,您将具有完成该项目所需的资源和文件结构,并且根文件夹如下所示:
第2步-创建HTML
我们使用HTML代码非常简单。 CSS样式表链接在<head>部分,而两个JavaScript文件包含在<body>部分的底部。 后者是必需的,因为如果将脚本放入<head>部分,则该代码将不会执行,因为它使用了已加载HTML page的元素 。
广告出现日历本身位于<article> 语义标记内 。 我们将圣诞节图像作为<img> HTML元素而不是CSS背景属性加载,因为通过这种方式,我们可以轻松地将其作为DOM元素进行访问。
在图像下方,我们放置了一个空的无序列表,其中包含“ adventDoors” id选择器,这些选择器将由脚本填充。 如果用户未在其浏览器中启用JavaScript,则他们只会看到一个简单的圣诞节图像。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Advent Calendar</title>
<!-- Mobile-friendly viewport -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Style sheet link -->
<link href="style.css" rel="stylesheet" media="all">
</head>
<body>
<article>
<h1>Advent Calendar</h1>
<img src="advent-calendar-javascript/background.jpg" alt="Advent Calendar" id="adventCal">
<ul id="adventDoors"></ul>
</article>
<!-- Scripts -->
<script src="scripts/messages.js"></script>
<script src="scripts/calendar.js"></script>
</body>
</html>
步骤3 –填充“消息”数组
我们需要24个圣诞节报价来填充“消息”数组。 我从GoodReads中选择了我的。
打开scripts / messages.js文件; 我们将引号放在此处以使其与功能分开。 消息数组是数组内部的数组,外部数组的每个元素都包含另一个包含两个元素的数组:引号和它的作者。
根据以下语法,用您喜欢的引号填充数组:
var messages = [
["Quote 1", "Author 1"],
["Quote 2", "Author 2"],
...
["Quote 24", "Author 24"]
];
第4步–为门添加基本CSS样式
要为门创建必要CSS样式,我们需要想象最终的设计,因为门本身将在以下步骤中使用JavaScript创建。
我们需要以正确的对齐方式创建4列和6行矩形。 为此,我们将使用position:relative和position:absolute CSS规则。 由于确切位置会逐门改变,因此我们将在JavaScript中添加top , bottom , left和right属性,在CSS中,我们只需向容器添加相对位置(HTML中的无序列表),然后列表元素的绝对位置(它们也将添加到JS中)。
样式表文件中的另一重要事项是为禁用状态和启用状态创建不同的设计 。 .disabled选择器将被JavaScript添加到禁用中。
在我的演示日历中,我为启用的门设置了纯白色边框和白色字体,将鼠标悬停在透明背景上。 以及浅绿色边框,字体和残疾人专用的透明浅绿色背景。 如果您不喜欢这种设计,则可以根据需要更改颜色和样式。
将以下代码(或修改后的样式规则)放入style.css文件中。
ul#adventDoors {
position: relative;
list-style: none;
padding: 0;
margin: 0;
}
#adventDoors li {
position: absolute;
}
#adventDoors li a {
color: #fff;
width: 100%;
height: 100%;
font-size: 24px;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
text-decoration: none;
border: 1px #fff solid;
}
#adventDoors li a:not(.disabled):hover {
color: #fff;
background-color: transparent;
background-color: rgba(255,255,255,0.15);
}
#adventDoors li a.disabled {
border-color: #b6fe98;
background-color: rgba(196,254,171,0.15);
color: #b6fe98;
cursor: default;
}
步骤5 –创建全局变量
从这一步开始,我们将仅使用scripts / calendar.js文件,因此现在让我们打开它。 我们的降临日历将使用两个全局变量。
myCal变量将Calendar图像保存为JS对象。 该图像已在第2步中添加到index.html文件中。在第7步中,我们将门放在该图像上。我们使用getElementById()捕获标记有“ adventCal”标识符的相关HTML <img>元素。 DOM方法。 myCal变量将是HTMLImageElement DOM对象。
currentDate变量保存当前日期,以便我们的脚本可以轻松地决定是否应启用或禁用门。 为了创建currentDate,我们实例化Date JavaScript类的新对象。
将以下代码段放入calendar.js文件的顶部。
var myCal = document.getElementById("adventCal");
var currentDate = new Date();
第6步-创建“门”类
当我们需要24门时,最简单的方法是创建“门”类,然后实例化24次。
我们的Door类有两个参数, calendar和day 。 对于calendar参数,我们需要传递圣诞节图像作为背景。 对于day参数,我们将需要以整数形式传递12月的当前日期。
我们将在实例化24个Door对象的最后一步(步骤8)中传递参数的精确值。
我们将为Door类设置5个属性和1个方法。 在这一步中,我们将仅浏览5个属性,而我将在下一步中解释content()方法。
“宽度”和“高度”属性
等式中的0.1和0.95乘数在每个门之间以及日历的侧面周围也留有一些空白空间。
“ adventMessage”属性
adventMessage属性保存警报消息的内容,即我们的messages.js文件保存的引号和匹配的作者。 adventMessage属性根据当前日期从messages []数组中获取一个引号和一个作者。
对于12月1日, adventMessage属性采用外部数组的第一个元素,即messages [0] ,因为JavaScript中的数组从零开始。
出于同样的原因,Dec 1的引号定位为messages [0] [0] (内部数组的第一个元素),而匹配的作者可以到达messages [0] [1] (内部数组的第二个元素)数组)。
“ x”和“ y”属性
属性x和y保持每个门的正确位置,我们将在下一步中使用这些属性来设置顶部和左侧 CSS属性。 这些将补充我们在步骤4中为门容器(ul#adventDoors)和门本身(#adventDoors li)设置的位置:相对和位置:绝对 CSS规则。 这些计算似乎有些令人生畏,但让我们快速进行一下。
x属性将在下一步(步骤7)中由左 CSS定位属性使用。 它以像素为单位确定需要在x轴上放置单个“门”的位置。
它占用背景图像的宽度,并为其留有一点空白(4%)。 然后,在余数运算符的帮助下,它评估将其放置在哪一列中(请记住,将有4列),最后使用1.1乘数为每个单独的门增加少量(10%)的边距。
同样, 顶部 CSS定位属性将使用y属性,同样,它以像素为单位确定需要在y轴上放置单个Door的位置。
我们借助传入的Calendar参数(包含DOM对象)的height属性获取背景图像的高度,并在Calendar的垂直边周围留出4%的边距。
然后,借助Math.floor()方法,我们计算给定的Door对象在哪一行中(将有6行)。
最后,我们通过使用1.1乘数乘以其每个门的高度,为每个门对象添加10%的边距。
function Door(calendar, day) {
this.width = ((calendar.width - 0.1 * calendar.width) / 4) * 0.95;
this.height = ((calendar.height - 0.1 * calendar.height) / 6) * 0.95;
this.adventMessage = 'Day ' + day + ' of Advent\n\n' + '"' +
messages[day - 1][0] + '"\n\n\t' + 'by ' +
messages[day - 1][1] + '\n\n';
this.x = ( 0.04 * calendar.width + ((day - 1) % 4) * (1.1 * this.width) );
this.y = - ( 0.96 * calendar.height - Math.floor((day - 1) / 4) * (1.1 * this.height) );
this.content = function() {
...
};
}
步骤7 –填充“ Content()”方法
内容()方法将在浏览器中显示我们的门。 首先,我们在变量节点的帮助下创建一个新的DOM节点,该节点将在HTML文件中当前为空的无序列表(ul#adventDoors)中创建<li>元素。
由于在下一步(步骤8)的for循环中将Door类实例化24次,这意味着我们将拥有24个<li>元素,每扇门一个li。 在下一行中,我们使用appendChild() DOM方法将新节点作为子元素追加到#adventDoors无序列表中。
下一行的node.id属性为每个列表元素(门)添加一个唯一的id选择器。 我们将需要它来在下一步骤(步骤8)中正确循环。 这样,门1将具有id =“ door1” ,门2将具有id =“ door2”选择器, 依此类推 。
下一行的node.style.cssText属性在style =”…” HTML属性的帮助下向每个列表元素(门)添加了一些CSS规则,该属性用于在HTML文件中包含内联CSS。 node.style.cssText属性使用我们在上一步(步骤6)中设置的Door类的属性。
为了使我们的Door对象可单击,我们还需要在列表元素内添加<a>标记。 我们借助innerNode变量来实现此目的,该变量通过使用appendChild作为子元素绑定到由id =“ door [i]”选择器(以[i]为天数)标识的适当列表元素上() DOM方法就像以前一样。
下一行的innerHTML属性在浏览器中显示当天的当前日期(1-24),并且我们还通过href DOM属性将href =“”属性添加到了锚标记中。
最后,在if-else语句中,我们评估是否应启用或禁用Door对象。 首先,我们使用Date对象的getMonth()方法检查是否在一年中的第12个月(十二月)。 我们需要加1,因为getMonth()是从零开始的(一月是月份0,依此类推)。
在此之后,我们检查,如果在的currentdate全局变量保持当前的日期,我们在步骤设置5小于当前门对象代表的一天 。
如果不是12月,或者给定“门”表示的日期大于当前日期,则应禁用“门”,在任何其他情况下都需要将其启用,以便用户可以单击它,并查看相关的Advent消息。
如果禁用了Door,我们将在className属性的帮助下将class =“ disabled”选择器添加到给定的锚标记中。 记住,我们已经在步骤4中使用CSS设置了.disabled类的样式。我们还需要设置onclick HTML事件属性以返回false。
如果门处于启用状态,则将adventMessage属性添加到警报消息中,并将其放置在onclick HTML事件属性中。
this.content = function() {
var node = document.createElement("li");
document.getElementById("adventDoors").appendChild(node);
node.id = "door" + day;
node.style.cssText = "width: " + this.width + "px; height: " + this.height +
"px; top: " + this.y + "px; left: " + this.x + "px;";
var innerNode = document.createElement("a");
document.getElementById("door" + day).appendChild(innerNode);
innerNode.innerHTML = day;
innerNode.href = "#";
if( ( currentDate.getMonth() + 1 ) < 12 || currentDate.getDate() < day ) {
innerNode.className = "disabled";
innerNode.onclick = function() {
return false;
}
} else {
var adventMessage = this.adventMessage;
innerNode.onclick = function() {
alert(adventMessage);
return false;
}
}
};
步骤8 –初始化“门”对象
最后,我们需要将Door类初始化24次。
为此,我们在这里使用了立即调用函数表达式 ,因为在此函数中我们只想执行一次代码,所以它不需要变量,因此它不需要变量。
我们创建一个door []数组,该数组将容纳24个Door对象。 我们遍历天从1至24(它们将门的0-23th元素[]数组,数组是从0开始),最后返回整个门[]数组包括24门对象显示它们在浏览器中。
(function() {
var doors = [];
for(var i = 0; i < 24; i++) {
doors[i] = new Door(myCal, i + 1);
doors[i].content();
}
return doors;
})();
翻译自: https://www.hongkiat.com/blog/advent-calendar-javascript/