这个怎么运作#
让我们考虑一下这种效果如何发挥作用的基本原理:
- 首先:我们需要创建所有单独的五彩纸屑。
- 接下来:我们需要像五彩纸屑一样移动它们,即达到一个顶峰,然后下降。?
- 最后:我们需要淡出并移除五彩纸屑。
为了制作五彩纸屑,我们将制作很多小div
s。我们将为它们分配所有随机颜色。
为此,代码如下所示:
.confetti-item { width: 10px; position: absolute; top: 0; left: 0; height: 10px; } .confetti { position: fixed; top: 0; left: 0; }
// Create a confetti holder element let createElement = document.createElement('div'); createElement.classList.add('confetti'); // These are our 'random' colors let colors = [ '#2162ff', '#9e21ff', '#21a9ff', '#a9ff21', '#ff2184' ] // Let's generate some confetti. The function below is generating 40 random confetti items! let confettiHTML = ''; for(var i = 0; i < 20; ++i) { let color = Math.floor(Math.random() * (colors.length)); confettiHTML += `<div class="confetti-item" style="background-color: ${colors[color]};" data-angle="${Math.random()}" data-speed="${Math.random()}"></div>`; confettiHTML += `<div class="confetti-item reverse" style="background-color: ${colors[color]};" data-angle="${Math.random()}" data-speed="${Math.random()}"></div>`; } // Updates the style of our new confetti element and appends it to the body createElement.style.position = `fixed`; createElement.style.top = `${y}px`; createElement.style.left = `${x}px`; createElement.innerHTML = confettiHTML; document.body.appendChild(createElement);
现在我们已经创建了五彩纸屑的结构,我们必须进入它的运动。
移动#
建模运动需要方程。对于这篇文章,我们将使用传统的弹丸运动方程。如果您不熟悉这些,它们会模拟物体从起点沿 x 和 y 轴的运动,给定一定的速度。
方程如下所示:
// x = speed * time * cos(angle) // y = speed * time * sin(angle) - (0.5 * gravity * time^2)
我们将使用这些核心方程来创建我们的运动,并为其添加一些修饰符以创建“随机”运动的感觉。例如,这里有一个物体随着抛射运动移动:
上述效果是使用这些射弹运动方程生成的,并根据它们的值简单地平移元素。
弹丸运动的实现#
当我们将其应用于每个五彩纸屑时,我们需要遍历每个项目并相应地调整其运动。您可能已经注意到,我们在每个五彩纸屑元素上都有两个数据标签,它们都有随机数。我们将使用这些随机数来产生随机运动的感觉。
我们将有一个角度和速度的随机数,然后通过其随机数调整每个五彩纸屑元素的位置。
我们将使用时间间隔为 33.3 微秒的时间间隔。
// The gravity or 'falling speed' adjuster let gravity = 50; // Fjolt is a high gravity planet // The range of speeds let maxSpeed = 105000; // Pixels * 1000 let minSpeed = 65000; // Pixels * 1000 // The time let t = 0; // Time starts at 0 // The range of angles let maxAngle = 1500; // Radians * 1000 let minAngle = 400; // Radians * 1000 // The initial opacity let opacity = 1; // The initial confetti rotation let rotateAngle = 0; // The interval let interval = setInterval(function() { // Generate motion for each confetti element document.querySelectorAll(`.confetti-item`).forEach(function(item) { // So we can have two directions of confetti, we use a modifier on the X axis. let modifierX = 1; if(item.classList.contains('reverse')) { modifierX = -1; } item.style.opacity = opacity; // Get both our random numbers let randomNumber = parseFloat(item.getAttribute('data-angle')); let otherRandom = parseFloat(item.getAttribute('data-speed')); // Generate a random angle motion for rotating each confetti element let newRotateAngle = randomNumber * rotateAngle; // Generate the angle and speed we use for the equations of motion let angle = (randomNumber * (maxAngle - minAngle) + minAngle) / 1000; let speed = (randomNumber * (maxSpeed - minSpeed) + minSpeed) / 1000; // Get x,y for projectile motion. We adjust this by the random number. let x = speed * t * Math.cos(angle) + (50 * otherRandom * t); let y = speed * t * Math.sin(angle) - (0.5 * gravity * Math.pow(t, 2)) + (50 * otherRandom * t); // Transform the element accordingly. item.style.transform = `translateX(${x * modifierX}px) translateY(${y * -1}px) rotateY(${newRotateAngle}deg) scale(${1})`; }) // Increase time, and rotate angle // Decrease opacity t += 0.1; rotateAngle += 3; opacity -= 0.02; // If the time is above 6, then lets remove the element if(t >= 6) { t = 0.1; if(document.querySelector(`.confetti`) !== null) { console.log(document.querySelector(`.confetti`)); document.querySelector(`.confetti`).remove(); } clearInterval(interval); } }, 33.33);
最后#
在最终代码中,我为每个 confetti 实例指定了一个单独的 ID,因此我们可以在页面上拥有多个 confetti 实例。还有一些其他的补充,这使它更具交互性。
我目前正在开展一个项目,如果用户点击正确答案,该项目会奖励用户。为用户提供与他们给出正确答案时的感受相匹配的响应,是用户体验的重要组成部分。
我想了几种方法来做到这一点——也许当用户点击正确的响应时,按钮会以积极的方式抖动。我对此不太走运,所以我的注意力转向了五彩纸屑,它(出于所有意图和目的)仅与庆祝有关。
值得一提的是,此页面启用了五彩纸屑。单击任意位置,五彩纸屑应从光标末端或您触摸的任何位置出现。
有趣的事实:在这样做的同时,我还发现五彩纸屑早在 14 世纪的米兰就被使用了,这比我预期的要长得多。