diff --git a/src/components/stage/stage.jsx b/src/components/stage/stage.jsx index 37b8bced0b49b77d680557e42dd27fd1ce45b034..be3b6bef2f872a979fa3bb71e0814ba18f9e12fa 100644 --- a/src/components/stage/stage.jsx +++ b/src/components/stage/stage.jsx @@ -3,6 +3,7 @@ import React from 'react'; import classNames from 'classnames'; import Box from '../box/box.jsx'; +import DOMElementRenderer from '../../containers/dom-element-renderer.jsx'; import Loupe from '../loupe/loupe.jsx'; import MonitorList from '../../containers/monitor-list.jsx'; import Question from '../../containers/question.jsx'; @@ -12,7 +13,7 @@ import styles from './stage.css'; const StageComponent = props => { const { - canvasRef, + canvas, dragRef, isColorPicking, isFullScreen, @@ -21,6 +22,7 @@ const StageComponent = props => { stageSize, useEditorDragStyle, onDeactivateColorPicker, + onDoubleClick, onQuestionAnswered, ...boxProps } = props; @@ -35,14 +37,14 @@ const StageComponent = props => { [styles.stageWrapperOverlay]: isFullScreen, [styles.withColorPicker]: !isFullScreen && isColorPicking })} + onDoubleClick={onDoubleClick} > - <Box + <DOMElementRenderer className={classNames( styles.stage, {[styles.stageOverlayContent]: isFullScreen} )} - componentRef={canvasRef} - element="canvas" + domElement={canvas} height={stageDimensions.height} width={stageDimensions.width} {...boxProps} @@ -93,7 +95,7 @@ const StageComponent = props => { ); }; StageComponent.propTypes = { - canvasRef: PropTypes.func, + canvas: PropTypes.instanceOf(Element).isRequired, colorInfo: Loupe.propTypes.colorInfo, dragRef: PropTypes.func, isColorPicking: PropTypes.bool, @@ -105,7 +107,6 @@ StageComponent.propTypes = { useEditorDragStyle: PropTypes.bool }; StageComponent.defaultProps = { - canvasRef: () => {}, dragRef: () => {} }; export default StageComponent; diff --git a/src/containers/dom-element-renderer.jsx b/src/containers/dom-element-renderer.jsx new file mode 100644 index 0000000000000000000000000000000000000000..f3e2b7d70bfc61bed10c74515fd1377b1f93b87b --- /dev/null +++ b/src/containers/dom-element-renderer.jsx @@ -0,0 +1,39 @@ +import omit from 'lodash.omit'; +import PropTypes from 'prop-types'; +import React from 'react'; + +/* + * DOMElementRenderer wraps a DOM element, allowing it to be + * rendered by React. It's up to the containing component + * to retain a reference to the element prop, or else it + * will be garbage collected after unmounting. + */ +class DOMElementRenderer extends React.Component { + constructor (props) { + super(props); + this.setContainer = this.setContainer.bind(this); + } + componentDidMount () { + this.container.appendChild(this.props.domElement); + } + componentWillUnmount () { + this.container.removeChild(this.props.domElement); + } + setContainer (c) { + this.container = c; + } + render () { + // Look at me, I'm the React now! + Object.assign( + this.props.domElement, + omit(this.props, ['domElement', 'children']) + ) + return <div ref={this.setContainer} />; + } +} + +DOMElementRenderer.propTypes = { + domElement: PropTypes.instanceOf(Element).isRequired +} + +export default DOMElementRenderer; diff --git a/src/containers/stage.jsx b/src/containers/stage.jsx index 0013307f8d31bee981f324ff83d182980badf8a2..c244b0fc155f4732c865f8fd5aa4ba846278f107 100644 --- a/src/containers/stage.jsx +++ b/src/containers/stage.jsx @@ -37,7 +37,6 @@ class Stage extends React.Component { 'onWheel', 'updateRect', 'questionListener', - 'setCanvas', 'setDragCanvas', 'clearDragCanvas', 'drawDragCanvas', @@ -52,16 +51,22 @@ class Stage extends React.Component { colorInfo: null, question: null }; + if (this.props.vm.runtime.renderer) { + this.renderer = this.props.vm.runtime.renderer; + this.canvas = this.props.vm.runtime.renderer._gl.canvas; + } else { + this.canvas = document.createElement('canvas'); + this.renderer = new Renderer(this.canvas); + this.props.vm.attachRenderer(this.renderer); + } + this.props.vm.attachV2SVGAdapter(new V2SVGAdapter()); + this.props.vm.setVideoProvider(new VideoProvider()); } componentDidMount () { this.attachRectEvents(); this.attachMouseEvents(this.canvas); this.updateRect(); - this.renderer = new Renderer(this.canvas); - this.props.vm.attachRenderer(this.renderer); - this.props.vm.attachV2SVGAdapter(new V2SVGAdapter()); this.props.vm.runtime.addListener('QUESTION', this.questionListener); - this.props.vm.setVideoProvider(new VideoProvider()); } shouldComponentUpdate (nextProps, nextState) { return this.props.stageSize !== nextProps.stageSize || @@ -353,9 +358,6 @@ class Stage extends React.Component { commonStopDragActions(); } } - setCanvas (canvas) { - this.canvas = canvas; - } setDragCanvas (canvas) { this.dragCanvas = canvas; } @@ -365,9 +367,10 @@ class Stage extends React.Component { onActivateColorPicker, // eslint-disable-line no-unused-vars ...props } = this.props; + if (!this.canvas) this.canvas = this.setCanvas(); return ( <StageComponent - canvasRef={this.setCanvas} + canvas={this.canvas} colorInfo={this.state.colorInfo} dragRef={this.setDragCanvas} question={this.state.question}