88 lines
3.2 KiB
TypeScript
88 lines
3.2 KiB
TypeScript
import React, { useCallback, useState } from "react";
|
|
import { Renderer, RendererError } from "./Renderer";
|
|
import { ShaderError } from "./Shader";
|
|
|
|
function Visualizer({
|
|
audioContext,
|
|
audioNode,
|
|
}: {
|
|
audioContext: AudioContext;
|
|
audioNode: AudioNode;
|
|
}) {
|
|
const [renderError, setRenderError] = useState<JSX.Element | null>(null);
|
|
|
|
const canvas = useCallback(
|
|
(canvas: HTMLCanvasElement | null) => {
|
|
// If we're rendering an error message, we won't be
|
|
// setting a canvas.
|
|
//
|
|
// Also, nonintuitively, renderError will be null here on
|
|
// subsequent iterations, so we can't rely on it to
|
|
// identify errors.
|
|
if (canvas === null) {
|
|
return;
|
|
}
|
|
|
|
const renderer = new Renderer(audioContext, audioNode, canvas);
|
|
try {
|
|
renderer.initializeScene();
|
|
} catch (error) {
|
|
// Log so we don't lose the stack trace
|
|
console.log(error);
|
|
|
|
if (error instanceof ShaderError) {
|
|
setRenderError(
|
|
<span>
|
|
Failed to compile shader; This is a bug, feel free
|
|
to contact me with this error message:
|
|
<pre>
|
|
<code className="has-text-danger">
|
|
{error.message}
|
|
</code>
|
|
</pre>
|
|
</span>
|
|
);
|
|
} else if (error instanceof RendererError) {
|
|
setRenderError(
|
|
<span>
|
|
This browser does not support WebGL 2, sadly. This
|
|
demo uses WebGL and specifically instanced drawing,
|
|
so unfortunately this means it can't run on your
|
|
browser/device.
|
|
</span>
|
|
);
|
|
} else if (error instanceof Error) {
|
|
setRenderError(
|
|
<span>
|
|
Something went very wrong; apologies, either your
|
|
browser is not behaving or there's a serious bug.
|
|
You can contact me with this error message:
|
|
<pre>
|
|
<code className="has-text-danger">
|
|
{error.message}
|
|
</code>
|
|
</pre>
|
|
</span>
|
|
);
|
|
} else {
|
|
setRenderError(
|
|
<span>
|
|
Something went very wrong; apologies, either your
|
|
browser is not behaving or there's a serious bug.
|
|
</span>
|
|
);
|
|
}
|
|
}
|
|
},
|
|
[audioContext, audioNode]
|
|
);
|
|
|
|
if (renderError === null) {
|
|
return <canvas ref={canvas} style={{ display: "block" }}></canvas>;
|
|
} else {
|
|
return renderError;
|
|
}
|
|
}
|
|
|
|
export default Visualizer;
|