SGraphyPolygonItem.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /**
  2. * 不规则多边形,元空间
  3. */
  4. import SGraphyItem from '../../node-templete/SGraphy/SGraphyItem'
  5. import SRect from '../../node-templete/SGraphy/types/SRect';
  6. function getItem(arr, name) {
  7. if (arr && arr.length) {
  8. return arr.map(item => {
  9. return item[name]
  10. })
  11. } else {
  12. return [0]
  13. }
  14. }
  15. function changeArr(arr) {
  16. if (arr && arr.length) {
  17. return arr.map(item => {
  18. return [
  19. item.X, item.Y
  20. ]
  21. })
  22. } else {
  23. return [0]
  24. }
  25. }
  26. /**
  27. * 求不规则多边形重点
  28. * @param {points} 数组,多个点位坐标
  29. *
  30. * @return {x, y} 重点点位坐标
  31. */
  32. // function getCenterOfGravityPoint(points) {
  33. // let area = 0,
  34. // gx = 0,
  35. // gy = 0,
  36. // i = 1,
  37. // px1, px2, py1, py2, temp, length = points.length;
  38. // for (i; i <= length; i++) {
  39. // px1 = points[(i % length)].X;
  40. // px2 = points[(i - 1)].X;
  41. // py1 = points[(i % length)].Y;
  42. // py2 = points[(i - 1)].Y;
  43. // temp = (px1 * py2 - py1 * px2) / 2
  44. // area += temp;
  45. // gx += temp * (px1 + px2) / 3
  46. // gy += temp * (py1 + py2) / 3
  47. // }
  48. // gx = gx / area
  49. // gy = gy / area
  50. // return {
  51. // x: gx,
  52. // y: gy
  53. // }
  54. // }
  55. export default class SGraphyPolygonItem extends SGraphyItem {
  56. /**
  57. *
  58. * 构造函数
  59. *
  60. * @param jsonArr 空间线条数组
  61. * @param lineWidth 空间线条的宽度
  62. * @param color 空间线条的颜色
  63. * @param fillColor 空间的填充颜色
  64. *
  65. */
  66. constructor(jsonArr, lineWidth, color, fillColor, id, centerOfGravityPoint, name, paths, faceColor, businessColor, isBusiness, parent = null) {
  67. super(parent)
  68. this.jsonArr = jsonArr
  69. this.lineWidth = lineWidth
  70. this.color = color
  71. this.id = id
  72. this.name = name //实际渲染名字
  73. this.fillColor = fillColor
  74. let xArr = getItem(this.jsonArr, 'X')
  75. let yArr = getItem(this.jsonArr, 'Y')
  76. this.minX = Math.min.apply(null, xArr) || 0
  77. this.maxX = Math.max.apply(null, xArr) || 0
  78. this.maxY = Math.max.apply(null, yArr) || 0
  79. this.minY = Math.min.apply(null, yArr) || 0
  80. this.width = this.maxX - this.minX || 0
  81. this.height = this.maxY - this.minY || 0
  82. this.type = 3
  83. this.businessName = null
  84. this.faceColor = faceColor || '#cacaca' //颜色
  85. this.businessId = null //业务空间id
  86. this.isBusiness = isBusiness || 1 //状态
  87. this.businessColor = businessColor || 'rgba(68,161,140,.4)' //业务空间颜色
  88. this.businessFaceColor = "#333"
  89. this.containsArr = changeArr(this.jsonArr)
  90. this.paths = null
  91. if (paths && paths.length > 1) {
  92. this.paths = paths.map(item => {
  93. if (item && item.length) {
  94. return changeArr(item)
  95. } else {
  96. return undefined
  97. }
  98. }).filter(d => d)
  99. }
  100. this.centerOfGravityPoint = centerOfGravityPoint
  101. } //constructor
  102. /**
  103. * Item的边界区域
  104. *
  105. * @return SRect
  106. */
  107. boundingRect() {
  108. return new SRect(this.minX, this.minY, this.width, this.height)
  109. }
  110. /**
  111. * 判断item是否包含点x,y
  112. *
  113. * @param x 横坐标(当前item)
  114. * @param y 纵坐标(当前item)
  115. *
  116. * @return boolean
  117. */
  118. contains(x, y) {
  119. let falg = false,
  120. isFullIn = false //是否在镂空图形内
  121. if (this.paths instanceof Array) {
  122. for (let i = 1; i < this.paths.length; i++) {
  123. if (this.isIn(x, y, this.paths[i])) {
  124. //位置信息在镂空图形内
  125. isFullIn = true
  126. break
  127. }
  128. }
  129. // //如果鼠标在大图形内切在镂空图形中返回false
  130. if (this.isIn(x, y, this.containsArr) && isFullIn) {
  131. falg = false
  132. } else if (this.isIn(x, y, this.containsArr) && !isFullIn) {
  133. falg = true
  134. } else {
  135. falg = this.isIn(x, y, this.containsArr)
  136. }
  137. } else {
  138. falg = this.isIn(x, y, this.containsArr)
  139. }
  140. return falg
  141. }
  142. isIn(x, y, json) {
  143. let nCross = 0,
  144. point = typeof(x) == 'object' ? [x.x, x.y] : [x, y],
  145. APoints = json,
  146. length = APoints.length,
  147. p1, p2, i, xinters;
  148. p1 = APoints[0];
  149. for (i = 1; i <= length; i++) {
  150. p2 = APoints[i % length];
  151. if (
  152. point[0] > Math.min(p1[0], p2[0]) &&
  153. point[0] <= Math.max(p1[0], p2[0])
  154. ) {
  155. if (point[1] <= Math.max(p1[1], p2[1])) {
  156. if (p1[0] != p2[0]) {
  157. //计算位置信息
  158. xinters = (point[0] - p1[0]) * (p2[1] - p1[1]) / (p2[0] - p1[0]) + p1[1];
  159. if (p1[1] == p2[1] || point[1] <= xinters) {
  160. nCross++
  161. }
  162. }
  163. }
  164. }
  165. p1 = p2;
  166. }
  167. if (nCross % 2 == 0) {
  168. return false
  169. } else {
  170. return true
  171. }
  172. }
  173. /**
  174. * 绘制不规则多边形
  175. *
  176. * @param canvas 画布
  177. * @param rect 绘制区域
  178. */
  179. onDraw(canvas, rect) {
  180. if (this.jsonArr && this.jsonArr.length) {
  181. canvas.beginPath();
  182. canvas.lineWidth = 220
  183. canvas.lineCap = 'butt';
  184. if (this.isBusiness == 1) {
  185. canvas.strokeStyle = this.color || '#000'
  186. canvas.fillStyle = this.fillColor
  187. } else if (this.isBusiness == 2) {
  188. //已有id 的业务空间
  189. canvas.strokeStyle = this.color || '#000'
  190. canvas.fillStyle = this.businessColor || '#fff'
  191. } else if (this.isBusiness == 3) {
  192. //被选择的元空间
  193. canvas.strokeStyle = this.color || '#000'
  194. canvas.lineWidth = 800
  195. canvas.fillStyle = '#1abc9c'
  196. } else if (this.isBusiness == 4) {
  197. canvas.strokeStyle = 'rgba(251,226,1,.8)' || '#000'
  198. canvas.fillStyle = '#fff' || '#fff'
  199. } else if (this.isBusiness == 5) {
  200. canvas.fillStyle = 'rgba(11,12,12,.2)' || '#fff'
  201. } else if (this.isBusiness == 6) {
  202. canvas.fillStyle = '#1abc9c'
  203. canvas.lineWidth = 800
  204. canvas.strokeStyle = 'rgba(68,161,140,.4)' || '#fff'
  205. } else if (this.isBusiness == 7) {
  206. canvas.strokeStyle = this.color || '#000'
  207. canvas.fillStyle = this.businessColor || '#fff'
  208. }
  209. canvas.moveTo(this.jsonArr[0].X, this.jsonArr[0].Y)
  210. for (let i = 1; i < this.jsonArr.length; i++) {
  211. canvas.lineTo(this.jsonArr[i].X, this.jsonArr[i].Y)
  212. }
  213. canvas.lineTo(this.jsonArr[0].X, this.jsonArr[0].Y)
  214. canvas.closePath()
  215. canvas.fill()
  216. canvas.stroke()
  217. if (!!this.name) {
  218. canvas.font = "normal small-caps bold 500px Arial";
  219. if (this.isBusiness == 1) {
  220. canvas.fillStyle = this.faceColor
  221. } else if (this.isBusiness == 2) {
  222. canvas.fillStyle = this.businessFaceColor;
  223. } else if (this.isBusiness == 3) {
  224. //业务空间异常状态
  225. canvas.fillStyle = '#fff'
  226. } else if (this.isBusiness == 4) {
  227. canvas.fillStyle = '#cacaca'
  228. } else if (this.isBusiness == 6) {
  229. canvas.fillStyle = '#fff'
  230. } else if (this.isBusiness == 7) {
  231. canvas.fillStyle = 'red'
  232. }
  233. if (!!this.businessName || !!this.businessId) {
  234. name = '👇 ' + this.businessName
  235. } else {
  236. name = '⬇️ ' + this.name
  237. }
  238. canvas.fillText(name, this.centerOfGravityPoint.x, this.centerOfGravityPoint.y);
  239. // canvas.fillText(this.name, (this.maxX - this.minX) / 2 + this.minX, (this.maxY - this.minY) / 2 + this.minY);
  240. }
  241. // canvas.fillText(this.name, this.jsonArr[0].X, this.jsonArr[0].Y);
  242. }
  243. }
  244. }