PageRenderTime 25ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/app/assets/javascripts/word_cloud.js

https://bitbucket.org/rve/midas_reader
JavaScript | 359 lines | 322 code | 20 blank | 17 comment | 93 complexity | 16372b44cadf7c243bde631d53ae1dfb MD5 | raw file
  1. var tar_rec;
  2. var screenSizeX = 1000;
  3. var screenSizeY = 500;
  4. var fontType = "px Courier New";
  5. var hasRead = false
  6. var lastTxt, rect, newRect, bitree;
  7. var centerPoint = new Point(screenSizeX / 2, screenSizeY / 2);
  8. function Word(str, size, color, x, y, sizeX, sizeY, offsetX, offsetY) {
  9. this.str = str;
  10. this.size = size;
  11. this.color = color;
  12. this.x = x;
  13. this.y = y;
  14. this.sizeX = sizeX;
  15. this.sizeY = sizeY;
  16. this.offsetX = offsetX;
  17. this.offsetY = offsetY;
  18. }
  19. function Rectangle(x1, y1, x2, y2) {
  20. this.x1 = x1;
  21. this.y1 = y1;
  22. this.x2 = x2;
  23. this.y2 = y2;
  24. }
  25. function Point(x, y) {
  26. this.x = x;
  27. this.y = y;
  28. }
  29. function BItree() {
  30. var tree = new Array();
  31. var vis = new Array();
  32. for (var i = 0; i <= screenSizeX; i++) {
  33. tree.push(new Array(screenSizeY + 1));
  34. vis.push(new Array(screenSizeY + 1));
  35. }
  36. for (var i = 0; i <= screenSizeX; i++)
  37. for (var j = 0; j <= screenSizeY; j++) {
  38. tree[i][j] = 0;
  39. vis[i][j] = false;
  40. }
  41. function lowbit(x) {return x & (-x);}
  42. this.update = function(x, y) {
  43. if (vis[x][y]) return;
  44. vis[x][y] = true;
  45. for (var i = x + 1; i <= screenSizeX; i += lowbit(i))
  46. for (var j = y + 1; j <= screenSizeY; j += lowbit(j))
  47. tree[i][j]++;
  48. }
  49. this.query = function(x, y) {
  50. var ans = 0;
  51. for (var i = x + 1; i > 0; i -= lowbit(i))
  52. for (var j = y + 1; j > 0; j -= lowbit(j))
  53. ans += tree[i][j];
  54. return ans;
  55. }
  56. }
  57. function dist(p1, p2) {
  58. return Math.sqrt((p1.x - p2.x) * (p1.x -p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
  59. }
  60. //**********************randomColor*******************//
  61. function randomColor()
  62. {
  63. var colors = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'];
  64. var color = '#';
  65. var brush = Math.random()*30;
  66. for (var i = 0; i < 6; i++)
  67. {
  68. index = Math.round(Math.random() * 15);
  69. color += colors[index];
  70. }
  71. return color;
  72. }
  73. //***********************Bublle Sort********************//
  74. function BubbleSort()
  75. {
  76. for (var i=0;i<words.length-1;i++)
  77. for (var j=i;j<words.length;j++)
  78. if (words[j].size>words[i].size)
  79. {
  80. var temp=words[j];
  81. words[j]=words[i];
  82. words[i]=temp;
  83. }
  84. }
  85. //***********************init***************************//
  86. function init() {
  87. tar_rec=new Array();
  88. hasRead = true;
  89. lastTxt = new String();
  90. words = new Array();
  91. var txt = "中山大学|程序设计|Midas|HTML5|社交化|ACM|编程之美|QQ|微博|人人|博创杯|竞赛|蔡骏|心理学|大学生|时事|易中天|算法|藏地密码|中国";
  92. var i = 0, j = 0;
  93. while (j < txt.length) {
  94. var str = new String;
  95. var num = new String;
  96. while (txt[j] != '|' && j < txt.length)
  97. str += txt[j++];
  98. words.push(new Word(str, 100-i*4, randomColor(), 0, 0, 0, 0, 0, 0));
  99. j++; i++;
  100. }
  101. BubbleSort();
  102. }
  103. //***********************guess***************************//
  104. function guessX() {
  105. return screenSizeX;
  106. }
  107. function guessY() {
  108. return screenSizeY;
  109. }
  110. //***********************getRect***************************//
  111. function getRect() {
  112. var cxt = document.getElementById("canvasId").getContext("2d");
  113. for (var i = 0; i < words.length; i++) {
  114. cxt.fillStyle="#FFFFFF";
  115. cxt.fillRect(0, 0, screenSizeX, screenSizeY);
  116. cxt.font = words[i].size + fontType;
  117. cxt.fillStyle = words[i].color;
  118. cxt.fillText(words[i].str, 0, screenSizeY / 2);
  119. var gX = guessX(words[i]);
  120. var gY = guessY(words[i]);
  121. var x = 0;
  122. var y = Math.floor(Math.max(0, screenSizeY / 2 - gY));
  123. var w = Math.floor(Math.min(screenSizeX - x, gX * 1.5));
  124. var h = Math.floor(Math.min(screenSizeY - y, gY * 1.5));
  125. var imageData=document.getElementById("canvasId").getContext("2d").getImageData(x, y, w, h);
  126. var pix=imageData.data;
  127. var maxX = 0, maxY = 0, minX = screenSizeX, minY = screenSizeY;
  128. for (var j = 0; j < pix.length; j++) {
  129. var sign = false;
  130. if (pix[j++] != 255) sign = true;
  131. if (pix[j++] != 255) sign = true;
  132. if (pix[j++] != 255) sign = true;
  133. if (sign) {
  134. var index = Math.floor(j / 4);
  135. minX = Math.min(minX, index % screenSizeX);
  136. maxX = Math.max(maxX, index % screenSizeX);
  137. minY = Math.min(minY, Math.floor(index / screenSizeX));
  138. maxY = Math.max(maxY, Math.floor(index / screenSizeX));
  139. }
  140. }
  141. words[i].sizeX = maxX - minX + 1;
  142. words[i].sizeY = maxY - minY + 1;
  143. words[i].offsetX = minX;
  144. words[i].offsetY = maxY - screenSizeY / 2;
  145. }
  146. cxt.fillStyle = "#FFFFFF";
  147. cxt.fillRect(0, 0, screenSizeX, screenSizeY);
  148. }
  149. //***********************canPush***************************//
  150. function canPush(unitRect) {
  151. if (unitRect.x1 < 0 || unitRect.y1 < 0) return false;
  152. if (unitRect.x2 > screenSizeX || unitRect.y2 > screenSizeY) return false;
  153. var sum1 = bitree.query(unitRect.x2 - 1, unitRect.y2 - 1);
  154. var sum2 = bitree.query(unitRect.x1 - 1, unitRect.y1 - 1);
  155. var sum3 = bitree.query(unitRect.x1 - 1, unitRect.y2 - 1);
  156. var sum4 = bitree.query(unitRect.x2 - 1, unitRect.y1 - 1);
  157. return sum1 + sum2 - sum3 - sum4 == 0;
  158. }
  159. //***********************updateBItree*************************//
  160. function updateBItree(unitRect) {
  161. var w = unitRect.x2 - unitRect.x1;
  162. var h = unitRect.y2 - unitRect.y1;
  163. var imageData=document.getElementById("canvasId").getContext("2d").getImageData(unitRect.x1, unitRect.y1, w, h);
  164. var pix=imageData.data;
  165. for (var j = 0; j < pix.length; j++) {
  166. var sign = false;
  167. if (pix[j++] != 255) sign = true;
  168. if (pix[j++] != 255) sign = true;
  169. if (pix[j++] != 255) sign = true;
  170. if (sign) {
  171. var index = Math.floor(j / 4);
  172. bitree.update(index % w + unitRect.x1, Math.floor(index / w) + unitRect.y1);
  173. }
  174. }
  175. }
  176. //***********************isBetterPoint*************************//
  177. function betterPoint(p1, p2, word) {
  178. if (!canPush(new Rectangle(p2.x, p2.y, p2.x + word.sizeX, p2.y + word.sizeY))) return p1;
  179. var p1c = new Point(p1.x + word.sizeX / 2, p1.y + word.sizeY / 2);
  180. var p2c = new Point(p2.x + word.sizeX / 2, p2.y + word.sizeY / 2);
  181. if (dist(p1c, centerPoint) < dist(p2c, centerPoint)) return p1;
  182. else return p2;
  183. }
  184. //***********************getBestPoint*************************//
  185. function getBestPoint(word) {
  186. var retP = new Point(0, 0);
  187. for (var i = 0; i < rect.length; i++) {
  188. var p1 = new Point(rect[i].x1, rect[i].y1);
  189. var p2 = new Point(rect[i].x1, rect[i].y2 - word.sizeY);
  190. var p3 = new Point(rect[i].x2 - word.sizeX, rect[i].y1);
  191. var p4 = new Point(rect[i].x2 - word.sizeX, rect[i].y2 - word.sizeY);
  192. retP = betterPoint(retP, p1, word);
  193. retP = betterPoint(retP, p2, word);
  194. retP = betterPoint(retP, p3, word);
  195. retP = betterPoint(retP, p4, word);
  196. }
  197. return retP;
  198. }
  199. //***********************splitUnitRect***************************//
  200. function splitUnitRect(unitRect) {
  201. if (unitRect.x2 - unitRect.x1 < 8) return;
  202. var cPoint = new Point(Math.floor((unitRect.x1 + unitRect.x2) / 2), Math.floor((unitRect.y1 + unitRect.y2) / 2));
  203. var rect1 = new Rectangle(unitRect.x1, unitRect.y1, cPoint.x, cPoint.y);
  204. var rect2 = new Rectangle(unitRect.x1, cPoint.y, cPoint.x, unitRect.y2);
  205. var rect3 = new Rectangle(cPoint.x, unitRect.y1, unitRect.x2, cPoint.y);
  206. var rect4 = new Rectangle(cPoint.x, cPoint.y, unitRect.x2, unitRect.y2);
  207. if (!canPush(rect1)) splitUnitRect(rect1);
  208. else newRect.push(rect1);
  209. if (!canPush(rect2)) splitUnitRect(rect2);
  210. else newRect.push(rect2);
  211. if (!canPush(rect3)) splitUnitRect(rect3);
  212. else newRect.push(rect3);
  213. if (!canPush(rect4)) splitUnitRect(rect4);
  214. else newRect.push(rect4);
  215. }
  216. //***********************splitRect***************************//
  217. function splitRect() {
  218. newRect = new Array();
  219. for (var i = 0; i < rect.length; i++)
  220. if (canPush(rect[i])) newRect.push(rect[i]);
  221. for (var i = 0; i < rect.length; i++)
  222. if (!canPush(rect[i])) splitUnitRect(rect[i]);
  223. rect = new Array();
  224. for (var i = 0; i < newRect.length; i++) {
  225. var sign = true;
  226. for (var j = 0; j < rect.length; j++) {
  227. var canMerger = false;
  228. if (newRect[i].x2 - newRect[i].x1 == rect[j].x2 - rect[j].x1 && newRect[i].x1 == rect[j].x1 && (newRect[i].y1 == rect[j].y2 || newRect[i].y2 == rect[j].y1)) canMerger = true;
  229. if (newRect[i].y2 - newRect[i].y1 == rect[j].y2 - rect[j].y1 && newRect[i].y1 == rect[j].y1 && (newRect[i].x1 == rect[j].x2 || newRect[i].x2 == rect[j].x1)) canMerger = true;
  230. if (canMerger) {
  231. var x1 = Math.min(rect[j].x1, newRect[i].x1);
  232. var y1 = Math.min(rect[j].y1, newRect[i].y1);
  233. var x2 = Math.max(rect[j].x2, newRect[i].x2);
  234. var y2 = Math.max(rect[j].y2, newRect[i].y2);
  235. if (x2 - x1 <= screenSizeX / 10 && y2 - y1 <= screenSizeY / 5) {
  236. sign = false;
  237. rect[j].x1 = x1;
  238. rect[j].y1 = y1;
  239. rect[j].x2 = x2;
  240. rect[j].y2 = y2;
  241. break;
  242. }
  243. }
  244. }
  245. if (sign) rect.push(newRect[i]);
  246. }
  247. }
  248. //**********************randomColor*******************//
  249. function randomColor()
  250. {
  251. var colors = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'];
  252. var color = '#';
  253. var brush = Math.random()*30;
  254. for (var i = 0; i < 6; i++)
  255. {
  256. index = Math.round(Math.random() * 15);
  257. color += colors[index];
  258. }
  259. return color;
  260. }
  261. //***********************getPlace***************************//
  262. function paint() {
  263. bitree = new BItree();
  264. rect = new Array();
  265. for (var i = 0; i < 10; i++)
  266. for (var j = 0; j < 5; j++) {
  267. var x1 = Math.floor(i * (screenSizeX / 10));
  268. var y1 = Math.floor(j * (screenSizeY / 5));
  269. var x2 = Math.floor((i + 1) * (screenSizeX / 10));
  270. var y2 = Math.floor((j + 1) * (screenSizeY / 5));
  271. rect.push(new Rectangle(x1, y1, x2, y2));
  272. }
  273. var cxt = document.getElementById("canvasId").getContext("2d");
  274. for (var i = 0; i < words.length; i++) {
  275. p = getBestPoint(words[i]);
  276. words[i].x = p.x;
  277. words[i].y = p.y;
  278. cxt.font = words[i].size + fontType;
  279. cxt.fillStyle = words[i].color;
  280. cxt.fillText(words[i].str, words[i].x - words[i].offsetX, words[i].y + words[i].sizeY - words[i].offsetY);
  281. updateBItree(new Rectangle(words[i].x, words[i].y, words[i].x + words[i].sizeX, words[i].y + words[i].sizeY));
  282. splitRect();
  283. }
  284. }
  285. //***********************getRandom************************//
  286. function getRandom(n)
  287. {
  288. return Math.round(Math.random(n))+1;
  289. }
  290. //***********************draw***************************//
  291. function draw()
  292. {
  293. init();
  294. getRect();
  295. paint();
  296. }
  297. //************************kmp*****************************//
  298. function kmp(str,pat)//find pat in str,return position
  299. {
  300. var fail=new Array(pat.length);
  301. var i=0,j;
  302. fail[0]=-1;
  303. for (j=1;j<pat.length;j++)
  304. {
  305. for (i=fail[j-1];i>=0 && pat[i+1]!=pat[j];i=fail[i]);
  306. if (pat[i+1]==pat[j]) fail[j]=i+1;
  307. else fail[j]=-1;
  308. }
  309. for (i=j=0;i<str.length && j<pat.length;i++)
  310. {
  311. if (str[i]==pat[j]) j++;
  312. else
  313. if (j>0)
  314. {
  315. j=fail[j-1]+1;
  316. i--;
  317. }
  318. }
  319. return j==pat.length?(i-pat.length):-1;
  320. }
  321. //*******************************high_light*********************//
  322. function high_light()
  323. {
  324. var pat=document.getElementById("search_id").value;
  325. var cxt=document.getElementById("canvasId").getContext("2d");
  326. for (var i=0;i<words.length;i++)
  327. if (pat.length!=0 && kmp(words[i].str,pat)!=-1)
  328. {
  329. cxt.font = words[i].size + fontType;
  330. cxt.fillStyle = "#FEFF00";
  331. cxt.fillText(words[i].str, words[i].x - words[i].offsetX, words[i].y + words[i].sizeY - words[i].offsetY);
  332. }
  333. else
  334. {
  335. cxt.font = words[i].size + fontType;
  336. cxt.fillStyle = randomColor();
  337. cxt.fillText(words[i].str, words[i].x - words[i].offsetX, words[i].y + words[i].sizeY - words[i].offsetY);
  338. }
  339. }