jquery.vector-map.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. /*!
  2. * jVectorMap version 0.1
  3. *
  4. * Copyright 2011, Kirill Lebedev
  5. * Licensed under the MIT license.
  6. *
  7. */
  8. (function( $ ){
  9. var apiParams = {
  10. colors: 1,
  11. values: 1,
  12. backgroundColor: 1,
  13. scaleColors: 1,
  14. normalizeFunction: 1
  15. };
  16. var apiEvents = {
  17. onLabelShow: 'labelShow',
  18. onRegionOver: 'regionMouseOver',
  19. onRegionOut: 'regionMouseOut',
  20. onRegionClick: 'regionClick'
  21. };
  22. $.fn.vectorMap = function(options) {
  23. var defaultParams = {
  24. map: 'world_en',
  25. backgroundColor: '#FFFFFF',//背景色
  26. color: '#ffffff',
  27. hoverColor: '#f63a3a',//鼠标放上去颜色
  28. scaleColors: ['#b6d6ff', '#005ace'],
  29. normalizeFunction: 'linear'
  30. }, map;
  31. if (options === 'addMap') {
  32. WorldMap.maps[arguments[1]] = arguments[2];
  33. } else if (options === 'set' && apiParams[arguments[1]]) {
  34. this.data('mapObject')['set'+arguments[1].charAt(0).toUpperCase()+arguments[1].substr(1)].apply(this.data('mapObject'), Array.prototype.slice.call(arguments, 2));
  35. } else {
  36. $.extend(defaultParams, options);
  37. defaultParams.container = this;
  38. this.css({
  39. position: 'relative',
  40. overflow: 'hidden'
  41. });
  42. map = new WorldMap(defaultParams);
  43. this.data('mapObject', map);
  44. for (var e in apiEvents) {
  45. if (defaultParams[e]) {
  46. this.bind(apiEvents[e]+'.jvectormap', defaultParams[e]);
  47. }
  48. }
  49. }
  50. };
  51. var VectorCanvas = function(width, height) {
  52. this.mode = window.SVGAngle ? 'svg' : 'vml';
  53. if (this.mode == 'svg') {
  54. this.createSvgNode = function(nodeName) {
  55. return document.createElementNS(this.svgns, nodeName);
  56. }
  57. } else {
  58. try {
  59. if (!document.namespaces.rvml) {
  60. document.namespaces.add("rvml","urn:schemas-microsoft-com:vml");
  61. }
  62. this.createVmlNode = function (tagName) {
  63. return document.createElement('<rvml:' + tagName + ' class="rvml">');
  64. };
  65. } catch (e) {
  66. this.createVmlNode = function (tagName) {
  67. return document.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
  68. };
  69. }
  70. document.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
  71. }
  72. if (this.mode == 'svg') {
  73. this.canvas = this.createSvgNode('svg');
  74. } else {
  75. this.canvas = this.createVmlNode('group');
  76. this.canvas.style.position = 'absolute';
  77. }
  78. this.setSize(width, height);
  79. }
  80. VectorCanvas.prototype = {
  81. svgns: "http://www.w3.org/2000/svg",
  82. mode: 'svg',
  83. width: 0,
  84. height: 0,
  85. canvas: null,
  86. setSize: function(width, height) {
  87. if (this.mode == 'svg') {
  88. this.canvas.setAttribute('width', width);
  89. this.canvas.setAttribute('height', height);
  90. } else {
  91. this.canvas.style.width = width + "px";
  92. this.canvas.style.height = height + "px";
  93. this.canvas.coordsize = width+' '+height;
  94. this.canvas.coordorigin = "0 0";
  95. if (this.rootGroup) {
  96. var pathes = this.rootGroup.getElementsByTagName('shape');
  97. for(var i=0, l=pathes.length; i<l; i++) {
  98. pathes[i].coordsize = width+' '+height;
  99. pathes[i].style.width = width+'px';
  100. pathes[i].style.height = height+'px';
  101. }
  102. this.rootGroup.coordsize = width+' '+height;
  103. this.rootGroup.style.width = width+'px';
  104. this.rootGroup.style.height = height+'px';
  105. }
  106. }
  107. this.width = width;
  108. this.height = height;
  109. },
  110. createPath: function(config) {
  111. var node;
  112. if (this.mode == 'svg') {
  113. node = this.createSvgNode('path');
  114. node.setAttribute('d', config.path);
  115. node.setFill = function(color) {
  116. this.setAttribute("fill", color);
  117. };
  118. node.getFill = function(color) {
  119. return this.getAttribute("fill");
  120. };
  121. node.setOpacity = function(opacity) {
  122. this.setAttribute('fill-opacity', opacity);
  123. };
  124. } else {
  125. node = this.createVmlNode('shape');
  126. node.coordorigin = "0 0";
  127. node.coordsize = this.width + ' ' + this.height;
  128. node.style.width = this.width+'px';
  129. node.style.height = this.height+'px';
  130. node.fillcolor = WorldMap.defaultFillColor;
  131. node.stroked = false;
  132. node.path = VectorCanvas.pathSvgToVml(config.path);
  133. var scale = this.createVmlNode('skew');
  134. scale.on = true;
  135. scale.matrix = '0.01,0,0,0.01,0,0';
  136. scale.offset = '0,0';
  137. node.appendChild(scale);
  138. var fill = this.createVmlNode('fill');
  139. node.appendChild(fill);
  140. node.setFill = function(color) {
  141. this.getElementsByTagName('fill')[0].color = color;
  142. };
  143. node.getFill = function(color) {
  144. return this.getElementsByTagName('fill')[0].color;
  145. };
  146. node.setOpacity = function(opacity) {
  147. this.getElementsByTagName('fill')[0].opacity = parseInt(opacity*100)+'%';
  148. };
  149. }
  150. return node;
  151. },
  152. createGroup: function(isRoot) {
  153. var node;
  154. if (this.mode == 'svg') {
  155. node = this.createSvgNode('g');
  156. } else {
  157. node = this.createVmlNode('group');
  158. node.style.width = this.width+'px';
  159. node.style.height = this.height+'px';
  160. node.style.left = '0px';
  161. node.style.top = '0px';
  162. node.coordorigin = "0 0";
  163. node.coordsize = this.width + ' ' + this.height;
  164. }
  165. if (isRoot) {
  166. this.rootGroup = node;
  167. }
  168. return node;
  169. },
  170. applyTransformParams: function(scale, transX, transY) {
  171. if (this.mode == 'svg') {
  172. this.rootGroup.setAttribute('transform', 'scale('+scale+') translate('+transX+', '+transY+')');
  173. } else {
  174. this.rootGroup.coordorigin = (this.width-transX)+','+(this.height-transY);
  175. this.rootGroup.coordsize = this.width/scale+','+this.height/scale;
  176. }
  177. }
  178. }
  179. VectorCanvas.pathSvgToVml = function(path) {
  180. var result = '';
  181. var cx = 0, cy = 0, ctrlx, ctrly;
  182. return path.replace(/([MmLlHhVvCcSs])((?:-?(?:\d+)?(?:\.\d+)?,?\s?)+)/g, function(segment, letter, coords, index){
  183. coords = coords.replace(/(\d)-/g, '$1,-').replace(/\s+/g, ',').split(',');
  184. if (!coords[0]) coords.shift();
  185. for (var i=0,l=coords.length; i<l; i++) {
  186. coords[i] = Math.round(100*coords[i]);
  187. }
  188. switch (letter) {
  189. case 'm':
  190. cx += coords[0];
  191. cy += coords[1];
  192. return 't'+coords.join(',');
  193. break;
  194. case 'M':
  195. cx = coords[0];
  196. cy = coords[1];
  197. return 'm'+coords.join(',');
  198. break;
  199. case 'l':
  200. cx += coords[0];
  201. cy += coords[1];
  202. return 'r'+coords.join(',');
  203. break;
  204. case 'L':
  205. cx = coords[0];
  206. cy = coords[1];
  207. return 'l'+coords.join(',');
  208. break;
  209. case 'h':
  210. cx += coords[0];
  211. return 'r'+coords[0]+',0';
  212. break;
  213. case 'H':
  214. cx = coords[0];
  215. return 'l'+cx+','+cy;
  216. break;
  217. case 'v':
  218. cy += coords[0];
  219. return 'r0,'+coords[0];
  220. break;
  221. case 'V':
  222. cy = coords[0];
  223. return 'l'+cx+','+cy;
  224. break;
  225. case 'c':
  226. ctrlx = cx + coords[coords.length-4];
  227. ctrly = cy + coords[coords.length-3];
  228. cx += coords[coords.length-2];
  229. cy += coords[coords.length-1];
  230. return 'v'+coords.join(',');
  231. break;
  232. case 'C':
  233. ctrlx = coords[coords.length-4];
  234. ctrly = coords[coords.length-3];
  235. cx = coords[coords.length-2];
  236. cy = coords[coords.length-1];
  237. return 'c'+coords.join(',');
  238. break;
  239. case 's':
  240. coords.unshift(cy-ctrly);
  241. coords.unshift(cx-ctrlx);
  242. ctrlx = cx + coords[coords.length-4];
  243. ctrly = cy + coords[coords.length-3];
  244. cx += coords[coords.length-2];
  245. cy += coords[coords.length-1];
  246. return 'v'+coords.join(',');
  247. break;
  248. case 'S':
  249. coords.unshift(cy+cy-ctrly);
  250. coords.unshift(cx+cx-ctrlx);
  251. ctrlx = coords[coords.length-4];
  252. ctrly = coords[coords.length-3];
  253. cx = coords[coords.length-2];
  254. cy = coords[coords.length-1];
  255. return 'c'+coords.join(',');
  256. break;
  257. }
  258. return '';
  259. }).replace(/z/g, '');
  260. }
  261. var WorldMap = function(params) {
  262. params = params || {};
  263. var map = this;
  264. var mapData = WorldMap.maps[params.map];
  265. this.container = params.container;
  266. this.defaultWidth = mapData.width;
  267. this.defaultHeight = mapData.height;
  268. this.color = params.color;
  269. this.hoverColor = params.hoverColor;
  270. this.setBackgroundColor(params.backgroundColor);
  271. this.width = params.container.width();
  272. this.height = params.container.height();
  273. this.resize();
  274. $(window).resize(function(){
  275. map.width = params.container.width();
  276. map.height = params.container.height();
  277. map.resize();
  278. map.canvas.setSize(map.width, map.height);
  279. map.applyTransform();
  280. });
  281. this.canvas = new VectorCanvas(this.width, this.height);
  282. params.container.append(this.canvas.canvas);
  283. this.makeDraggable();
  284. this.rootGroup = this.canvas.createGroup(true);
  285. this.index = WorldMap.mapIndex;
  286. this.label = $('<div/>').addClass('jvectormap-label').appendTo($('body'));
  287. //this.labelText = $('<div/>').addClass('jvectormap-label').appendTo($('body'));
  288. //$('<div/>').addClass('jvectormap-zoomin').text('+').appendTo(params.container);
  289. //$('<div/>').addClass('jvectormap-zoomout').html('&#x2212;').appendTo(params.container);
  290. for(var key in mapData.pathes) {
  291. var path = this.canvas.createPath({path: mapData.pathes[key].path});
  292. path.setFill(this.color);
  293. path.id = 'jvectormap'+map.index+'_'+key;
  294. map.countries[key] = path;
  295. $(this.rootGroup).append(path);
  296. }
  297. $(params.container).delegate(this.canvas.mode == 'svg' ? 'path' : 'shape', 'mouseover mouseout', function(e){
  298. var path = e.target,
  299. code = e.target.id.split('_').pop(),
  300. labelShowEvent = $.Event('labelShow.jvectormap'),
  301. regionMouseOverEvent = $.Event('regionMouseOver.jvectormap');;
  302. if (e.type == 'mouseover') {
  303. $(params.container).trigger(regionMouseOverEvent, [code]);
  304. if (!regionMouseOverEvent.isDefaultPrevented()) {
  305. if (params.hoverOpacity) {
  306. path.setOpacity(params.hoverOpacity);
  307. }
  308. if (params.hoverColor) {
  309. path.currentFillColor = path.getFill()+'';
  310. path.setFill(params.hoverColor);
  311. }
  312. }
  313. map.label.html(mapData.pathes[code].name);
  314. //map.labelText.html(mapData.pathes[code].name);
  315. //map.labelText.css({color:'0xa1a1a1'});
  316. $(params.container).trigger(labelShowEvent, [map.label, code]);
  317. //$(params.container).trigger(labelShowEvent, [map.labelText, code]);
  318. //map.labelText.show();
  319. if (!labelShowEvent.isDefaultPrevented()) {
  320. map.label.show();
  321. map.labelWidth = map.label.width();
  322. map.labelHeight = map.label.height();
  323. }
  324. } else {
  325. path.setOpacity(1);
  326. if (path.currentFillColor) {
  327. path.setFill(path.currentFillColor);
  328. }
  329. map.label.hide();
  330. $(params.container).trigger('regionMouseOut.jvectormap', [code]);
  331. }
  332. });
  333. $(params.container).delegate(this.canvas.mode == 'svg' ? 'path' : 'shape', 'click', function(e){
  334. var path = e.target;
  335. var code = e.target.id.split('_').pop();
  336. $(params.container).trigger('regionClick.jvectormap', [code]);
  337. });
  338. params.container.mousemove(function(e){
  339. if (map.label.is(':visible')) {
  340. map.label.css({
  341. color:'0xfff000',
  342. left: e.pageX-15-map.labelWidth,
  343. top: e.pageY-15-map.labelHeight
  344. })
  345. }
  346. });
  347. this.setColors(params.colors);
  348. this.canvas.canvas.appendChild(this.rootGroup);
  349. this.applyTransform();
  350. this.colorScale = new ColorScale(params.scaleColors, params.normalizeFunction, params.valueMin, params.valueMax);
  351. if (params.values) {
  352. this.values = params.values;
  353. this.setValues(params.values);
  354. }
  355. this.bindZoomButtons();
  356. WorldMap.mapIndex++;
  357. }
  358. WorldMap.prototype = {
  359. transX: 0,
  360. transY: 0,
  361. scale: 1,
  362. baseTransX: 0,
  363. baseTransY: 0,
  364. baseScale: 1,
  365. width: 0,
  366. height: 0,
  367. countries: {},
  368. countriesColors: {},
  369. countriesData: {},
  370. zoomStep: 1.4,
  371. zoomMaxStep: 4,
  372. zoomCurStep: 1,
  373. setColors: function(key, color) {
  374. if (typeof key == 'string') {
  375. this.countries[key].setFill(color);
  376. } else {
  377. var colors = key;
  378. for (var code in colors) {
  379. if (this.countries[code]) {
  380. this.countries[code].setFill(colors[code]);
  381. }
  382. }
  383. }
  384. },
  385. setValues: function(values) {
  386. var max = 0,
  387. min = Number.MAX_VALUE,
  388. val;
  389. for (var cc in values) {
  390. val = parseFloat(values[cc]);
  391. if (val > max) max = values[cc];
  392. if (val && val < min) min = val;
  393. }
  394. this.colorScale.setMin(min);
  395. this.colorScale.setMax(max);
  396. var colors = {};
  397. for (cc in values) {
  398. val = parseFloat(values[cc]);
  399. if (val) {
  400. colors[cc] = this.colorScale.getColor(val);
  401. } else {
  402. colors[cc] = this.color;
  403. }
  404. }
  405. this.setColors(colors);
  406. this.values = values;
  407. },
  408. setBackgroundColor: function(backgroundColor) {
  409. this.container.css('background-color', backgroundColor);
  410. },
  411. setScaleColors: function(colors) {
  412. this.colorScale.setColors(colors);
  413. if (this.values) {
  414. this.setValues(this.values);
  415. }
  416. },
  417. setNormalizeFunction: function(f) {
  418. this.colorScale.setNormalizeFunction(f);
  419. if (this.values) {
  420. this.setValues(this.values);
  421. }
  422. },
  423. resize: function() {
  424. var curBaseScale = this.baseScale;
  425. if (this.width / this.height > this.defaultWidth / this.defaultHeight) {
  426. this.baseScale = this.height / this.defaultHeight;
  427. this.baseTransX = Math.abs(this.width - this.defaultWidth * this.baseScale) / (2 * this.baseScale);
  428. } else {
  429. this.baseScale = this.width / this.defaultWidth;
  430. this.baseTransY = Math.abs(this.height - this.defaultHeight * this.baseScale) / (2 * this.baseScale);
  431. }
  432. this.scale *= this.baseScale / curBaseScale;
  433. this.transX *= this.baseScale / curBaseScale;
  434. this.transY *= this.baseScale / curBaseScale;
  435. },
  436. reset: function() {
  437. this.countryTitle.reset();
  438. for(var key in this.countries) {
  439. this.countries[key].setFill(WorldMap.defaultColor);
  440. }
  441. this.scale = this.baseScale;
  442. this.transX = this.baseTransX;
  443. this.transY = this.baseTransY;
  444. this.applyTransform();
  445. },
  446. applyTransform: function() {
  447. var maxTransX, maxTransY, minTransX, maxTransY;
  448. if (this.defaultWidth * this.scale <= this.width) {
  449. maxTransX = (this.width - this.defaultWidth * this.scale) / (2 * this.scale);
  450. minTransX = (this.width - this.defaultWidth * this.scale) / (2 * this.scale);
  451. } else {
  452. maxTransX = 0;
  453. minTransX = (this.width - this.defaultWidth * this.scale) / this.scale;
  454. }
  455. if (this.defaultHeight * this.scale <= this.height) {
  456. maxTransY = (this.height - this.defaultHeight * this.scale) / (2 * this.scale);
  457. minTransY = (this.height - this.defaultHeight * this.scale) / (2 * this.scale);
  458. } else {
  459. maxTransY = 0;
  460. minTransY = (this.height - this.defaultHeight * this.scale) / this.scale;
  461. }
  462. if (this.transY > maxTransY) {
  463. this.transY = maxTransY;
  464. } else if (this.transY < minTransY) {
  465. this.transY = minTransY;
  466. }
  467. if (this.transX > maxTransX) {
  468. this.transX = maxTransX;
  469. } else if (this.transX < minTransX) {
  470. this.transX = minTransX;
  471. }
  472. this.canvas.applyTransformParams(this.scale, this.transX, this.transY);
  473. },
  474. makeDraggable: function(){
  475. var mouseDown = false;
  476. var oldPageX, oldPageY;
  477. var self = this;
  478. this.container.mousemove(function(e){
  479. if (mouseDown) {
  480. var curTransX = self.transX;
  481. var curTransY = self.transY;
  482. self.transX -= (oldPageX - e.pageX) / self.scale;
  483. self.transY -= (oldPageY - e.pageY) / self.scale;
  484. self.applyTransform();
  485. oldPageX = e.pageX;
  486. oldPageY = e.pageY;
  487. }
  488. return false;
  489. }).mousedown(function(e){
  490. mouseDown = true;
  491. oldPageX = e.pageX;
  492. oldPageY = e.pageY;
  493. return false;
  494. }).mouseup(function(){
  495. mouseDown = false;
  496. return false;
  497. });
  498. },
  499. bindZoomButtons: function() {
  500. var map = this;
  501. var sliderDelta = ($('#zoom').innerHeight() - 6*2 - 15*2 - 3*2 - 7 - 6) / (this.zoomMaxStep - this.zoomCurStep);
  502. this.container.find('.jvectormap-zoomin').click(function(){
  503. if (map.zoomCurStep < map.zoomMaxStep) {
  504. var curTransX = map.transX;
  505. var curTransY = map.transY;
  506. var curScale = map.scale;
  507. map.transX -= (map.width / map.scale - map.width / (map.scale * map.zoomStep)) / 2;
  508. map.transY -= (map.height / map.scale - map.height / (map.scale * map.zoomStep)) / 2;
  509. map.setScale(map.scale * map.zoomStep);
  510. map.zoomCurStep++;
  511. $('#zoomSlider').css('top', parseInt($('#zoomSlider').css('top')) - sliderDelta);
  512. }
  513. });
  514. this.container.find('.jvectormap-zoomout').click(function(){
  515. if (map.zoomCurStep > 1) {
  516. var curTransX = map.transX;
  517. var curTransY = map.transY;
  518. var curScale = map.scale;
  519. map.transX += (map.width / (map.scale / map.zoomStep) - map.width / map.scale) / 2;
  520. map.transY += (map.height / (map.scale / map.zoomStep) - map.height / map.scale) / 2;
  521. map.setScale(map.scale / map.zoomStep);
  522. map.zoomCurStep--;
  523. $('#zoomSlider').css('top', parseInt($('#zoomSlider').css('top')) + sliderDelta);
  524. }
  525. });
  526. },
  527. setScale: function(scale) {
  528. this.scale = scale;
  529. this.applyTransform();
  530. },
  531. getCountryPath: function(cc) {
  532. return $('#'+cc)[0];
  533. }
  534. }
  535. WorldMap.xlink = "http://www.w3.org/1999/xlink";
  536. WorldMap.mapIndex = 1;
  537. WorldMap.maps = {};
  538. var ColorScale = function(colors, normalizeFunction, minValue, maxValue) {
  539. if (colors) this.setColors(colors);
  540. if (normalizeFunction) this.setNormalizeFunction(normalizeFunction);
  541. if (minValue) this.setMin(minValue);
  542. if (minValue) this.setMax(maxValue);
  543. }
  544. ColorScale.prototype = {
  545. colors: [],
  546. setMin: function(min) {
  547. this.clearMinValue = min;
  548. if (typeof this.normalize === 'function') {
  549. this.minValue = this.normalize(min);
  550. } else {
  551. this.minValue = min;
  552. }
  553. },
  554. setMax: function(max) {
  555. this.clearMaxValue = max;
  556. if (typeof this.normalize === 'function') {
  557. this.maxValue = this.normalize(max);
  558. } else {
  559. this.maxValue = max;
  560. }
  561. },
  562. setColors: function(colors) {
  563. for (var i=0; i<colors.length; i++) {
  564. colors[i] = ColorScale.rgbToArray(colors[i]);
  565. }
  566. this.colors = colors;
  567. },
  568. setNormalizeFunction: function(f) {
  569. if (f === 'polynomial') {
  570. this.normalize = function(value) {
  571. return Math.pow(value, 0.2);
  572. }
  573. } else if (f === 'linear') {
  574. delete this.normalize;
  575. } else {
  576. this.normalize = f;
  577. }
  578. this.setMin(this.clearMinValue);
  579. this.setMax(this.clearMaxValue);
  580. },
  581. getColor: function(value) {
  582. if (typeof this.normalize === 'function') {
  583. value = this.normalize(value);
  584. }
  585. var lengthes = [];
  586. var fullLength = 0;
  587. var l;
  588. for (var i=0; i<this.colors.length-1; i++) {
  589. l = this.vectorLength(this.vectorSubtract(this.colors[i+1], this.colors[i]));
  590. lengthes.push(l);
  591. fullLength += l;
  592. }
  593. var c = (this.maxValue - this.minValue) / fullLength;
  594. for (i=0; i<lengthes.length; i++) {
  595. lengthes[i] *= c;
  596. }
  597. i = 0;
  598. value -= this.minValue;
  599. while (value - lengthes[i] >= 0) {
  600. value -= lengthes[i];
  601. i++;
  602. }
  603. var color;
  604. if (i == this.colors.length - 1) {
  605. color = this.vectorToNum(this.colors[i]).toString(16);
  606. } else {
  607. color = (
  608. this.vectorToNum(
  609. this.vectorAdd(this.colors[i],
  610. this.vectorMult(
  611. this.vectorSubtract(this.colors[i+1], this.colors[i]),
  612. (value) / (lengthes[i])
  613. )
  614. )
  615. )
  616. ).toString(16);
  617. }
  618. while (color.length < 6) {
  619. color = '0' + color;
  620. }
  621. return '#'+color;
  622. },
  623. vectorToNum: function(vector) {
  624. var num = 0;
  625. for (var i=0; i<vector.length; i++) {
  626. num += Math.round(vector[i])*Math.pow(256, vector.length-i-1);
  627. }
  628. return num;
  629. },
  630. vectorSubtract: function(vector1, vector2) {
  631. var vector = [];
  632. for (var i=0; i<vector1.length; i++) {
  633. vector[i] = vector1[i] - vector2[i];
  634. }
  635. return vector;
  636. },
  637. vectorAdd: function(vector1, vector2) {
  638. var vector = [];
  639. for (var i=0; i<vector1.length; i++) {
  640. vector[i] = vector1[i] + vector2[i];
  641. }
  642. return vector;
  643. },
  644. vectorMult: function(vector, num) {
  645. var result = [];
  646. for (var i=0; i<vector.length; i++) {
  647. result[i] = vector[i] * num;
  648. }
  649. return result;
  650. },
  651. vectorLength: function(vector) {
  652. var result = 0;
  653. for (var i=0; i<vector.length; i++) {
  654. result += vector[i]*vector[i];
  655. }
  656. return Math.sqrt(result);
  657. }
  658. }
  659. ColorScale.arrayToRgb = function(ar) {
  660. var rgb = '#';
  661. var d;
  662. for (var i=0; i<ar.length; i++) {
  663. d = ar[i].toString(16);
  664. rgb += d.length == 1 ? '0'+d : d;
  665. }
  666. return rgb;
  667. }
  668. ColorScale.rgbToArray = function(rgb) {
  669. rgb = rgb.substr(1);
  670. return [parseInt(rgb.substr(0, 2), 16), parseInt(rgb.substr(2, 2), 16), parseInt(rgb.substr(4, 2), 16)];
  671. }
  672. })( jQuery );