From df4e0e7b51b86553ea8a2379c1ff69af5b5ac283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFs=20Poujade?= <lois.poujade@tetras-libre.fr> Date: Mon, 19 Dec 2022 17:13:46 +0100 Subject: [PATCH] wip0 --- src/AnnotationCreation.js | 29 +++++++- src/AnnotationDrawing.js | 153 ++++++++++++++++++++++++-------------- 2 files changed, 124 insertions(+), 58 deletions(-) diff --git a/src/AnnotationCreation.js b/src/AnnotationCreation.js index 4b5a275..e23bc26 100644 --- a/src/AnnotationCreation.js +++ b/src/AnnotationCreation.js @@ -114,8 +114,8 @@ class AnnotationCreation extends Component { popoverAnchorEl: null, popoverLineWeightAnchorEl: null, svg: null, - tend: '', - tstart: '', + tend: Math.floor(props.currentTime) + 10, + tstart: Math.floor(props.currentTime), textEditorStateBustingKey: 0, xywh: null, ...annoState, @@ -125,6 +125,10 @@ class AnnotationCreation extends Component { this.updateBody = this.updateBody.bind(this); this.updateTstart = this.updateTstart.bind(this); this.updateTend = this.updateTend.bind(this); + this.setTstartNow = this.setTstartNow.bind(this); + this.setTendNow = this.setTendNow.bind(this); + this.seekToTstart = this.seekToTstart.bind(this); + this.seekToTend = this.seekToTend.bind(this); this.updateGeometry = this.updateGeometry.bind(this); this.changeTool = this.changeTool.bind(this); this.changeClosedMode = this.changeClosedMode.bind(this); @@ -227,6 +231,8 @@ class AnnotationCreation extends Component { svg: null, textEditorStateBustingKey: textEditorStateBustingKey + 1, xywh: null, + tsart: null, + tend: null }); } @@ -255,6 +261,19 @@ class AnnotationCreation extends Component { /** update annotation end time */ updateTend(ev) { this.setState({ tend: ev.target.value }); } + /** set annotation start time to current time */ + setTstartNow() { this.setState({ tstart: Math.floor(this.currentTime) }); } + + /** set annotation end time to current time */ + setTendNow() { this.setState({ tend: Math.floor(this.props.currentTime) }); } + + /** seekTo annotation start time */ + seekToTstart() { this.props.setSeekTo(this.state.tstart); } + + /** seekTo annotation end time */ + seekToTend() { this.props.setSeekTo(this.state.tend); } + + /** */ updateGeometry({ svg, xywh }) { this.setState({ @@ -406,7 +425,11 @@ class AnnotationCreation extends Component { </Grid> <Grid item xs={12}> <input name="tstart" type="number" step="1" value={tstart} onChange={this.updateTstart} /> + <Button onClick={this.setTstartNow}>now</Button> + <Button onClick={this.seekToTstart}>seek</Button> <input name="tend" type="number" step="1" value={tend} onChange={this.updateTend} /> + <Button onClick={this.setTendNow}>now</Button> + <Button onClick={this.seekToTend}>seek</Button> </Grid> <Grid item xs={12}> <Typography variant="overline"> @@ -495,6 +518,7 @@ const styles = (theme) => ({ }); AnnotationCreation.propTypes = { + currentTime: PropTypes.number, // TODO proper web annotation type ? annotation: PropTypes.object, // eslint-disable-line react/forbid-prop-types canvases: PropTypes.arrayOf( @@ -515,6 +539,7 @@ AnnotationCreation.propTypes = { id: PropTypes.string.isRequired, receiveAnnotation: PropTypes.func.isRequired, windowId: PropTypes.string.isRequired, + setSeekTo: PropTypes.func.isRequired, }; AnnotationCreation.defaultProps = { diff --git a/src/AnnotationDrawing.js b/src/AnnotationDrawing.js index b817d24..6c35d96 100644 --- a/src/AnnotationDrawing.js +++ b/src/AnnotationDrawing.js @@ -1,9 +1,10 @@ import React, { Component } from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; +import ResizeObserver from 'react-resize-observer'; import { OSDReferences } from 'mirador/dist/es/src/plugins/OSDReferences'; -import { VideoViewersReferences } from 'mirador/dist/es/src/plugins/VideoViewersReferences'; -import { renderWithPaperScope, PaperContainer } from '@psychobolt/react-paperjs'; +import { VideosReferences } from 'mirador/dist/es/src/plugins/VideosReferences'; +import { renderWithPaperScope, PaperContainer, Size } from '@psychobolt/react-paperjs'; import { EllipseTool, @@ -17,23 +18,16 @@ import flatten from 'lodash/flatten'; import EditTool from './EditTool'; import { mapChildren } from './utils'; -/** Use a canvas "like a OSD viewport" (temporary) */ -function viewportFromAnnotationOverlayVideo(annotationOverlayVideo) { - const { canvas } = annotationOverlayVideo; - return { - getCenter: () => ({ x: canvas.getWidth() / 2, y: canvas.getHeight() / 2 }), - getFlip: () => false, - getRotation: () => false, - getZoom: () => 1, - }; -} - /** */ class AnnotationDrawing extends Component { /** */ constructor(props) { super(props); + this.paper = null; + this.getViewProps = this.getViewProps.bind(this); + this.onPaperResize = this.onPaperResize.bind(this); + this.paperDidMount = this.paperDidMount.bind(this); this.addPath = this.addPath.bind(this); } @@ -65,36 +59,76 @@ class AnnotationDrawing extends Component { }); } - /** */ - paperThing() { + onPaperResize(ev) { + if (this.paper) { + console.debug('size: ', this.paper.view.viewSize); + console.debug('el: ', this.paper.view.element); + const { canvasOverlay } = VideosReferences.get(this.props.windowId); + const height = canvasOverlay.ref.current.height; + const width = canvasOverlay.ref.current.width; + this.paper.view.viewSize = new this.paper.Size(width, height); + this.paper.view.zoom = canvasOverlay.scale; + console.debug('new scale: ', canvasOverlay.scale); + } + } + + getViewport() { + const { canvasOverlay } = VideosReferences.get(this.props.windowId); + const height = canvasOverlay.ref.current.height; + const width = canvasOverlay.ref.current.width; + return { + getCenter: () => ({ x: width / 2, y: height / 2 }), + getFlip: () => false, + getRotation: () => false, + getZoom: () => canvasOverlay.scale, + }; + } + + getViewProps() { const { windowId } = this.props; let viewport = null; let img = null; if (OSDReferences.get(windowId)) { - console.debug('[annotation-plugin] OSD reference: ', OSDReferences.get(windowId)); viewport = OSDReferences.get(windowId).current.viewport; img = OSDReferences.get(windowId).current.world.getItemAt(0); - } else if (VideoViewersReferences.get(windowId)) { - console.debug('[annotation-plugin] VideoViewers reference: ', VideoViewersReferences.get(windowId)); - viewport = viewportFromAnnotationOverlayVideo(VideoViewersReferences.get(windowId).props); + } else if (VideosReferences.get(windowId)) { + viewport = this.getViewport(); } - const { - activeTool, fillColor, strokeColor, strokeWidth, svg, - } = this.props; - if (!activeTool || activeTool === 'cursor') return null; // Setup Paper View to have the same center and zoom as the OSD Viewport/video canvas const center = img ? img.viewportToImageCoordinates(viewport.getCenter(true)) : viewport.getCenter(); const flipped = viewport.getFlip(); - const viewProps = { + return { center: new Point(center.x, center.y), rotation: viewport.getRotation(), scaling: new Point(flipped ? -1 : 1, 1), zoom: img ? img.viewportToImageZoom(viewport.getZoom()) : viewport.getZoom(), }; + } + componentDidMount() { + console.debug('componentDidMount'); + this.onPaperResize(); + } + + componentDidUpdate() { + console.debug('componentDidUpdate'); + this.onPaperResize(); + } + + paperDidMount(paper) { + console.debug('paper mounted: ', paper); + this.paper = paper; + } + + /** */ + paperThing() { + const { + activeTool, fillColor, strokeColor, strokeWidth, svg, + } = this.props; + if (!activeTool || activeTool === 'cursor') return null; let ActiveTool = RectangleTool; switch (activeTool) { case 'rectangle': @@ -116,39 +150,46 @@ class AnnotationDrawing extends Component { break; } + const { canvasOverlay } = VideosReferences.get(this.props.windowId); + const height = canvasOverlay.ref.current.height; + const width = canvasOverlay.ref.current.width; + + // canvasProps={{ style: { left: 0, position: 'absolute', top: 0}, height: height, width: width, resize: 'true' }} return ( <div - className="foo" - style={{ - height: '100%', left: 0, position: 'absolute', top: 0, width: '100%', - }} + className="foo" + style={{ + height: '100%', left: 0, position: 'absolute', top: 0, width: '100%', + }} + > + <PaperContainer + canvasProps={{ style: { position: 'absolute', left: 0, top: 0 }, height, width }} + viewProps={this.getViewProps} + onMount={this.paperDidMount} > - <PaperContainer - canvasProps={{ style: { height: '100%', width: '100%' } }} - viewProps={viewProps} - > - {renderWithPaperScope((paper) => { - const paths = flatten(paper.project.layers.map((layer) => ( - flatten(mapChildren(layer)).map((aPath) => aPath) - ))); - if (svg && paths.length === 0) { - paper.project.importSVG(svg); - } - paper.settings.handleSize = 10; // eslint-disable-line no-param-reassign - paper.settings.hitTolerance = 10; // eslint-disable-line no-param-reassign - return ( - <ActiveTool - onPathAdd={this.addPath} - pathProps={{ - fillColor, - strokeColor, - strokeWidth: strokeWidth / paper.view.zoom, - }} - paper={paper} - /> - ); - })} - </PaperContainer> + {renderWithPaperScope((paper) => { + const paths = flatten(paper.project.layers.map((layer) => ( + flatten(mapChildren(layer)).map((aPath) => aPath) + ))); + if (svg && paths.length === 0) { + paper.project.importSVG(svg); + } + paper.settings.handleSize = 10; // eslint-disable-line no-param-reassign + paper.settings.hitTolerance = 10; // eslint-disable-line no-param-reassign + return ( + <ActiveTool + onPathAdd={this.addPath} + pathProps={{ + fillColor, + strokeColor, + strokeWidth: strokeWidth / paper.view.zoom, + }} + paper={paper} + /> + ); + })} + </PaperContainer> + <ResizeObserver onResize={this.onPaperResize} /> </div> ); } @@ -156,10 +197,10 @@ class AnnotationDrawing extends Component { /** */ render() { const { windowId } = this.props; + console.log('[render] videoref : ', VideosReferences.get(windowId)); const container = OSDReferences.get(windowId) ? OSDReferences.get(windowId).current.element - : VideoViewersReferences.get(windowId).apiRef.current; - + : VideosReferences.get(windowId).ref.current.parentElement; return ( ReactDOM.createPortal(this.paperThing(), container) ); -- GitLab