You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
3.5 KiB
152 lines
3.5 KiB
// site-reactions.js
|
|
// Copyright (C) 2022 DTP Technologies, LLC
|
|
// License: Apache-2.0
|
|
|
|
'use strict';
|
|
|
|
const dtp = window.dtp = window.dtp || { }; // jshint ignore:line
|
|
|
|
import DtpLog from 'dtp/dtp-log';
|
|
|
|
class Reaction {
|
|
|
|
static get COMPONENT ( ) { return { logId: 'reaction', index: 'reaction', className: 'Reaction' }; }
|
|
|
|
constructor (container, reaction) {
|
|
this.container = container;
|
|
this.reaction = reaction;
|
|
|
|
this.element = document.createElement('span');
|
|
this.element.classList.add('reaction-icon');
|
|
|
|
switch (this.reaction.reaction) {
|
|
case 'clap':
|
|
this.element.textContent = '👏';
|
|
break;
|
|
|
|
case 'fire':
|
|
this.element.textContent = '🔥';
|
|
break;
|
|
|
|
case 'happy':
|
|
this.element.textContent = '🤗';
|
|
break;
|
|
|
|
case 'laugh':
|
|
this.element.textContent = '🤣';
|
|
break;
|
|
|
|
case 'angry':
|
|
this.element.textContent = '🤬';
|
|
break;
|
|
|
|
case 'honk':
|
|
this.element.textContent = '🤡';
|
|
break;
|
|
}
|
|
|
|
this.position = {
|
|
x: Math.random() * (this.container.offsetWidth - 32.0),
|
|
y: this.container.clientHeight,
|
|
};
|
|
|
|
this.opacity = 1.0;
|
|
this.moveSpeed = 150.0 + (Math.random() * 50.0);
|
|
|
|
this.rotation = 0.0;
|
|
this.rotationDelta = 60.0 + (Math.random() * 15.0);
|
|
|
|
this.container.appendChild(this.element);
|
|
}
|
|
|
|
update (elapsed) {
|
|
const scale = elapsed / 1000.0;
|
|
this.position.y -= this.moveSpeed * scale;
|
|
this.rotation += this.rotationDelta * scale;
|
|
if (this.rotation > 30 || this.rotation < -30) {
|
|
this.rotationDelta = -this.rotationDelta;
|
|
}
|
|
|
|
const adjustedY = this.position.y + this.element.offsetHeight;
|
|
if (adjustedY > 100) {
|
|
return;
|
|
}
|
|
if (adjustedY === 0) {
|
|
this.opacity = 0.0;
|
|
return;
|
|
}
|
|
|
|
this.opacity = adjustedY / 100.0;
|
|
}
|
|
|
|
render ( ) {
|
|
this.element.style.left = `${this.position.x}px`;
|
|
this.element.style.top = `${this.position.y}px`;
|
|
|
|
if (this.opacity > 0.8) { this.opacity = 0.8; }
|
|
this.element.style.opacity = this.opacity;
|
|
|
|
const transform = `rotate(${this.rotation}deg)`;
|
|
this.element.style.transform = transform;
|
|
}
|
|
|
|
destroy ( ) {
|
|
this.container.removeChild(this.element);
|
|
}
|
|
}
|
|
|
|
export default class SiteReactions {
|
|
|
|
static get COMPONENT ( ) { return { logId: 'site-reactions', index: 'siteReactions', className: 'SiteReactions' }; }
|
|
|
|
constructor ( ) {
|
|
this.log = new DtpLog(SiteReactions.COMPONENT);
|
|
|
|
this.container = document.querySelector('#chat-reactions');
|
|
this.reactions = [ ];
|
|
|
|
this.updateHandler = this.onUpdate.bind(this);
|
|
}
|
|
|
|
create (reaction) {
|
|
const react = new Reaction(this.container, reaction);
|
|
this.reactions.push(react);
|
|
|
|
if (this.reactions.length === 1) {
|
|
this.lastUpdate = new Date();
|
|
requestAnimationFrame(this.updateHandler);
|
|
}
|
|
}
|
|
|
|
onUpdate ( ) {
|
|
const NOW = new Date();
|
|
const elapsed = NOW - this.lastUpdate;
|
|
const expired = [ ];
|
|
|
|
for (const reaction of this.reactions) {
|
|
reaction.update(elapsed);
|
|
if (reaction.position.y <= -(reaction.element.offsetHeight)) {
|
|
expired.push(reaction);
|
|
} else {
|
|
reaction.render();
|
|
}
|
|
}
|
|
|
|
expired.forEach((react) => {
|
|
const idx = this.reactions.indexOf(react);
|
|
if (idx === -1) {
|
|
return;
|
|
}
|
|
react.destroy();
|
|
this.reactions.splice(idx, 1);
|
|
});
|
|
|
|
if (this.reactions.length > 0) {
|
|
requestAnimationFrame(this.updateHandler);
|
|
}
|
|
|
|
this.lastUpdate = NOW;
|
|
}
|
|
}
|
|
|
|
dtp.SiteReactions = SiteReactions;
|