image-canvas.tsx 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import * as React from 'react'
  7. type State = { imageData: ImageData, width: number, height: number }
  8. function getExtend(aspectRatio: number, maxWidth: number, maxHeight: number) {
  9. let width = maxWidth
  10. let height = width / aspectRatio
  11. if (height > maxHeight) {
  12. height = maxHeight
  13. width = height * aspectRatio
  14. }
  15. return { width, height }
  16. }
  17. export class ImageCanvas extends React.Component<{ imageData: ImageData, aspectRatio: number, maxWidth: number, maxHeight: number }, State> {
  18. private canvas: HTMLCanvasElement | null = null;
  19. private ctx: CanvasRenderingContext2D | null = null;
  20. updateStateFromProps() {
  21. this.setState({
  22. imageData: this.props.imageData,
  23. ...getExtend(this.props.aspectRatio, this.props.maxWidth, this.props.maxHeight)
  24. })
  25. }
  26. updateImage() {
  27. if (this.canvas) {
  28. this.canvas.width = this.state.imageData.width
  29. this.canvas.height = this.state.imageData.height
  30. }
  31. if (this.ctx) {
  32. this.ctx.putImageData(this.state.imageData, 0, 0)
  33. }
  34. }
  35. componentWillMount() {
  36. this.updateStateFromProps()
  37. }
  38. componentDidMount() {
  39. if (this.canvas && !this.ctx) {
  40. this.ctx = this.canvas.getContext('2d')
  41. if (this.ctx) this.ctx.imageSmoothingEnabled = false
  42. }
  43. this.updateImage()
  44. }
  45. componentWillReceiveProps() {
  46. this.updateStateFromProps()
  47. }
  48. componentDidUpdate() {
  49. this.updateImage()
  50. }
  51. render() {
  52. return <div
  53. className='molstar-image-canvas'
  54. style={{
  55. width: this.state.width + 6,
  56. height: this.state.height + 6,
  57. margin: 10,
  58. display: 'inline-block',
  59. border: '3px white solid',
  60. }}
  61. >
  62. <canvas
  63. ref={elm => this.canvas = elm}
  64. style={{
  65. width: this.state.width,
  66. height: this.state.height,
  67. imageRendering: 'pixelated'
  68. }}
  69. />
  70. </div>;
  71. }
  72. }