threepipe
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BasicSVGRendererPlugin.ts 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import {
  2. AViewerPluginSync,
  3. type IViewerEvent,
  4. ThreeViewer,
  5. uiButton,
  6. uiConfig,
  7. uiFolderContainer,
  8. uiToggle,
  9. } from 'threepipe'
  10. import {BasicSVGRenderer} from './basic/BasicSVGRenderer'
  11. /**
  12. * SVG rendering of 3d objects using SVGRenderer from three/addons
  13. */
  14. @uiFolderContainer('SVG Renderer')
  15. export class BasicSVGRendererPlugin extends AViewerPluginSync {
  16. static readonly PluginType = 'BasicSVGRendererPlugin'
  17. @uiToggle()
  18. enabled = true
  19. @uiConfig()
  20. readonly renderer = new BasicSVGRenderer()
  21. /**
  22. * @param enabled
  23. * @param autoAddToContainer - automatically add the svg to the viewer container and style it same as the viewer is position is absolute
  24. */
  25. constructor(enabled = true, readonly autoAddToContainer = true) {
  26. super()
  27. this._onResize = this._onResize.bind(this)
  28. this.enabled = enabled
  29. this.renderer.domElement.style.position = 'absolute'
  30. this.renderer.domElement.style.display = 'none'
  31. }
  32. protected _lastStyles?: string = undefined
  33. onAdded(viewer: ThreeViewer) {
  34. super.onAdded(viewer)
  35. this.renderer.setSize(viewer.canvas.clientWidth, viewer.canvas.clientHeight)
  36. this._refreshParams()
  37. if (this.autoAddToContainer) {
  38. viewer.container.prepend(this.renderer.domElement) // behind the canvas so that we get pointer events
  39. const element = this.renderer.domElement
  40. element.style.pointerEvents = 'none'
  41. const canvasStyles = getComputedStyle(viewer.canvas)
  42. if (canvasStyles.position === 'absolute') {
  43. this._lastStyles = element.style.cssText
  44. // copy styles from canvas to svg so it looks the same.
  45. element.style.top = canvasStyles.top
  46. element.style.left = canvasStyles.left
  47. element.style.width = canvasStyles.width
  48. element.style.height = canvasStyles.height
  49. // element.style.zIndex = '999999' // svg should be behind the canvas
  50. } else {
  51. this._viewer?.console.warn('BasicSVGRendererPlugin: canvas position should be absolute for proper rendering')
  52. }
  53. viewer.renderManager.addEventListener('resize', this._onResize)
  54. }
  55. this.renderer.domElement.style.display = this.enabled ? '' : 'none'
  56. }
  57. onRemove(viewer: ThreeViewer) {
  58. super.onRemove(viewer)
  59. if (this.autoAddToContainer) {
  60. viewer.container.removeChild(this.renderer.domElement)
  61. }
  62. if (this._lastStyles !== undefined) {
  63. this.renderer.domElement.style.cssText = this._lastStyles
  64. this._lastStyles = undefined
  65. }
  66. viewer.renderManager.removeEventListener('resize', this._onResize)
  67. this.renderer.domElement.style.display = 'none'
  68. }
  69. @uiToggle()
  70. autoRender = true
  71. @uiButton()
  72. render() {
  73. if (!this._viewer) return
  74. if (this.isDisabled()) return
  75. this.renderer.render(this._viewer.scene, this._viewer.scene.mainCamera)
  76. }
  77. @uiButton()
  78. download() {
  79. const svg = this.renderer.domElement.outerHTML
  80. const blob = new Blob([svg], {type: 'image/svg+xml'})
  81. this._viewer?.exportBlob(blob, 'scene.svg')
  82. }
  83. protected _viewerListeners = {
  84. postRender: (_: IViewerEvent)=>{
  85. if (this.autoRender) this.render()
  86. },
  87. }
  88. get svgNode() {
  89. return this.renderer.domElement
  90. }
  91. protected _refreshParams() {
  92. if (this.isDisabled()) return
  93. this.renderer.setQuality('medium')
  94. }
  95. protected _onResize() {
  96. if (!this._viewer) return
  97. this.renderer.setSize(this._viewer.canvas.clientWidth, this._viewer.canvas.clientHeight)
  98. }
  99. }