Render confetti the react way

pull/21833/head
Steffen Kolmer 2020-10-19 13:54:09 +02:00
parent 3e8e817a3d
commit 41160ff08e
3 changed files with 56 additions and 23 deletions

View File

@ -73,6 +73,7 @@ import TintableSvg from "../views/elements/TintableSvg";
import {XOR} from "../../@types/common";
import { IThreepidInvite } from "../../stores/ThreepidInviteStore";
import { CallState, CallType, MatrixCall } from "matrix-js-sdk/lib/webrtc/call";
import ConfettiOverlay from "../views/elements/ConfettiOverlay";
const DEBUG = false;
let debuglog = function(msg: string) {};
@ -693,7 +694,7 @@ export default class RoomView extends React.Component<IProps, IState> {
this.checkIfAlone(this.state.room);
break;
case 'confetti':
animateConfetti(this.roomView.current.offsetWidth);
//TODO: animateConfetti(this.roomView.current.offsetWidth);
break;
case 'post_sticker_message':
this.injectSticker(
@ -853,7 +854,7 @@ export default class RoomView extends React.Component<IProps, IState> {
this.calculateRecommendedVersion(room);
this.updateE2EStatus(room);
this.updatePermissions(room);
forceStopConfetti();
//TODO: forceStopConfetti();
};
private async calculateRecommendedVersion(room: Room) {
@ -2072,6 +2073,9 @@ export default class RoomView extends React.Component<IProps, IState> {
return (
<RoomContext.Provider value={this.state}>
<main className={mainClasses} ref={this.roomView} onKeyDown={this.onReactKeyDown}>
{this.roomView.current &&
<ConfettiOverlay roomWidth={this.roomView.current.offsetWidth} />
}
<ErrorBoundary>
<RoomHeader
room={this.state.room}

View File

@ -1,14 +1,18 @@
/*
MIT License
Copyright (c) 2018 MathuSum Mut
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -89,9 +93,7 @@ const confetti = {
}
}
function startConfetti(roomWidth, timeout) {
const width = roomWidth;
const height = window.innerHeight;
function startConfetti(canvas, roomWidth, timeout) {
window.requestAnimationFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
@ -102,26 +104,12 @@ const confetti = {
return window.setTimeout(callback, confetti.frameInterval);
};
})();
let canvas = document.getElementById("confetti-canvas");
if (canvas === null) {
canvas = document.createElement("canvas");
canvas.setAttribute("id", "confetti-canvas");
canvas.setAttribute("style",
"display:block;z-index:999999;pointer-events:none;position:fixed;top:0; right:0");
document.body.prepend(canvas);
canvas.width = width;
canvas.height = height;
window.addEventListener("resize", function() {
canvas.width = roomWidth;
canvas.height = window.innerHeight;
}, true);
context = canvas.getContext("2d");
} else if (context === null) {
if (context === null) {
context = canvas.getContext("2d");
}
const count = confetti.maxCount;
while (particles.length < count) {
particles.push(resetParticle({}, width, height));
particles.push(resetParticle({}, canvas.width, canvas.height));
}
streamingConfetti = true;
runAnimation();
@ -211,8 +199,8 @@ export function isConfettiEmoji(content) {
return !!(hexArray.includes('1f389') || hexArray.includes('1f38a'));
}
export function animateConfetti(roomWidth) {
confetti.start(roomWidth, 3000);
export function animateConfetti(canvas, roomWidth) {
confetti.start(canvas, roomWidth, 3000);
}
export function forceStopConfetti() {
confetti.remove();

View File

@ -0,0 +1,41 @@
import React, {useEffect, useRef} from 'react';
import {animateConfetti, forceStopConfetti} from './Confetti.js';
export default function ConfettiOverlay({roomWidth}) {
const canvasRef = useRef(null);
// on mount
useEffect(() => {
const resize = () => {
const canvas = canvasRef.current;
canvas.height = window.innerHeight;
};
const canvas = canvasRef.current;
canvas.width = roomWidth;
canvas.height = window.innerHeight;
window.addEventListener("resize", resize, true);
animateConfetti(canvas, roomWidth);
return () => {
window.removeEventListener("resize", resize);
forceStopConfetti();
};
}, []);
// on roomWidth change
useEffect(() => {
const canvas = canvasRef.current;
canvas.width = roomWidth;
}, [roomWidth]);
return (
<canvas
ref={canvasRef}
style={{
display: "block",
zIndex: 999999,
pointerEvents: "none",
position: "fixed",
top: 0,
right: 0,
}}
/>
)
}