VisualMapping.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. /**
  20. * AUTO-GENERATED FILE. DO NOT MODIFY.
  21. */
  22. /*
  23. * Licensed to the Apache Software Foundation (ASF) under one
  24. * or more contributor license agreements. See the NOTICE file
  25. * distributed with this work for additional information
  26. * regarding copyright ownership. The ASF licenses this file
  27. * to you under the Apache License, Version 2.0 (the
  28. * "License"); you may not use this file except in compliance
  29. * with the License. You may obtain a copy of the License at
  30. *
  31. * http://www.apache.org/licenses/LICENSE-2.0
  32. *
  33. * Unless required by applicable law or agreed to in writing,
  34. * software distributed under the License is distributed on an
  35. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  36. * KIND, either express or implied. See the License for the
  37. * specific language governing permissions and limitations
  38. * under the License.
  39. */
  40. import * as zrUtil from 'zrender/lib/core/util.js';
  41. import * as zrColor from 'zrender/lib/tool/color.js';
  42. import { linearMap } from '../util/number.js';
  43. import { warn } from '../util/log.js';
  44. var each = zrUtil.each;
  45. var isObject = zrUtil.isObject;
  46. var CATEGORY_DEFAULT_VISUAL_INDEX = -1;
  47. var VisualMapping =
  48. /** @class */
  49. function () {
  50. function VisualMapping(option) {
  51. var mappingMethod = option.mappingMethod;
  52. var visualType = option.type;
  53. var thisOption = this.option = zrUtil.clone(option);
  54. this.type = visualType;
  55. this.mappingMethod = mappingMethod;
  56. this._normalizeData = normalizers[mappingMethod];
  57. var visualHandler = VisualMapping.visualHandlers[visualType];
  58. this.applyVisual = visualHandler.applyVisual;
  59. this.getColorMapper = visualHandler.getColorMapper;
  60. this._normalizedToVisual = visualHandler._normalizedToVisual[mappingMethod];
  61. if (mappingMethod === 'piecewise') {
  62. normalizeVisualRange(thisOption);
  63. preprocessForPiecewise(thisOption);
  64. } else if (mappingMethod === 'category') {
  65. thisOption.categories ? preprocessForSpecifiedCategory(thisOption) // categories is ordinal when thisOption.categories not specified,
  66. // which need no more preprocess except normalize visual.
  67. : normalizeVisualRange(thisOption, true);
  68. } else {
  69. // mappingMethod === 'linear' or 'fixed'
  70. zrUtil.assert(mappingMethod !== 'linear' || thisOption.dataExtent);
  71. normalizeVisualRange(thisOption);
  72. }
  73. }
  74. VisualMapping.prototype.mapValueToVisual = function (value) {
  75. var normalized = this._normalizeData(value);
  76. return this._normalizedToVisual(normalized, value);
  77. };
  78. VisualMapping.prototype.getNormalizer = function () {
  79. return zrUtil.bind(this._normalizeData, this);
  80. };
  81. /**
  82. * List available visual types.
  83. *
  84. * @public
  85. * @return {Array.<string>}
  86. */
  87. VisualMapping.listVisualTypes = function () {
  88. return zrUtil.keys(VisualMapping.visualHandlers);
  89. }; // /**
  90. // * @public
  91. // */
  92. // static addVisualHandler(name, handler) {
  93. // visualHandlers[name] = handler;
  94. // }
  95. /**
  96. * @public
  97. */
  98. VisualMapping.isValidType = function (visualType) {
  99. return VisualMapping.visualHandlers.hasOwnProperty(visualType);
  100. };
  101. /**
  102. * Convenient method.
  103. * Visual can be Object or Array or primary type.
  104. */
  105. VisualMapping.eachVisual = function (visual, callback, context) {
  106. if (zrUtil.isObject(visual)) {
  107. zrUtil.each(visual, callback, context);
  108. } else {
  109. callback.call(context, visual);
  110. }
  111. };
  112. VisualMapping.mapVisual = function (visual, callback, context) {
  113. var isPrimary;
  114. var newVisual = zrUtil.isArray(visual) ? [] : zrUtil.isObject(visual) ? {} : (isPrimary = true, null);
  115. VisualMapping.eachVisual(visual, function (v, key) {
  116. var newVal = callback.call(context, v, key);
  117. isPrimary ? newVisual = newVal : newVisual[key] = newVal;
  118. });
  119. return newVisual;
  120. };
  121. /**
  122. * Retrieve visual properties from given object.
  123. */
  124. VisualMapping.retrieveVisuals = function (obj) {
  125. var ret = {};
  126. var hasVisual;
  127. obj && each(VisualMapping.visualHandlers, function (h, visualType) {
  128. if (obj.hasOwnProperty(visualType)) {
  129. ret[visualType] = obj[visualType];
  130. hasVisual = true;
  131. }
  132. });
  133. return hasVisual ? ret : null;
  134. };
  135. /**
  136. * Give order to visual types, considering colorSaturation, colorAlpha depends on color.
  137. *
  138. * @public
  139. * @param {(Object|Array)} visualTypes If Object, like: {color: ..., colorSaturation: ...}
  140. * IF Array, like: ['color', 'symbol', 'colorSaturation']
  141. * @return {Array.<string>} Sorted visual types.
  142. */
  143. VisualMapping.prepareVisualTypes = function (visualTypes) {
  144. if (zrUtil.isArray(visualTypes)) {
  145. visualTypes = visualTypes.slice();
  146. } else if (isObject(visualTypes)) {
  147. var types_1 = [];
  148. each(visualTypes, function (item, type) {
  149. types_1.push(type);
  150. });
  151. visualTypes = types_1;
  152. } else {
  153. return [];
  154. }
  155. visualTypes.sort(function (type1, type2) {
  156. // color should be front of colorSaturation, colorAlpha, ...
  157. // symbol and symbolSize do not matter.
  158. return type2 === 'color' && type1 !== 'color' && type1.indexOf('color') === 0 ? 1 : -1;
  159. });
  160. return visualTypes;
  161. };
  162. /**
  163. * 'color', 'colorSaturation', 'colorAlpha', ... are depends on 'color'.
  164. * Other visuals are only depends on themself.
  165. */
  166. VisualMapping.dependsOn = function (visualType1, visualType2) {
  167. return visualType2 === 'color' ? !!(visualType1 && visualType1.indexOf(visualType2) === 0) : visualType1 === visualType2;
  168. };
  169. /**
  170. * @param value
  171. * @param pieceList [{value: ..., interval: [min, max]}, ...]
  172. * Always from small to big.
  173. * @param findClosestWhenOutside Default to be false
  174. * @return index
  175. */
  176. VisualMapping.findPieceIndex = function (value, pieceList, findClosestWhenOutside) {
  177. var possibleI;
  178. var abs = Infinity; // value has the higher priority.
  179. for (var i = 0, len = pieceList.length; i < len; i++) {
  180. var pieceValue = pieceList[i].value;
  181. if (pieceValue != null) {
  182. if (pieceValue === value // FIXME
  183. // It is supposed to compare value according to value type of dimension,
  184. // but currently value type can exactly be string or number.
  185. // Compromise for numeric-like string (like '12'), especially
  186. // in the case that visualMap.categories is ['22', '33'].
  187. || zrUtil.isString(pieceValue) && pieceValue === value + '') {
  188. return i;
  189. }
  190. findClosestWhenOutside && updatePossible(pieceValue, i);
  191. }
  192. }
  193. for (var i = 0, len = pieceList.length; i < len; i++) {
  194. var piece = pieceList[i];
  195. var interval = piece.interval;
  196. var close_1 = piece.close;
  197. if (interval) {
  198. if (interval[0] === -Infinity) {
  199. if (littleThan(close_1[1], value, interval[1])) {
  200. return i;
  201. }
  202. } else if (interval[1] === Infinity) {
  203. if (littleThan(close_1[0], interval[0], value)) {
  204. return i;
  205. }
  206. } else if (littleThan(close_1[0], interval[0], value) && littleThan(close_1[1], value, interval[1])) {
  207. return i;
  208. }
  209. findClosestWhenOutside && updatePossible(interval[0], i);
  210. findClosestWhenOutside && updatePossible(interval[1], i);
  211. }
  212. }
  213. if (findClosestWhenOutside) {
  214. return value === Infinity ? pieceList.length - 1 : value === -Infinity ? 0 : possibleI;
  215. }
  216. function updatePossible(val, index) {
  217. var newAbs = Math.abs(val - value);
  218. if (newAbs < abs) {
  219. abs = newAbs;
  220. possibleI = index;
  221. }
  222. }
  223. };
  224. VisualMapping.visualHandlers = {
  225. color: {
  226. applyVisual: makeApplyVisual('color'),
  227. getColorMapper: function () {
  228. var thisOption = this.option;
  229. return zrUtil.bind(thisOption.mappingMethod === 'category' ? function (value, isNormalized) {
  230. !isNormalized && (value = this._normalizeData(value));
  231. return doMapCategory.call(this, value);
  232. } : function (value, isNormalized, out) {
  233. // If output rgb array
  234. // which will be much faster and useful in pixel manipulation
  235. var returnRGBArray = !!out;
  236. !isNormalized && (value = this._normalizeData(value));
  237. out = zrColor.fastLerp(value, thisOption.parsedVisual, out);
  238. return returnRGBArray ? out : zrColor.stringify(out, 'rgba');
  239. }, this);
  240. },
  241. _normalizedToVisual: {
  242. linear: function (normalized) {
  243. return zrColor.stringify(zrColor.fastLerp(normalized, this.option.parsedVisual), 'rgba');
  244. },
  245. category: doMapCategory,
  246. piecewise: function (normalized, value) {
  247. var result = getSpecifiedVisual.call(this, value);
  248. if (result == null) {
  249. result = zrColor.stringify(zrColor.fastLerp(normalized, this.option.parsedVisual), 'rgba');
  250. }
  251. return result;
  252. },
  253. fixed: doMapFixed
  254. }
  255. },
  256. colorHue: makePartialColorVisualHandler(function (color, value) {
  257. return zrColor.modifyHSL(color, value);
  258. }),
  259. colorSaturation: makePartialColorVisualHandler(function (color, value) {
  260. return zrColor.modifyHSL(color, null, value);
  261. }),
  262. colorLightness: makePartialColorVisualHandler(function (color, value) {
  263. return zrColor.modifyHSL(color, null, null, value);
  264. }),
  265. colorAlpha: makePartialColorVisualHandler(function (color, value) {
  266. return zrColor.modifyAlpha(color, value);
  267. }),
  268. decal: {
  269. applyVisual: makeApplyVisual('decal'),
  270. _normalizedToVisual: {
  271. linear: null,
  272. category: doMapCategory,
  273. piecewise: null,
  274. fixed: null
  275. }
  276. },
  277. opacity: {
  278. applyVisual: makeApplyVisual('opacity'),
  279. _normalizedToVisual: createNormalizedToNumericVisual([0, 1])
  280. },
  281. liftZ: {
  282. applyVisual: makeApplyVisual('liftZ'),
  283. _normalizedToVisual: {
  284. linear: doMapFixed,
  285. category: doMapFixed,
  286. piecewise: doMapFixed,
  287. fixed: doMapFixed
  288. }
  289. },
  290. symbol: {
  291. applyVisual: function (value, getter, setter) {
  292. var symbolCfg = this.mapValueToVisual(value);
  293. setter('symbol', symbolCfg);
  294. },
  295. _normalizedToVisual: {
  296. linear: doMapToArray,
  297. category: doMapCategory,
  298. piecewise: function (normalized, value) {
  299. var result = getSpecifiedVisual.call(this, value);
  300. if (result == null) {
  301. result = doMapToArray.call(this, normalized);
  302. }
  303. return result;
  304. },
  305. fixed: doMapFixed
  306. }
  307. },
  308. symbolSize: {
  309. applyVisual: makeApplyVisual('symbolSize'),
  310. _normalizedToVisual: createNormalizedToNumericVisual([0, 1])
  311. }
  312. };
  313. return VisualMapping;
  314. }();
  315. function preprocessForPiecewise(thisOption) {
  316. var pieceList = thisOption.pieceList;
  317. thisOption.hasSpecialVisual = false;
  318. zrUtil.each(pieceList, function (piece, index) {
  319. piece.originIndex = index; // piece.visual is "result visual value" but not
  320. // a visual range, so it does not need to be normalized.
  321. if (piece.visual != null) {
  322. thisOption.hasSpecialVisual = true;
  323. }
  324. });
  325. }
  326. function preprocessForSpecifiedCategory(thisOption) {
  327. // Hash categories.
  328. var categories = thisOption.categories;
  329. var categoryMap = thisOption.categoryMap = {};
  330. var visual = thisOption.visual;
  331. each(categories, function (cate, index) {
  332. categoryMap[cate] = index;
  333. }); // Process visual map input.
  334. if (!zrUtil.isArray(visual)) {
  335. var visualArr_1 = [];
  336. if (zrUtil.isObject(visual)) {
  337. each(visual, function (v, cate) {
  338. var index = categoryMap[cate];
  339. visualArr_1[index != null ? index : CATEGORY_DEFAULT_VISUAL_INDEX] = v;
  340. });
  341. } else {
  342. // Is primary type, represents default visual.
  343. visualArr_1[CATEGORY_DEFAULT_VISUAL_INDEX] = visual;
  344. }
  345. visual = setVisualToOption(thisOption, visualArr_1);
  346. } // Remove categories that has no visual,
  347. // then we can mapping them to CATEGORY_DEFAULT_VISUAL_INDEX.
  348. for (var i = categories.length - 1; i >= 0; i--) {
  349. if (visual[i] == null) {
  350. delete categoryMap[categories[i]];
  351. categories.pop();
  352. }
  353. }
  354. }
  355. function normalizeVisualRange(thisOption, isCategory) {
  356. var visual = thisOption.visual;
  357. var visualArr = [];
  358. if (zrUtil.isObject(visual)) {
  359. each(visual, function (v) {
  360. visualArr.push(v);
  361. });
  362. } else if (visual != null) {
  363. visualArr.push(visual);
  364. }
  365. var doNotNeedPair = {
  366. color: 1,
  367. symbol: 1
  368. };
  369. if (!isCategory && visualArr.length === 1 && !doNotNeedPair.hasOwnProperty(thisOption.type)) {
  370. // Do not care visualArr.length === 0, which is illegal.
  371. visualArr[1] = visualArr[0];
  372. }
  373. setVisualToOption(thisOption, visualArr);
  374. }
  375. function makePartialColorVisualHandler(applyValue) {
  376. return {
  377. applyVisual: function (value, getter, setter) {
  378. // Only used in HSL
  379. var colorChannel = this.mapValueToVisual(value); // Must not be array value
  380. setter('color', applyValue(getter('color'), colorChannel));
  381. },
  382. _normalizedToVisual: createNormalizedToNumericVisual([0, 1])
  383. };
  384. }
  385. function doMapToArray(normalized) {
  386. var visual = this.option.visual;
  387. return visual[Math.round(linearMap(normalized, [0, 1], [0, visual.length - 1], true))] || {}; // TODO {}?
  388. }
  389. function makeApplyVisual(visualType) {
  390. return function (value, getter, setter) {
  391. setter(visualType, this.mapValueToVisual(value));
  392. };
  393. }
  394. function doMapCategory(normalized) {
  395. var visual = this.option.visual;
  396. return visual[this.option.loop && normalized !== CATEGORY_DEFAULT_VISUAL_INDEX ? normalized % visual.length : normalized];
  397. }
  398. function doMapFixed() {
  399. // visual will be convert to array.
  400. return this.option.visual[0];
  401. }
  402. /**
  403. * Create mapped to numeric visual
  404. */
  405. function createNormalizedToNumericVisual(sourceExtent) {
  406. return {
  407. linear: function (normalized) {
  408. return linearMap(normalized, sourceExtent, this.option.visual, true);
  409. },
  410. category: doMapCategory,
  411. piecewise: function (normalized, value) {
  412. var result = getSpecifiedVisual.call(this, value);
  413. if (result == null) {
  414. result = linearMap(normalized, sourceExtent, this.option.visual, true);
  415. }
  416. return result;
  417. },
  418. fixed: doMapFixed
  419. };
  420. }
  421. function getSpecifiedVisual(value) {
  422. var thisOption = this.option;
  423. var pieceList = thisOption.pieceList;
  424. if (thisOption.hasSpecialVisual) {
  425. var pieceIndex = VisualMapping.findPieceIndex(value, pieceList);
  426. var piece = pieceList[pieceIndex];
  427. if (piece && piece.visual) {
  428. return piece.visual[this.type];
  429. }
  430. }
  431. }
  432. function setVisualToOption(thisOption, visualArr) {
  433. thisOption.visual = visualArr;
  434. if (thisOption.type === 'color') {
  435. thisOption.parsedVisual = zrUtil.map(visualArr, function (item) {
  436. var color = zrColor.parse(item);
  437. if (!color && process.env.NODE_ENV !== 'production') {
  438. warn("'" + item + "' is an illegal color, fallback to '#000000'", true);
  439. }
  440. return color || [0, 0, 0, 1];
  441. });
  442. }
  443. return visualArr;
  444. }
  445. /**
  446. * Normalizers by mapping methods.
  447. */
  448. var normalizers = {
  449. linear: function (value) {
  450. return linearMap(value, this.option.dataExtent, [0, 1], true);
  451. },
  452. piecewise: function (value) {
  453. var pieceList = this.option.pieceList;
  454. var pieceIndex = VisualMapping.findPieceIndex(value, pieceList, true);
  455. if (pieceIndex != null) {
  456. return linearMap(pieceIndex, [0, pieceList.length - 1], [0, 1], true);
  457. }
  458. },
  459. category: function (value) {
  460. var index = this.option.categories ? this.option.categoryMap[value] : value; // ordinal value
  461. return index == null ? CATEGORY_DEFAULT_VISUAL_INDEX : index;
  462. },
  463. fixed: zrUtil.noop
  464. };
  465. function littleThan(close, a, b) {
  466. return close ? a <= b : a < b;
  467. }
  468. export default VisualMapping;