canvas.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /**
  2. * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  6. */
  7. import * as React from 'react';
  8. import { PluginUIComponent } from '../base';
  9. import { resizeCanvas } from '../../mol-canvas3d/util';
  10. import { Subject } from 'rxjs';
  11. import { debounceTime } from 'rxjs/internal/operators/debounceTime';
  12. interface ViewportCanvasState {
  13. noWebGl: boolean
  14. showLogo: boolean
  15. }
  16. export interface ViewportCanvasParams {
  17. logo?: React.FC,
  18. noWebGl?: React.FC,
  19. parentClassName?: string,
  20. parentStyle?: React.CSSProperties,
  21. hostClassName?: string,
  22. hostStyle?: React.CSSProperties
  23. }
  24. export class ViewportCanvas extends PluginUIComponent<ViewportCanvasParams, ViewportCanvasState> {
  25. private container = React.createRef<HTMLDivElement>();
  26. private canvas = React.createRef<HTMLCanvasElement>();
  27. state: ViewportCanvasState = {
  28. noWebGl: false,
  29. showLogo: true
  30. };
  31. private handleLogo = () => {
  32. this.setState({ showLogo: !this.plugin.canvas3d?.reprCount.value });
  33. }
  34. private handleResize = () => {
  35. const container = this.container.current;
  36. const canvas = this.canvas.current;
  37. if (container && canvas) {
  38. resizeCanvas(canvas, container);
  39. this.plugin.canvas3d!.handleResize();
  40. }
  41. }
  42. componentDidMount() {
  43. if (!this.canvas.current || !this.container.current || !this.plugin.initViewer(this.canvas.current!, this.container.current!)) {
  44. this.setState({ noWebGl: true });
  45. return;
  46. }
  47. this.handleLogo();
  48. this.handleResize();
  49. const canvas3d = this.plugin.canvas3d!;
  50. this.subscribe(canvas3d.reprCount, this.handleLogo);
  51. const resized = new Subject();
  52. const resize = () => resized.next();
  53. this.subscribe(resized.pipe(debounceTime(1000 / 24)), () => this.handleResize());
  54. this.subscribe(canvas3d.input.resize, resize);
  55. this.subscribe(canvas3d.interaction.click, e => this.plugin.behaviors.interaction.click.next(e));
  56. this.subscribe(canvas3d.interaction.drag, e => this.plugin.behaviors.interaction.drag.next(e));
  57. this.subscribe(canvas3d.interaction.hover, e => this.plugin.behaviors.interaction.hover.next(e));
  58. this.subscribe(this.plugin.layout.events.updated, resize);
  59. }
  60. componentWillUnmount() {
  61. super.componentWillUnmount();
  62. // TODO viewer cleanup
  63. }
  64. renderMissing() {
  65. if (this.props.noWebGl) {
  66. const C = this.props.noWebGl;
  67. return <C />;
  68. }
  69. return <div className='msp-no-webgl'>
  70. <div>
  71. <p><b>WebGL does not seem to be available.</b></p>
  72. <p>This can be caused by an outdated browser, graphics card driver issue, or bad weather. Sometimes, just restarting the browser helps.</p>
  73. <p>For a list of supported browsers, refer to <a href='http://caniuse.com/#feat=webgl' target='_blank'>http://caniuse.com/#feat=webgl</a>.</p>
  74. </div>
  75. </div>;
  76. }
  77. render() {
  78. if (this.state.noWebGl) return this.renderMissing();
  79. const Logo = this.props.logo;
  80. return <div className={this.props.parentClassName || 'msp-viewport'} style={this.props.parentStyle}>
  81. <div className={this.props.hostClassName || 'msp-viewport-host3d'} style={this.props.hostStyle} ref={this.container}>
  82. <canvas ref={this.canvas} />
  83. </div>
  84. {(this.state.showLogo && Logo) && <Logo />}
  85. </div>;
  86. }
  87. }