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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /**
  2. * @Author: Caven
  3. * @Date: 2020-02-12 21:46:22
  4. */
  5. import { Cesium } from '@dc-modules/namespace'
  6. import State from '@dc-modules/state/State'
  7. import Parse from '@dc-modules/parse/Parse'
  8. import { DomUtil, Util } from '@dc-modules/utils'
  9. import { MouseEventType } from '@dc-modules/event'
  10. import { isBetween } from '@dc-modules/math'
  11. import { Transform } from '@dc-modules/transform'
  12. import Overlay from '../Overlay'
  13. class DivIcon extends Overlay {
  14. constructor(position, content) {
  15. super()
  16. this._delegate = DomUtil.create('div', 'div-icon')
  17. this._position = Parse.parsePosition(position)
  18. this._delegate.setAttribute('id', this._id)
  19. Util.merge(this._delegate.style, {
  20. position: 'absolute',
  21. top: '0',
  22. left: '0'
  23. })
  24. this.content = content
  25. this._state = State.INITIALIZED
  26. }
  27. get type() {
  28. return Overlay.getOverlayType('div_icon')
  29. }
  30. set show(show) {
  31. this._show = show
  32. this._delegate.style.visibility = this._show ? 'visible' : 'hidden'
  33. return this
  34. }
  35. get show() {
  36. return this._show
  37. }
  38. set position(position) {
  39. this._position = Parse.parsePosition(position)
  40. return this
  41. }
  42. get position() {
  43. return this._position
  44. }
  45. set content(content) {
  46. if (content && typeof content === 'string') {
  47. this._delegate.innerHTML = content
  48. } else if (content && content instanceof Element) {
  49. while (this._delegate.hasChildNodes()) {
  50. this._delegate.removeChild(this._delegate.firstChild)
  51. }
  52. this._delegate.appendChild(content)
  53. }
  54. return this
  55. }
  56. get content() {
  57. return this._delegate.childNodes || []
  58. }
  59. /**
  60. * Updates style
  61. * @param windowCoord
  62. * @param distance
  63. * @param isFront
  64. * @private
  65. */
  66. _updateStyle(windowCoord, distance, isFront) {
  67. if (!this._show || !windowCoord) {
  68. return
  69. }
  70. // set translate
  71. let x = windowCoord.x - this._delegate.offsetWidth / 2
  72. let y = windowCoord.y - this._delegate.offsetHeight / 2
  73. if (this._style.position === 'topleft') {
  74. x = windowCoord.x - this._delegate.offsetWidth
  75. y = windowCoord.y - this._delegate.offsetHeight
  76. } else if (this._style.position === 'topright') {
  77. x = windowCoord.x
  78. y = windowCoord.y - this._delegate.offsetHeight
  79. } else if (this._style.position === 'bottomleft') {
  80. x = windowCoord.x - this._delegate.offsetWidth
  81. y = windowCoord.y
  82. } else if (this._style.position === 'bottomright') {
  83. x = windowCoord.x
  84. y = windowCoord.y
  85. }
  86. let translate3d = `translate3d(${Math.round(x)}px,${Math.round(y)}px, 0)`
  87. // set scale
  88. let scale3d = 'scale3d(1,1,1)'
  89. let scaleByDistance = this._style.scaleByDistance
  90. if (distance && scaleByDistance) {
  91. let near = scaleByDistance.near || 0.0
  92. let nearValue = scaleByDistance.nearValue || 1.0
  93. let far = scaleByDistance.far || Number.MAX_VALUE
  94. let farValue = scaleByDistance.farValue || 0.0
  95. let f = distance / far
  96. if (distance < near) {
  97. scale3d = `scale3d(${nearValue},${nearValue},1)`
  98. } else if (distance > far) {
  99. scale3d = `scale3d(${farValue},${farValue},1)`
  100. } else {
  101. let scale = farValue + f * (nearValue - farValue)
  102. scale3d = `scale3d(${scale},${scale},1)`
  103. }
  104. }
  105. // set condition
  106. let isDisplay = true
  107. let distanceDisplayCondition = this._style.distanceDisplayCondition
  108. if (distance && distanceDisplayCondition) {
  109. isDisplay = isBetween(
  110. distance,
  111. distanceDisplayCondition.near || 0.0,
  112. distanceDisplayCondition.far || Number.MAX_VALUE
  113. )
  114. }
  115. // update style
  116. this._delegate.style.transform = `${translate3d} ${scale3d}`
  117. this._delegate.style.visibility =
  118. isDisplay && isFront ? 'visible' : 'hidden'
  119. }
  120. /**
  121. *
  122. * @param layer
  123. * @returns {boolean}
  124. * @private
  125. */
  126. _onAdd(layer) {
  127. this._layer = layer
  128. this._layer.delegate.appendChild(this._delegate)
  129. let params = {
  130. layer: layer,
  131. overlay: this,
  132. position: Transform.transformWGS84ToCartesian(this._position)
  133. }
  134. this._delegate.addEventListener('click', () => {
  135. this._overlayEvent.fire(MouseEventType.CLICK, params)
  136. })
  137. this._delegate.addEventListener('mouseover', () => {
  138. this._overlayEvent.fire(MouseEventType.MOUSE_OVER, params)
  139. })
  140. this._delegate.addEventListener('mouseout', () => {
  141. this._overlayEvent.fire(MouseEventType.MOUSE_OUT, params)
  142. })
  143. this._state = State.ADDED
  144. }
  145. /**
  146. *
  147. * @private
  148. */
  149. _onRemove() {
  150. if (this._layer) {
  151. this._layer.delegate.removeChild(this._delegate)
  152. this._state = State.REMOVED
  153. }
  154. }
  155. /**
  156. * Sets text
  157. * @param text
  158. * @param textStyle
  159. * @returns {DivIcon}
  160. */
  161. setLabel(text, textStyle) {
  162. return this
  163. }
  164. /**
  165. * Sets style
  166. * @param style
  167. * @returns {DivIcon}
  168. */
  169. setStyle(style) {
  170. if (!style || Object.keys(style).length === 0) {
  171. return this
  172. }
  173. Util.merge(this._style, style)
  174. this._style.className &&
  175. DomUtil.addClass(this._delegate, this._style.className)
  176. return this
  177. }
  178. /**
  179. * Parse from entity
  180. * @param entity
  181. * @param content
  182. * @returns {DivIcon}
  183. */
  184. static fromEntity(entity, content) {
  185. let divIcon
  186. let now = Cesium.JulianDate.now()
  187. let position = Transform.transformCartesianToWGS84(
  188. entity.position.getValue(now)
  189. )
  190. divIcon = new DivIcon(position, content)
  191. if (entity.billboard) {
  192. divIcon.attr = {
  193. ...entity?.properties?.getValue(now)
  194. }
  195. }
  196. return divIcon
  197. }
  198. }
  199. Overlay.registerType('div_icon')
  200. export default DivIcon