wordCloud.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // 词云
  2. Component({
  3. /**
  4. * 组件的属性列表
  5. */
  6. properties: {
  7. width: {
  8. type: Number | String,
  9. value: "100%"
  10. },
  11. height: {
  12. type: Number,
  13. value: 330
  14. },
  15. minFont: {
  16. type: Number,
  17. value: 12
  18. },
  19. maxFont: {
  20. type: Number,
  21. value: 35
  22. },
  23. fontColor: {
  24. type: String,
  25. value: "#f4347a"
  26. },
  27. wordsCloud: {
  28. type: Array,
  29. value: [],
  30. observer(words) {
  31. this.texts = [];
  32. this.ctx && this.ctx.clearRect(0, 0, this.width, this.height);
  33. if (words.length > 0) {
  34. //排序
  35. words.sort((a, b) => {
  36. return parseFloat(b.value) - parseFloat(a.value)
  37. })
  38. this.maxVal = words[0].value;
  39. this.minVal = words[words.length - 1].value;
  40. words.forEach((v, i) => {
  41. let point = this.creatText(v, i);
  42. this.texts.push(point);
  43. this.drawText(point);
  44. })
  45. }
  46. this.ctx && this.ctx.draw()
  47. }
  48. }
  49. },
  50. minVal: 0,
  51. maxVal: 0,
  52. /**
  53. * 组件的初始数据
  54. */
  55. data: {
  56. texts: []
  57. },
  58. attached() {
  59. this.ctx = wx.createCanvasContext('canvas', this);
  60. this.height = this.data.height;
  61. this.width = wx.getSystemInfoSync().screenWidth;
  62. this.texts = [];
  63. },
  64. /**
  65. * 组件的方法列表
  66. */
  67. methods: {
  68. drawText(word) {
  69. let colorLi = ['8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
  70. let color = "#";
  71. for (let i = 0, len = 6; i < len; i++) {
  72. color += colorLi[Math.floor(Math.random() * len)]
  73. }
  74. this.ctx.translate(word.x, word.y);
  75. this.ctx.rotate(word.angle);
  76. this.ctx.setFillStyle(color);
  77. this.ctx.textAlign = "left";
  78. this.ctx.textBaseline = "top";
  79. this.ctx.font = word.height + "px arial";
  80. this.ctx.fillText(word.name, 0, 0);
  81. this.ctx.rotate(-1 * word.angle);
  82. this.ctx.translate(-1 * word.x, -1 * word.y);
  83. },
  84. creatText(v, i) {
  85. const maxf = this.data.maxFont;
  86. const minf = this.data.minFont;
  87. let fen = (this.maxVal - this.minVal) / (maxf - minf);
  88. let fontsize = Math.ceil((v.value - this.minVal) / fen + minf)
  89. this.ctx.setFontSize(fontsize)
  90. let textWidth = this.ctx.measureText(v.name).width //文字所占宽度
  91. const createPoint = {
  92. x: 0,
  93. y: 0,
  94. width: textWidth,
  95. height: fontsize,
  96. angle: Math.random() * Math.PI / 4,
  97. }
  98. if (i === 0) {
  99. createPoint.x = this.width / 2 - textWidth / 2;
  100. createPoint.y = this.data.height / 2 - fontsize / 2;
  101. createPoint.angle = 0;
  102. } else {
  103. createPoint.x = Math.floor(Math.random() * (this.width));
  104. createPoint.y = Math.floor(Math.random() * (this.data.height));
  105. }
  106. // else{
  107. // createPoint.x = Math.floor(Math.random() * (this.width));
  108. // createPoint.y = Math.floor(Math.random() * (this.data.height));
  109. // }
  110. // 边界碰撞
  111. let c = Math.ceil(Math.sqrt(Math.pow(fontsize, 2) + Math.pow(textWidth, 2)));
  112. let cosx = Math.cos(createPoint.angle);
  113. let cosy = Math.cos(Math.PI / 2 - createPoint.angle);
  114. let jH = Math.asin(fontsize / textWidth);
  115. let cosyR = Math.cos(jH);
  116. let height = c * cosyR;
  117. let width = textWidth * cosx;
  118. let leftX = fontsize * cosy;
  119. createPoint.x < leftX && (createPoint.x = leftX);
  120. createPoint.x > this.width - width && (createPoint.x = this.width - width - 5);
  121. createPoint.y > this.data.height - height && (createPoint.y = this.data.height - height);
  122. return {
  123. ...v,
  124. ...createPoint
  125. }
  126. }
  127. }
  128. })