wordCloud__.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // 词云
  2. function Bounds(min, max) {
  3. this.min = min;
  4. this.max = max;
  5. }
  6. Component({
  7. /**
  8. * 组件的属性列表
  9. */
  10. properties: {
  11. width: {
  12. type: Number | String,
  13. value: "100%"
  14. },
  15. height: {
  16. type: Number,
  17. value: 200
  18. },
  19. minFont: {
  20. type: Number,
  21. value: 12
  22. },
  23. maxFont: {
  24. type: Number,
  25. value: 35
  26. },
  27. fontColor: {
  28. type: String,
  29. value: "#f4347a"
  30. },
  31. wordsCloud: {
  32. type: Array,
  33. value: [],
  34. observer(words) {
  35. this.texts = [];
  36. this.value = 0;
  37. if (words.length > 0) {
  38. //排序
  39. words.sort((a, b) => {
  40. return parseFloat(b.value) - parseFloat(a.value)
  41. })
  42. let maxval = words[0].value;
  43. let minval = words[words.length - 1].value;
  44. const percent = this.data.maxFont / maxval
  45. words.forEach(item => {
  46. let value = isNaN(parseFloat(item.value)) ? this.data.minFont : parseFloat(item.value);
  47. let size = value * percent;
  48. item.fontSize = size < 10 ? size + 10 : size;
  49. return item
  50. })
  51. this.words = words;
  52. this.ctx.clearRect(0, 0, this.width, this.height)
  53. this.draw(this.words)
  54. } else {
  55. wx.createCanvasContext('canvas', this).draw()
  56. }
  57. }
  58. }
  59. },
  60. /**
  61. * 组件的初始数据
  62. */
  63. data: {
  64. },
  65. attached() {
  66. this.ctx = wx.createCanvasContext('canvas', this);
  67. this.height = this.data.height;
  68. this.width = wx.getSystemInfoSync().screenWidth - 48;
  69. this.texts = [];
  70. this.value = 0;
  71. this.canvasBound = new Bounds({
  72. x: 0,
  73. y: 0
  74. }, {
  75. x: this.width,
  76. y: this.height
  77. })
  78. },
  79. /**
  80. * 组件的方法列表
  81. */
  82. methods: {
  83. draw(words) {
  84. words.forEach((item, index) => {
  85. this.isDraw(item, index == 0)
  86. })
  87. this.ctx.draw();
  88. },
  89. isDraw(item, center) {
  90. let bound = this.createText(item, center)
  91. for (let i = 0; i < this.texts.length; i++) {
  92. let hasDraw = this.texts[i];
  93. if (this.intersects(hasDraw)) {
  94. this.value++;
  95. return;
  96. }
  97. }
  98. this.drawText(item.name, item.value)
  99. this.texts.push(new Bounds(this.min, this.max))
  100. },
  101. drawText(word, value) {
  102. this.ctx.textAlign = "left";
  103. this.ctx.textBaseline = "top";
  104. let colorLi = ['8','9', 'a', 'b', 'c', 'd', 'e', 'f'];
  105. let color = "#";
  106. for (let i = 0,len = 6; i < len; i++) {
  107. color += colorLi[Math.floor(Math.random() * len)]
  108. }
  109. this.ctx.setFillStyle(color);
  110. this.ctx.fillText(word, this.min.x, this.min.y);
  111. },
  112. //生成文本坐标
  113. createText(item, center, random) {
  114. let textRect = this.getTextRect(item)
  115. if (center) {
  116. this.min = {
  117. x: this.width / 2 - textRect.width / 2,
  118. y: this.height / 2 - textRect.height / 2
  119. }
  120. } else {
  121. this.min = this.getRandom()
  122. }
  123. this.max = {
  124. x: this.min.x + textRect.width,
  125. y: this.min.y + textRect.height
  126. }
  127. const bound = new Bounds(this.min, this.max);
  128. if (this.inAll(bound)) return;
  129. else this.createText(item)
  130. },
  131. //获取随机值
  132. getRandom() {
  133. return {
  134. x: Math.floor(Math.random() * this.width),
  135. y: Math.floor(Math.random() * this.height)
  136. }
  137. },
  138. //获取文字宽高
  139. getTextRect(item) {
  140. this.ctx.setFontSize(item.fontSize)
  141. let textWidth = this.ctx.measureText(item.word).width //文字所占宽度
  142. return {
  143. width: textWidth + 2,
  144. height: item.fontSize
  145. }
  146. },
  147. //检测是否有碰撞, 返回true是有碰撞
  148. intersects(bound) {
  149. var min = this.min,
  150. max = this.max,
  151. min2 = bound.min,
  152. max2 = bound.max,
  153. xIntersects = max2.x >= min.x && min2.x <= max.x,
  154. yIntersects = max2.y >= min.y && min2.y <= max.y;
  155. return xIntersects && yIntersects;
  156. },
  157. inAll(bound) {
  158. var min = bound.min,
  159. max = bound.max,
  160. start = this.canvasBound.min,
  161. end = this.canvasBound.max;
  162. return min.x >= start.x && min.y >= start.y && max.x <= end.x && max.y <= end.y
  163. }
  164. }
  165. })