plaque.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /**
  2. * DevExtreme (viz/core/plaque.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. Object.defineProperty(exports, "__esModule", {
  11. value: true
  12. });
  13. exports.Plaque = void 0;
  14. var _extend = require("../../core/utils/extend");
  15. var _type = require("../../core/utils/type");
  16. function _classCallCheck(instance, Constructor) {
  17. if (!(instance instanceof Constructor)) {
  18. throw new TypeError("Cannot call a class as a function")
  19. }
  20. }
  21. function _defineProperties(target, props) {
  22. for (var i = 0; i < props.length; i++) {
  23. var descriptor = props[i];
  24. descriptor.enumerable = descriptor.enumerable || false;
  25. descriptor.configurable = true;
  26. if ("value" in descriptor) {
  27. descriptor.writable = true
  28. }
  29. Object.defineProperty(target, descriptor.key, descriptor)
  30. }
  31. }
  32. function _createClass(Constructor, protoProps, staticProps) {
  33. if (protoProps) {
  34. _defineProperties(Constructor.prototype, protoProps)
  35. }
  36. if (staticProps) {
  37. _defineProperties(Constructor, staticProps)
  38. }
  39. Object.defineProperty(Constructor, "prototype", {
  40. writable: false
  41. });
  42. return Constructor
  43. }
  44. var math = Math;
  45. var round = math.round;
  46. var max = math.max;
  47. var min = math.min;
  48. var sin = math.sin;
  49. var cos = math.cos;
  50. var asin = math.asin;
  51. var PI = math.PI;
  52. var buildPath = function() {
  53. for (var _len = arguments.length, points = new Array(_len), _key = 0; _key < _len; _key++) {
  54. points[_key] = arguments[_key]
  55. }
  56. return points.join("")
  57. };
  58. function getArc(cornerRadius, xDirection, yDirection) {
  59. return "a ".concat(cornerRadius, " ").concat(cornerRadius, " 0 0 1 ").concat(xDirection * cornerRadius, " ").concat(yDirection * cornerRadius)
  60. }
  61. function getAbsoluteArc(cornerRadius, x, y) {
  62. return "A ".concat(cornerRadius, " ").concat(cornerRadius, " 0 0 1 ").concat(x, " ").concat(y)
  63. }
  64. function rotateX(x, y, angle, x0, y0) {
  65. return (x - x0) * round(cos(angle)) + (y - y0) * round(sin(angle)) + x0
  66. }
  67. function rotateY(x, y, angle, x0, y0) {
  68. return -(x - x0) * round(sin(angle)) + (y - y0) * round(cos(angle)) + y0
  69. }
  70. function rotateSize(options, angle) {
  71. if (angle % 90 === 0 && angle % 180 !== 0) {
  72. return {
  73. width: options.height,
  74. height: options.width
  75. }
  76. }
  77. return options
  78. }
  79. function getCloudAngle(_ref, x, y, anchorX, anchorY) {
  80. var width = _ref.width,
  81. height = _ref.height;
  82. var halfWidth = width / 2;
  83. var halfHeight = height / 2;
  84. var xr = Math.ceil(x + halfWidth);
  85. var xl = Math.floor(x - halfWidth);
  86. var yt = Math.floor(y - halfHeight);
  87. var yb = Math.ceil(y + halfHeight);
  88. if (anchorX < xl && anchorY < yt || anchorX >= xl && anchorX <= xr && anchorY < yt) {
  89. return 270
  90. }
  91. if (anchorX > xr && anchorY > yb || anchorX >= xl && anchorX <= xr && anchorY > yb) {
  92. return 90
  93. } else {
  94. if (anchorX < xl && anchorY > yb || anchorX < xl && anchorY >= yt && anchorY <= yb) {
  95. return 180
  96. }
  97. }
  98. return 0
  99. }
  100. function getCloudPoints(_ref2, x, y, anchorX, anchorY, _ref3, bounded) {
  101. var width = _ref2.width,
  102. height = _ref2.height;
  103. var arrowWidth = _ref3.arrowWidth,
  104. _ref3$cornerRadius = _ref3.cornerRadius,
  105. cornerRadius = void 0 === _ref3$cornerRadius ? 0 : _ref3$cornerRadius;
  106. var halfArrowWidth = arrowWidth / 2;
  107. var halfWidth = width / 2;
  108. var halfHeight = height / 2;
  109. var xr = Math.ceil(x + halfWidth);
  110. var xl = Math.floor(x - halfWidth);
  111. var yt = Math.floor(y - halfHeight);
  112. var yb = Math.ceil(y + halfHeight);
  113. var leftTopCorner = [xl, yt];
  114. var rightTopCorner = [xr, yt];
  115. var rightBottomCorner = [xr, yb];
  116. var leftBottomCorner = [xl, yb];
  117. var arrowX = anchorX <= xl ? xl : xr <= anchorX ? xr : anchorX;
  118. var arrowY = anchorY <= yt ? yt : yb <= anchorY ? yb : anchorY;
  119. var arrowBaseBottom = min(arrowY + halfArrowWidth, yb);
  120. var arrowBaseTop = max(arrowY - halfArrowWidth, yt);
  121. var arrowBaseLeft = max(arrowX - halfArrowWidth, xl);
  122. cornerRadius = Math.min(width / 2, height / 2, cornerRadius);
  123. var points;
  124. leftTopCorner[1] += cornerRadius;
  125. rightTopCorner[0] -= cornerRadius;
  126. rightBottomCorner[1] -= cornerRadius;
  127. leftBottomCorner[0] += cornerRadius;
  128. if (!bounded || xl <= anchorX && anchorX <= xr && yt <= anchorY && anchorY <= yb) {
  129. points = buildPath(leftTopCorner, getArc(cornerRadius, 1, -1), "L", rightTopCorner, getArc(cornerRadius, 1, 1), "L", rightBottomCorner, getArc(cornerRadius, -1, 1), "L", leftBottomCorner, getArc(cornerRadius, -1, -1))
  130. } else {
  131. if (anchorX > xr && anchorY < yt) {
  132. var arrowAngle = arrowWidth / cornerRadius || 0;
  133. var angle = PI / 4 + arrowAngle / 2;
  134. var endAngle = PI / 4 - arrowAngle / 2;
  135. var arrowEndPointX = rightTopCorner[0] + cos(endAngle) * cornerRadius;
  136. var arrowEndPointY = rightTopCorner[1] + (1 - sin(endAngle)) * cornerRadius;
  137. var arrowArc = buildPath("L", rightTopCorner, getArc(cornerRadius, cos(angle), 1 - sin(angle)), "L", [anchorX, anchorY, arrowEndPointX, arrowEndPointY], getAbsoluteArc(cornerRadius, rightTopCorner[0] + cornerRadius, rightTopCorner[1] + cornerRadius));
  138. if (Math.abs(angle) > PI / 2) {
  139. arrowArc = buildPath("L", [arrowBaseLeft, yt, anchorX, anchorY, xr, arrowBaseBottom])
  140. }
  141. points = buildPath(leftTopCorner, getArc(cornerRadius, 1, -1), arrowArc, "L", rightBottomCorner, getArc(cornerRadius, -1, 1), "L", leftBottomCorner, getArc(cornerRadius, -1, -1))
  142. } else {
  143. if (anchorX > xr && anchorY >= yt && anchorY <= yb) {
  144. var _arrowArc;
  145. if (arrowBaseTop >= rightTopCorner[1] + cornerRadius && arrowBaseBottom <= rightBottomCorner[1]) {
  146. _arrowArc = buildPath(getArc(cornerRadius, 1, 1), "L", [xr, arrowBaseTop, anchorX, anchorY, xr, arrowBaseBottom], "L", rightBottomCorner, getArc(cornerRadius, -1, 1))
  147. } else {
  148. if (arrowBaseTop < rightTopCorner[1] + cornerRadius && arrowBaseBottom >= rightTopCorner[1] + cornerRadius && arrowBaseBottom <= rightBottomCorner[1]) {
  149. var arrowWidthRest = rightTopCorner[1] + cornerRadius - arrowBaseTop;
  150. var _angle = arrowWidthRest / cornerRadius;
  151. var arrowBaseTopX = rightTopCorner[0] + cos(_angle) * cornerRadius;
  152. var arrowBaseTopY = rightTopCorner[1] + (1 - sin(_angle)) * cornerRadius;
  153. _arrowArc = buildPath(getArc(cornerRadius, cos(_angle), 1 - sin(_angle)), "L", [arrowBaseTopX, arrowBaseTopY, anchorX, anchorY, xr, arrowBaseBottom], "L", rightBottomCorner, getArc(cornerRadius, -1, 1))
  154. } else {
  155. if (arrowBaseTop < rightTopCorner[1] + cornerRadius && arrowBaseBottom < rightTopCorner[1] + cornerRadius) {
  156. var _arrowWidthRest = rightTopCorner[1] + cornerRadius - arrowBaseTop;
  157. var _arrowAngle = _arrowWidthRest / cornerRadius;
  158. var _angle2 = _arrowAngle;
  159. var _arrowBaseTopX = rightTopCorner[0] + cos(_angle2) * cornerRadius;
  160. var _arrowBaseTopY = rightTopCorner[1] + (1 - sin(_angle2)) * cornerRadius;
  161. var bottomAngle = Math.sin((rightTopCorner[1] + cornerRadius - arrowBaseBottom) / cornerRadius);
  162. var arrowBaseBottomX = rightTopCorner[0] + cornerRadius * cos(bottomAngle);
  163. var arrowBaseBottomY = rightTopCorner[1] + cornerRadius * (1 - sin(bottomAngle));
  164. _arrowArc = buildPath(getArc(cornerRadius, cos(_angle2), 1 - sin(_angle2)), "L", [_arrowBaseTopX, _arrowBaseTopY, anchorX, anchorY, arrowBaseBottomX, arrowBaseBottomY], getAbsoluteArc(cornerRadius, rightTopCorner[0] + cornerRadius, rightTopCorner[1] + cornerRadius), "L", rightBottomCorner, getArc(cornerRadius, -1, 1))
  165. } else {
  166. if (arrowBaseTop <= rightTopCorner[1] + cornerRadius && arrowBaseBottom >= rightBottomCorner[1]) {
  167. var topAngle = asin((rightTopCorner[1] + cornerRadius - arrowBaseTop) / cornerRadius);
  168. var _arrowBaseTopX2 = rightTopCorner[0] + cornerRadius * cos(topAngle);
  169. var _arrowBaseTopY2 = rightTopCorner[1] + cornerRadius * (1 - sin(topAngle));
  170. var _bottomAngle = asin((arrowBaseBottom - rightBottomCorner[1]) / cornerRadius);
  171. var _arrowBaseBottomX = rightBottomCorner[0] + cornerRadius * (cos(_bottomAngle) - 1);
  172. var _arrowBaseBottomY = rightBottomCorner[1] + cornerRadius * sin(_bottomAngle);
  173. _arrowArc = buildPath(getArc(cornerRadius, cos(topAngle), 1 - sin(topAngle)), "L", [_arrowBaseTopX2, _arrowBaseTopY2, anchorX, anchorY, _arrowBaseBottomX, _arrowBaseBottomY], getAbsoluteArc(cornerRadius, rightBottomCorner[0] - cornerRadius, rightBottomCorner[1] + cornerRadius))
  174. } else {
  175. if (arrowBaseTop > rightTopCorner[1] + cornerRadius && arrowBaseTop <= rightBottomCorner[1] && arrowBaseBottom > rightBottomCorner[1]) {
  176. var _bottomAngle2 = asin((arrowBaseBottom - rightBottomCorner[1]) / cornerRadius);
  177. var _arrowBaseBottomX2 = rightBottomCorner[0] + cornerRadius * (cos(_bottomAngle2) - 1);
  178. var _arrowBaseBottomY2 = rightBottomCorner[1] + cornerRadius * sin(_bottomAngle2);
  179. _arrowArc = buildPath(getArc(cornerRadius, 1, 1), "L", [xr, arrowBaseTop, anchorX, anchorY, _arrowBaseBottomX2, _arrowBaseBottomY2], getAbsoluteArc(cornerRadius, rightBottomCorner[0] - cornerRadius, rightBottomCorner[1] + cornerRadius))
  180. } else {
  181. if (arrowBaseTop > rightTopCorner[1] + cornerRadius && arrowBaseBottom > rightBottomCorner[1]) {
  182. var _bottomAngle3 = asin((arrowBaseBottom - rightBottomCorner[1]) / cornerRadius);
  183. var _arrowBaseBottomX3 = rightBottomCorner[0] + cornerRadius * (cos(_bottomAngle3) - 1);
  184. var _arrowBaseBottomY3 = rightBottomCorner[1] + cornerRadius * sin(_bottomAngle3);
  185. var _topAngle = asin((arrowBaseTop - rightBottomCorner[1]) / cornerRadius);
  186. var _arrowBaseTopX3 = rightBottomCorner[0] + cornerRadius * (cos(_topAngle) - 1);
  187. var _arrowBaseTopY3 = rightBottomCorner[1] + cornerRadius * sin(_topAngle);
  188. _arrowArc = buildPath(getArc(cornerRadius, 1, 1), "L", rightBottomCorner, getArc(cornerRadius, cos(_topAngle) - 1, sin(_topAngle)), "L", [_arrowBaseTopX3, _arrowBaseTopY3, anchorX, anchorY, _arrowBaseBottomX3, _arrowBaseBottomY3], getAbsoluteArc(cornerRadius, rightBottomCorner[0] - cornerRadius, rightBottomCorner[1] + cornerRadius))
  189. }
  190. }
  191. }
  192. }
  193. }
  194. }
  195. points = buildPath(leftTopCorner, getArc(cornerRadius, 1, -1), "L", rightTopCorner, _arrowArc, "L", leftBottomCorner, getArc(cornerRadius, -1, -1))
  196. }
  197. }
  198. }
  199. return buildPath("M", points, "Z")
  200. }
  201. var Plaque = exports.Plaque = function() {
  202. function Plaque(options, widget, root, renderContent) {
  203. var bounded = arguments.length > 4 && void 0 !== arguments[4] ? arguments[4] : true;
  204. var measureContent = arguments.length > 5 && void 0 !== arguments[5] ? arguments[5] : function(_, g) {
  205. return g.getBBox()
  206. };
  207. var moveContentGroup = arguments.length > 6 && void 0 !== arguments[6] ? arguments[6] : function(_, g, x, y) {
  208. return g.move(x, y)
  209. };
  210. _classCallCheck(this, Plaque);
  211. this.widget = widget;
  212. this.options = options;
  213. this.root = root;
  214. this.renderContent = renderContent;
  215. this.bonded = bounded;
  216. this.measureContent = measureContent;
  217. this.moveContentGroup = moveContentGroup
  218. }
  219. _createClass(Plaque, [{
  220. key: "draw",
  221. value: function(_ref4) {
  222. var anchorX = _ref4.x,
  223. anchorY = _ref4.y,
  224. _ref4$canvas = _ref4.canvas,
  225. canvas = void 0 === _ref4$canvas ? {} : _ref4$canvas,
  226. offsetX = _ref4.offsetX,
  227. offsetY = _ref4.offsetY,
  228. _ref4$offset = _ref4.offset,
  229. offset = void 0 === _ref4$offset ? 0 : _ref4$offset;
  230. var options = this.options;
  231. var x = options.x,
  232. y = options.y;
  233. var bounds = {
  234. xl: canvas.left,
  235. xr: canvas.width - canvas.right,
  236. width: canvas.width - canvas.right - canvas.left,
  237. yt: canvas.top,
  238. yb: canvas.height - canvas.bottom,
  239. height: canvas.height - canvas.bottom - canvas.top
  240. };
  241. if (!((0, _type.isDefined)(anchorX) && (0, _type.isDefined)(anchorY)) && !((0, _type.isDefined)(x) && (0, _type.isDefined)(y))) {
  242. return
  243. }
  244. if ((0, _type.isDefined)(anchorX) && (anchorX < bounds.xl || bounds.xr < anchorX || anchorY < bounds.yt || bounds.yb < anchorY)) {
  245. return
  246. }
  247. if (!this._root) {
  248. this._draw()
  249. }
  250. var shadowSettings = (0, _extend.extend)({
  251. x: "-50%",
  252. y: "-50%",
  253. width: "200%",
  254. height: "200%"
  255. }, options.shadow);
  256. var contentWidth = options.width > 0 ? options.width : null;
  257. var contentHeight = options.height > 0 ? options.height : null;
  258. this.renderContent(this.widget, this._contentGroup, {
  259. width: contentWidth,
  260. height: contentHeight
  261. });
  262. var bBox = this._contentBBox = this.measureContent(this.widget, this._contentGroup);
  263. var size = this._size = {
  264. width: max(contentWidth, bBox.width) + 2 * options.paddingLeftRight,
  265. height: max(contentHeight, bBox.height) + 2 * options.paddingTopBottom,
  266. offset: offset
  267. };
  268. var xOff = shadowSettings.offsetX;
  269. var yOff = shadowSettings.offsetY;
  270. var blur = 2 * shadowSettings.blur + 1;
  271. var lm = max(blur - xOff, 0);
  272. var rm = max(blur + xOff, 0);
  273. var tm = max(blur - yOff, 0);
  274. var bm = max(blur + yOff, 0);
  275. this.margins = {
  276. lm: lm,
  277. rm: rm,
  278. tm: tm,
  279. bm: bm
  280. };
  281. if (!(0, _type.isDefined)(x)) {
  282. if ((0, _type.isDefined)(offsetX)) {
  283. x = anchorX + offsetX
  284. } else {
  285. if (bounds.width < size.width) {
  286. x = round(bounds.xl + bounds.width / 2)
  287. } else {
  288. x = min(max(anchorX, Math.ceil(bounds.xl + size.width / 2 + lm)), Math.floor(bounds.xr - size.width / 2 - rm))
  289. }
  290. }
  291. } else {
  292. x += offsetX || 0;
  293. if (!(0, _type.isDefined)(anchorX)) {
  294. anchorX = x
  295. }
  296. }
  297. if (!(0, _type.isDefined)(y)) {
  298. if ((0, _type.isDefined)(offsetY)) {
  299. y = anchorY + offsetY
  300. } else {
  301. var y_top = anchorY - options.arrowLength - size.height / 2 - offset;
  302. var y_bottom = anchorY + options.arrowLength + size.height / 2 + offset;
  303. if (bounds.height < size.height + options.arrowLength) {
  304. y = round(bounds.yt + size.height / 2)
  305. } else {
  306. if (y_top - size.height / 2 - tm < bounds.yt) {
  307. if (y_bottom + size.height / 2 + bm < bounds.yb) {
  308. y = y_bottom;
  309. anchorY += offset
  310. } else {
  311. y = round(bounds.yt + size.height / 2)
  312. }
  313. } else {
  314. y = y_top;
  315. anchorY -= offset
  316. }
  317. }
  318. }
  319. } else {
  320. y += offsetY || 0;
  321. if (!(0, _type.isDefined)(anchorY)) {
  322. anchorY = y + size.height / 2
  323. }
  324. }
  325. this.anchorX = anchorX;
  326. this.anchorY = anchorY;
  327. this.move(x, y)
  328. }
  329. }, {
  330. key: "_draw",
  331. value: function() {
  332. var renderer = this.widget._renderer;
  333. var options = this.options;
  334. var cloudSettings = {
  335. opacity: options.opacity,
  336. "stroke-width": 0,
  337. fill: options.color
  338. };
  339. var borderOptions = options.border || {};
  340. if (borderOptions.visible) {
  341. (0, _extend.extend)(cloudSettings, {
  342. "stroke-width": borderOptions.width,
  343. stroke: borderOptions.color,
  344. "stroke-opacity": borderOptions.opacity,
  345. dashStyle: borderOptions.dashStyle
  346. })
  347. }
  348. var shadowSettings = (0, _extend.extend)({
  349. x: "-50%",
  350. y: "-50%",
  351. width: "200%",
  352. height: "200%"
  353. }, options.shadow);
  354. var shadow = this._shadow = renderer.shadowFilter().attr(shadowSettings);
  355. var group = this._root = renderer.g().append(this.root);
  356. if (options.type) {
  357. group.attr({
  358. "class": "dxc-".concat(options.type, "-annotation")
  359. })
  360. }
  361. var cloudGroup = renderer.g().attr({
  362. filter: shadow.id
  363. }).append(group);
  364. this._cloud = renderer.path([], "area").attr(cloudSettings).sharp().append(cloudGroup);
  365. this._contentGroup = renderer.g().append(group)
  366. }
  367. }, {
  368. key: "getBBox",
  369. value: function() {
  370. var size = this._size || {};
  371. var margins = this.margins || {};
  372. var rotationAngle = getCloudAngle(size, this.x, this.y, this.anchorX, this.anchorY);
  373. return {
  374. x: Math.floor(this.x - size.width / 2 - margins.lm),
  375. y: Math.floor(this.y - size.height / 2 - margins.tm - (270 === rotationAngle ? this.options.arrowLength : 0)),
  376. width: size.width + margins.lm + margins.rm,
  377. height: size.height + margins.tm + margins.bm + (90 === rotationAngle || 270 === rotationAngle ? this.options.arrowLength : 0)
  378. }
  379. }
  380. }, {
  381. key: "clear",
  382. value: function() {
  383. if (this._root) {
  384. this._root.remove();
  385. this._shadow.remove();
  386. this._root = null
  387. }
  388. return this
  389. }
  390. }, {
  391. key: "customizeCloud",
  392. value: function(attr) {
  393. if (this._cloud) {
  394. this._cloud.attr(attr)
  395. }
  396. }
  397. }, {
  398. key: "moveRoot",
  399. value: function(x, y) {
  400. if (this._root) {
  401. this._root.move(x, y)
  402. }
  403. }
  404. }, {
  405. key: "move",
  406. value: function(x, y) {
  407. x = round(x);
  408. y = round(y);
  409. this.x = x;
  410. this.y = y;
  411. var rotationAngle = getCloudAngle(this._size, x, y, this.anchorX, this.anchorY);
  412. var radRotationAngle = rotationAngle * PI / 180;
  413. this._cloud.attr({
  414. d: getCloudPoints(rotateSize(this._size, rotationAngle), x, y, rotateX(this.anchorX, this.anchorY, radRotationAngle, x, y), rotateY(this.anchorX, this.anchorY, radRotationAngle, x, y), this.options, this.bonded)
  415. }).rotate(rotationAngle, x, y);
  416. this.moveContentGroup(this.widget, this._contentGroup, x - this._contentBBox.x - this._contentBBox.width / 2, y - this._contentBBox.y - this._contentBBox.height / 2)
  417. }
  418. }, {
  419. key: "hitTest",
  420. value: function(x, y) {
  421. var _ref5 = this._size || {},
  422. width = _ref5.width,
  423. height = _ref5.height;
  424. return Math.abs(x - this.x) <= width / 2 && Math.abs(y - this.y) <= height / 2
  425. }
  426. }]);
  427. return Plaque
  428. }();