Label.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. /*global define*/
  2. define([
  3. '../Core/Cartesian2',
  4. '../Core/Cartesian3',
  5. '../Core/Color',
  6. '../Core/defaultValue',
  7. '../Core/defined',
  8. '../Core/defineProperties',
  9. '../Core/DeveloperError',
  10. '../Core/NearFarScalar',
  11. './Billboard',
  12. './HorizontalOrigin',
  13. './LabelStyle',
  14. './VerticalOrigin'
  15. ], function(
  16. Cartesian2,
  17. Cartesian3,
  18. Color,
  19. defaultValue,
  20. defined,
  21. defineProperties,
  22. DeveloperError,
  23. NearFarScalar,
  24. Billboard,
  25. HorizontalOrigin,
  26. LabelStyle,
  27. VerticalOrigin) {
  28. "use strict";
  29. function rebindAllGlyphs(label) {
  30. if (!label._rebindAllGlyphs && !label._repositionAllGlyphs) {
  31. // only push label if it's not already been marked dirty
  32. label._labelCollection._labelsToUpdate.push(label);
  33. }
  34. label._rebindAllGlyphs = true;
  35. }
  36. function repositionAllGlyphs(label) {
  37. if (!label._rebindAllGlyphs && !label._repositionAllGlyphs) {
  38. // only push label if it's not already been marked dirty
  39. label._labelCollection._labelsToUpdate.push(label);
  40. }
  41. label._repositionAllGlyphs = true;
  42. }
  43. /**
  44. * A Label draws viewport-aligned text positioned in the 3D scene. This constructor
  45. * should not be used directly, instead create labels by calling {@link LabelCollection#add}.
  46. *
  47. * @alias Label
  48. * @internalConstructor
  49. *
  50. * @exception {DeveloperError} translucencyByDistance.far must be greater than translucencyByDistance.near
  51. * @exception {DeveloperError} pixelOffsetScaleByDistance.far must be greater than pixelOffsetScaleByDistance.near
  52. *
  53. * @see LabelCollection
  54. * @see LabelCollection#add
  55. *
  56. * @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Labels.html|Cesium Sandcastle Labels Demo}
  57. */
  58. var Label = function(options, labelCollection) {
  59. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  60. //>>includeStart('debug', pragmas.debug);
  61. if (defined(options.translucencyByDistance) && options.translucencyByDistance.far <= options.translucencyByDistance.near) {
  62. throw new DeveloperError('translucencyByDistance.far must be greater than translucencyByDistance.near.');
  63. }
  64. if (defined(options.pixelOffsetScaleByDistance) && options.pixelOffsetScaleByDistance.far <= options.pixelOffsetScaleByDistance.near) {
  65. throw new DeveloperError('pixelOffsetScaleByDistance.far must be greater than pixelOffsetScaleByDistance.near.');
  66. }
  67. //>>includeEnd('debug');
  68. this._text = defaultValue(options.text, '');
  69. this._show = defaultValue(options.show, true);
  70. this._font = defaultValue(options.font, '30px sans-serif');
  71. this._fillColor = Color.clone(defaultValue(options.fillColor, Color.WHITE));
  72. this._outlineColor = Color.clone(defaultValue(options.outlineColor, Color.BLACK));
  73. this._outlineWidth = defaultValue(options.outlineWidth, 1.0);
  74. this._style = defaultValue(options.style, LabelStyle.FILL);
  75. this._verticalOrigin = defaultValue(options.verticalOrigin, VerticalOrigin.BOTTOM);
  76. this._horizontalOrigin = defaultValue(options.horizontalOrigin, HorizontalOrigin.LEFT);
  77. this._pixelOffset = Cartesian2.clone(defaultValue(options.pixelOffset, Cartesian2.ZERO));
  78. this._eyeOffset = Cartesian3.clone(defaultValue(options.eyeOffset, Cartesian3.ZERO));
  79. this._position = Cartesian3.clone(defaultValue(options.position, Cartesian3.ZERO));
  80. this._scale = defaultValue(options.scale, 1.0);
  81. this._id = options.id;
  82. this._translucencyByDistance = options.translucencyByDistance;
  83. this._pixelOffsetScaleByDistance = options.pixelOffsetScaleByDistance;
  84. this._labelCollection = labelCollection;
  85. this._glyphs = [];
  86. this._rebindAllGlyphs = true;
  87. this._repositionAllGlyphs = true;
  88. };
  89. defineProperties(Label.prototype, {
  90. /**
  91. * Determines if this label will be shown. Use this to hide or show a label, instead
  92. * of removing it and re-adding it to the collection.
  93. * @memberof Label.prototype
  94. * @type {Boolean}
  95. */
  96. show : {
  97. get : function() {
  98. return this._show;
  99. },
  100. set : function(value) {
  101. //>>includeStart('debug', pragmas.debug);
  102. if (!defined(value)) {
  103. throw new DeveloperError('value is required.');
  104. }
  105. //>>includeEnd('debug');
  106. if (this._show !== value) {
  107. this._show = value;
  108. var glyphs = this._glyphs;
  109. for (var i = 0, len = glyphs.length; i < len; i++) {
  110. var glyph = glyphs[i];
  111. if (defined(glyph.billboard)) {
  112. glyph.billboard.show = value;
  113. }
  114. }
  115. }
  116. }
  117. },
  118. /**
  119. * Gets or sets the Cartesian position of this label.
  120. * @memberof Label.prototype
  121. * @type {Cartesian3}
  122. */
  123. position : {
  124. get : function() {
  125. return this._position;
  126. },
  127. set : function(value) {
  128. //>>includeStart('debug', pragmas.debug);
  129. if (!defined(value)) {
  130. throw new DeveloperError('value is required.');
  131. }
  132. //>>includeEnd('debug');
  133. var position = this._position;
  134. if (!Cartesian3.equals(position, value)) {
  135. Cartesian3.clone(value, position);
  136. var glyphs = this._glyphs;
  137. for (var i = 0, len = glyphs.length; i < len; i++) {
  138. var glyph = glyphs[i];
  139. if (defined(glyph.billboard)) {
  140. glyph.billboard.position = value;
  141. }
  142. }
  143. }
  144. }
  145. },
  146. /**
  147. * Gets or sets the text of this label.
  148. * @memberof Label.prototype
  149. * @type {String}
  150. */
  151. text : {
  152. get : function() {
  153. return this._text;
  154. },
  155. set : function(value) {
  156. //>>includeStart('debug', pragmas.debug);
  157. if (!defined(value)) {
  158. throw new DeveloperError('value is required.');
  159. }
  160. //>>includeEnd('debug');
  161. if (this._text !== value) {
  162. this._text = value;
  163. rebindAllGlyphs(this);
  164. }
  165. }
  166. },
  167. /**
  168. * Gets or sets the font used to draw this label. Fonts are specified using the same syntax as the CSS 'font' property.
  169. * @memberof Label.prototype
  170. * @type {String}
  171. * @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles|HTML canvas 2D context text styles}
  172. */
  173. font : {
  174. get : function() {
  175. return this._font;
  176. },
  177. set : function(value) {
  178. //>>includeStart('debug', pragmas.debug);
  179. if (!defined(value)) {
  180. throw new DeveloperError('value is required.');
  181. }
  182. //>>includeEnd('debug');
  183. if (this._font !== value) {
  184. this._font = value;
  185. rebindAllGlyphs(this);
  186. }
  187. }
  188. },
  189. /**
  190. * Gets or sets the fill color of this label.
  191. * @memberof Label.prototype
  192. * @type {Color}
  193. * @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#fill-and-stroke-styles|HTML canvas 2D context fill and stroke styles}
  194. */
  195. fillColor : {
  196. get : function() {
  197. return this._fillColor;
  198. },
  199. set : function(value) {
  200. //>>includeStart('debug', pragmas.debug);
  201. if (!defined(value)) {
  202. throw new DeveloperError('value is required.');
  203. }
  204. //>>includeEnd('debug');
  205. var fillColor = this._fillColor;
  206. if (!Color.equals(fillColor, value)) {
  207. Color.clone(value, fillColor);
  208. rebindAllGlyphs(this);
  209. }
  210. }
  211. },
  212. /**
  213. * Gets or sets the outline color of this label.
  214. * @memberof Label.prototype
  215. * @type {Color}
  216. * @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#fill-and-stroke-styles|HTML canvas 2D context fill and stroke styles}
  217. */
  218. outlineColor : {
  219. get : function() {
  220. return this._outlineColor;
  221. },
  222. set : function(value) {
  223. //>>includeStart('debug', pragmas.debug);
  224. if (!defined(value)) {
  225. throw new DeveloperError('value is required.');
  226. }
  227. //>>includeEnd('debug');
  228. var outlineColor = this._outlineColor;
  229. if (!Color.equals(outlineColor, value)) {
  230. Color.clone(value, outlineColor);
  231. rebindAllGlyphs(this);
  232. }
  233. }
  234. },
  235. /**
  236. * Gets or sets the outline width of this label.
  237. * @memberof Label.prototype
  238. * @type {Number}
  239. * @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#fill-and-stroke-styles|HTML canvas 2D context fill and stroke styles}
  240. */
  241. outlineWidth : {
  242. get : function() {
  243. return this._outlineWidth;
  244. },
  245. set : function(value) {
  246. //>>includeStart('debug', pragmas.debug);
  247. if (!defined(value)) {
  248. throw new DeveloperError('value is required.');
  249. }
  250. //>>includeEnd('debug');
  251. if (this._outlineWidth !== value) {
  252. this._outlineWidth = value;
  253. rebindAllGlyphs(this);
  254. }
  255. }
  256. },
  257. /**
  258. * Gets or sets the style of this label.
  259. * @memberof Label.prototype
  260. * @type {LabelStyle}
  261. */
  262. style : {
  263. get : function() {
  264. return this._style;
  265. },
  266. set : function(value) {
  267. //>>includeStart('debug', pragmas.debug);
  268. if (!defined(value)) {
  269. throw new DeveloperError('value is required.');
  270. }
  271. //>>includeEnd('debug');
  272. if (this._style !== value) {
  273. this._style = value;
  274. rebindAllGlyphs(this);
  275. }
  276. }
  277. },
  278. /**
  279. * Gets or sets the pixel offset in screen space from the origin of this label. This is commonly used
  280. * to align multiple labels and billboards at the same position, e.g., an image and text. The
  281. * screen space origin is the top, left corner of the canvas; <code>x</code> increases from
  282. * left to right, and <code>y</code> increases from top to bottom.
  283. * <br /><br />
  284. * <div align='center'>
  285. * <table border='0' cellpadding='5'><tr>
  286. * <td align='center'><code>default</code><br/><img src='images/Label.setPixelOffset.default.png' width='250' height='188' /></td>
  287. * <td align='center'><code>l.pixeloffset = new Cartesian2(25, 75);</code><br/><img src='images/Label.setPixelOffset.x50y-25.png' width='250' height='188' /></td>
  288. * </tr></table>
  289. * The label's origin is indicated by the yellow point.
  290. * </div>
  291. * @memberof Label.prototype
  292. * @type {Cartesian2}
  293. */
  294. pixelOffset : {
  295. get : function() {
  296. return this._pixelOffset;
  297. },
  298. set : function(value) {
  299. //>>includeStart('debug', pragmas.debug);
  300. if (!defined(value)) {
  301. throw new DeveloperError('value is required.');
  302. }
  303. //>>includeEnd('debug');
  304. var pixelOffset = this._pixelOffset;
  305. if (!Cartesian2.equals(pixelOffset, value)) {
  306. Cartesian2.clone(value, pixelOffset);
  307. var glyphs = this._glyphs;
  308. for (var i = 0, len = glyphs.length; i < len; i++) {
  309. var glyph = glyphs[i];
  310. if (defined(glyph.billboard)) {
  311. glyph.billboard.pixelOffset = value;
  312. }
  313. }
  314. }
  315. }
  316. },
  317. /**
  318. * Gets or sets near and far translucency properties of a Label based on the Label's distance from the camera.
  319. * A label's translucency will interpolate between the {@link NearFarScalar#nearValue} and
  320. * {@link NearFarScalar#farValue} while the camera distance falls within the upper and lower bounds
  321. * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
  322. * Outside of these ranges the label's translucency remains clamped to the nearest bound. If undefined,
  323. * translucencyByDistance will be disabled.
  324. * @memberof Label.prototype
  325. * @type {NearFarScalar}
  326. *
  327. * @example
  328. * // Example 1.
  329. * // Set a label's translucencyByDistance to 1.0 when the
  330. * // camera is 1500 meters from the label and disappear as
  331. * // the camera distance approaches 8.0e6 meters.
  332. * text.translucencyByDistance = new Cesium.NearFarScalar(1.5e2, 1.0, 8.0e6, 0.0);
  333. *
  334. * @example
  335. * // Example 2.
  336. * // disable translucency by distance
  337. * text.translucencyByDistance = undefined;
  338. */
  339. translucencyByDistance : {
  340. get : function() {
  341. return this._translucencyByDistance;
  342. },
  343. set : function(value) {
  344. //>>includeStart('debug', pragmas.debug);
  345. if (defined(value) && value.far <= value.near) {
  346. throw new DeveloperError('far distance must be greater than near distance.');
  347. }
  348. //>>includeEnd('debug');
  349. var translucencyByDistance = this._translucencyByDistance;
  350. if (!NearFarScalar.equals(translucencyByDistance, value)) {
  351. this._translucencyByDistance = NearFarScalar.clone(value, translucencyByDistance);
  352. var glyphs = this._glyphs;
  353. for (var i = 0, len = glyphs.length; i < len; i++) {
  354. var glyph = glyphs[i];
  355. if (defined(glyph.billboard)) {
  356. glyph.billboard.translucencyByDistance = value;
  357. }
  358. }
  359. }
  360. }
  361. },
  362. /**
  363. * Gets or sets near and far pixel offset scaling properties of a Label based on the Label's distance from the camera.
  364. * A label's pixel offset will be scaled between the {@link NearFarScalar#nearValue} and
  365. * {@link NearFarScalar#farValue} while the camera distance falls within the upper and lower bounds
  366. * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.
  367. * Outside of these ranges the label's pixel offset scaling remains clamped to the nearest bound. If undefined,
  368. * pixelOffsetScaleByDistance will be disabled.
  369. * @memberof Label.prototype
  370. * @type {NearFarScalar}
  371. *
  372. * @example
  373. * // Example 1.
  374. * // Set a label's pixel offset scale to 0.0 when the
  375. * // camera is 1500 meters from the label and scale pixel offset to 10.0 pixels
  376. * // in the y direction the camera distance approaches 8.0e6 meters.
  377. * text.pixelOffset = new Cesium.Cartesian2(0.0, 1.0);
  378. * text.pixelOffsetScaleByDistance = new Cesium.NearFarScalar(1.5e2, 0.0, 8.0e6, 10.0);
  379. *
  380. * @example
  381. * // Example 2.
  382. * // disable pixel offset by distance
  383. * text.pixelOffsetScaleByDistance = undefined;
  384. */
  385. pixelOffsetScaleByDistance : {
  386. get : function() {
  387. return this._pixelOffsetScaleByDistance;
  388. },
  389. set : function(value) {
  390. //>>includeStart('debug', pragmas.debug);
  391. if (defined(value) && value.far <= value.near) {
  392. throw new DeveloperError('far distance must be greater than near distance.');
  393. }
  394. //>>includeEnd('debug');
  395. var pixelOffsetScaleByDistance = this._pixelOffsetScaleByDistance;
  396. if (!NearFarScalar.equals(pixelOffsetScaleByDistance, value)) {
  397. this._pixelOffsetScaleByDistance = NearFarScalar.clone(value, pixelOffsetScaleByDistance);
  398. var glyphs = this._glyphs;
  399. for (var i = 0, len = glyphs.length; i < len; i++) {
  400. var glyph = glyphs[i];
  401. if (defined(glyph.billboard)) {
  402. glyph.billboard.pixelOffsetScaleByDistance = value;
  403. }
  404. }
  405. }
  406. }
  407. },
  408. /**
  409. * Gets and sets the 3D Cartesian offset applied to this label in eye coordinates. Eye coordinates is a left-handed
  410. * coordinate system, where <code>x</code> points towards the viewer's right, <code>y</code> points up, and
  411. * <code>z</code> points into the screen. Eye coordinates use the same scale as world and model coordinates,
  412. * which is typically meters.
  413. * <br /><br />
  414. * An eye offset is commonly used to arrange multiple label or objects at the same position, e.g., to
  415. * arrange a label above its corresponding 3D model.
  416. * <br /><br />
  417. * Below, the label is positioned at the center of the Earth but an eye offset makes it always
  418. * appear on top of the Earth regardless of the viewer's or Earth's orientation.
  419. * <br /><br />
  420. * <div align='center'>
  421. * <table border='0' cellpadding='5'><tr>
  422. * <td align='center'><img src='images/Billboard.setEyeOffset.one.png' width='250' height='188' /></td>
  423. * <td align='center'><img src='images/Billboard.setEyeOffset.two.png' width='250' height='188' /></td>
  424. * </tr></table>
  425. * <code>l.eyeOffset = new Cartesian3(0.0, 8000000.0, 0.0);</code><br /><br />
  426. * </div>
  427. * @memberof Label.prototype
  428. * @type {Cartesian3}
  429. */
  430. eyeOffset : {
  431. get : function() {
  432. return this._eyeOffset;
  433. },
  434. set : function(value) {
  435. //>>includeStart('debug', pragmas.debug);
  436. if (!defined(value)) {
  437. throw new DeveloperError('value is required.');
  438. }
  439. //>>includeEnd('debug');
  440. var eyeOffset = this._eyeOffset;
  441. if (!Cartesian3.equals(eyeOffset, value)) {
  442. Cartesian3.clone(value, eyeOffset);
  443. var glyphs = this._glyphs;
  444. for (var i = 0, len = glyphs.length; i < len; i++) {
  445. var glyph = glyphs[i];
  446. if (defined(glyph.billboard)) {
  447. glyph.billboard.eyeOffset = value;
  448. }
  449. }
  450. }
  451. }
  452. },
  453. /**
  454. * Gets or sets the horizontal origin of this label, which determines if the label is drawn
  455. * to the left, center, or right of its position.
  456. * <br /><br />
  457. * <div align='center'>
  458. * <img src='images/Billboard.setHorizontalOrigin.png' width='400' height='300' /><br />
  459. * </div>
  460. * @memberof Label.prototype
  461. * @type {HorizontalOrigin}
  462. * @example
  463. * // Use a top, right origin
  464. * l.horizontalOrigin = Cesium.HorizontalOrigin.RIGHT;
  465. * l.verticalOrigin = Cesium.VerticalOrigin.TOP;
  466. */
  467. horizontalOrigin : {
  468. get : function() {
  469. return this._horizontalOrigin;
  470. },
  471. set : function(value) {
  472. //>>includeStart('debug', pragmas.debug);
  473. if (!defined(value)) {
  474. throw new DeveloperError('value is required.');
  475. }
  476. //>>includeEnd('debug');
  477. if (this._horizontalOrigin !== value) {
  478. this._horizontalOrigin = value;
  479. repositionAllGlyphs(this);
  480. }
  481. }
  482. },
  483. /**
  484. * Gets or sets the vertical origin of this label, which determines if the label is
  485. * to the above, below, or at the center of its position.
  486. * <br /><br />
  487. * <div align='center'>
  488. * <img src='images/Billboard.setVerticalOrigin.png' width='400' height='300' /><br />
  489. * </div>
  490. * @memberof Label.prototype
  491. * @type {VerticalOrigin}
  492. * @example
  493. * // Use a top, right origin
  494. * l.horizontalOrigin = Cesium.HorizontalOrigin.RIGHT;
  495. * l.verticalOrigin = Cesium.VerticalOrigin.TOP;
  496. */
  497. verticalOrigin : {
  498. get : function() {
  499. return this._verticalOrigin;
  500. },
  501. set : function(value) {
  502. //>>includeStart('debug', pragmas.debug);
  503. if (!defined(value)) {
  504. throw new DeveloperError('value is required.');
  505. }
  506. //>>includeEnd('debug');
  507. if (this._verticalOrigin !== value) {
  508. this._verticalOrigin = value;
  509. var glyphs = this._glyphs;
  510. for (var i = 0, len = glyphs.length; i < len; i++) {
  511. var glyph = glyphs[i];
  512. if (defined(glyph.billboard)) {
  513. glyph.billboard.verticalOrigin = value;
  514. }
  515. }
  516. repositionAllGlyphs(this);
  517. }
  518. }
  519. },
  520. /**
  521. * Gets or sets the uniform scale that is multiplied with the label's size in pixels.
  522. * A scale of <code>1.0</code> does not change the size of the label; a scale greater than
  523. * <code>1.0</code> enlarges the label; a positive scale less than <code>1.0</code> shrinks
  524. * the label.
  525. * <br /><br />
  526. * Applying a large scale value may pixelate the label. To make text larger without pixelation,
  527. * use a larger font size when calling {@link Label#font} instead.
  528. * <br /><br />
  529. * <div align='center'>
  530. * <img src='images/Label.setScale.png' width='400' height='300' /><br/>
  531. * From left to right in the above image, the scales are <code>0.5</code>, <code>1.0</code>,
  532. * and <code>2.0</code>.
  533. * </div>
  534. * @memberof Label.prototype
  535. * @type {Number}
  536. */
  537. scale : {
  538. get : function() {
  539. return this._scale;
  540. },
  541. set : function(value) {
  542. //>>includeStart('debug', pragmas.debug);
  543. if (!defined(value)) {
  544. throw new DeveloperError('value is required.');
  545. }
  546. //>>includeEnd('debug');
  547. if (this._scale !== value) {
  548. this._scale = value;
  549. var glyphs = this._glyphs;
  550. for (var i = 0, len = glyphs.length; i < len; i++) {
  551. var glyph = glyphs[i];
  552. if (defined(glyph.billboard)) {
  553. glyph.billboard.scale = value;
  554. }
  555. }
  556. repositionAllGlyphs(this);
  557. }
  558. }
  559. },
  560. /**
  561. * Gets or sets the user-defined object returned when the label is picked.
  562. * @memberof Label.prototype
  563. * @type {Object}
  564. */
  565. id : {
  566. get : function() {
  567. return this._id;
  568. },
  569. set : function(value) {
  570. if (this._id !== value) {
  571. this._id = value;
  572. var glyphs = this._glyphs;
  573. for (var i = 0, len = glyphs.length; i < len; i++) {
  574. var glyph = glyphs[i];
  575. if (defined(glyph.billboard)) {
  576. glyph.billboard.id = value;
  577. }
  578. }
  579. }
  580. }
  581. }
  582. });
  583. /**
  584. * Computes the screen-space position of the label's origin, taking into account eye and pixel offsets.
  585. * The screen space origin is the top, left corner of the canvas; <code>x</code> increases from
  586. * left to right, and <code>y</code> increases from top to bottom.
  587. *
  588. * @param {Scene} scene The scene the label is in.
  589. * @returns {Cartesian2} The screen-space position of the label.
  590. *
  591. * @see Label#eyeOffset
  592. * @see Label#pixelOffset
  593. *
  594. * @example
  595. * console.log(l.computeScreenSpacePosition(scene).toString());
  596. */
  597. Label.prototype.computeScreenSpacePosition = function(scene) {
  598. //>>includeStart('debug', pragmas.debug);
  599. if (!defined(scene)) {
  600. throw new DeveloperError('context is required.');
  601. }
  602. //>>includeEnd('debug');
  603. var labelCollection = this._labelCollection;
  604. var modelMatrix = labelCollection.modelMatrix;
  605. var actualPosition = Billboard._computeActualPosition(this._position, scene.frameState, modelMatrix);
  606. var windowCoordinates = Billboard._computeScreenSpacePosition(modelMatrix, actualPosition, this._eyeOffset, this._pixelOffset, scene);
  607. windowCoordinates.y = scene.canvas.clientHeight - windowCoordinates.y;
  608. return windowCoordinates;
  609. };
  610. /**
  611. * Determines if this label equals another label. Labels are equal if all their properties
  612. * are equal. Labels in different collections can be equal.
  613. *
  614. * @param {Label} other The label to compare for equality.
  615. * @returns {Boolean} <code>true</code> if the labels are equal; otherwise, <code>false</code>.
  616. */
  617. Label.prototype.equals = function(other) {
  618. return this === other ||
  619. defined(other) &&
  620. this._show === other._show &&
  621. this._scale === other._scale &&
  622. this._style === other._style &&
  623. this._verticalOrigin === other._verticalOrigin &&
  624. this._horizontalOrigin === other._horizontalOrigin &&
  625. this._text === other._text &&
  626. this._font === other._font &&
  627. Cartesian3.equals(this._position, other._position) &&
  628. Color.equals(this._fillColor, other._fillColor) &&
  629. Color.equals(this._outlineColor, other._outlineColor) &&
  630. Cartesian2.equals(this._pixelOffset, other._pixelOffset) &&
  631. Cartesian3.equals(this._eyeOffset, other._eyeOffset) &&
  632. NearFarScalar.equals(this._translucencyByDistance, other._translucencyByDistance) &&
  633. NearFarScalar.equals(this._pixelOffsetScaleByDistance, other._pixelOffsetScaleByDistance) &&
  634. this._id === other._id;
  635. };
  636. /**
  637. * Returns true if this object was destroyed; otherwise, false.
  638. * <br /><br />
  639. * If this object was destroyed, it should not be used; calling any function other than
  640. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
  641. *
  642. * @returns {Boolean} True if this object was destroyed; otherwise, false.
  643. */
  644. Label.prototype.isDestroyed = function() {
  645. return false;
  646. };
  647. return Label;
  648. });