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

// 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;