VisualMapping.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  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 = /** @class */function () {
  48. function VisualMapping(option) {
  49. var mappingMethod = option.mappingMethod;
  50. var visualType = option.type;
  51. var thisOption = this.option = zrUtil.clone(option);
  52. this.type = visualType;
  53. this.mappingMethod = mappingMethod;
  54. this._normalizeData = normalizers[mappingMethod];
  55. var visualHandler = VisualMapping.visualHandlers[visualType];
  56. this.applyVisual = visualHandler.applyVisual;
  57. this.getColorMapper = visualHandler.getColorMapper;
  58. this._normalizedToVisual = visualHandler._normalizedToVisual[mappingMethod];
  59. if (mappingMethod === 'piecewise') {
  60. normalizeVisualRange(thisOption);
  61. preprocessForPiecewise(thisOption);
  62. } else if (mappingMethod === 'category') {
  63. thisOption.categories ? preprocessForSpecifiedCategory(thisOption)
  64. // categories is ordinal when thisOption.categories not specified,
  65. // which need no more preprocess except normalize visual.
  66. : normalizeVisualRange(thisOption, true);
  67. } else {
  68. // mappingMethod === 'linear' or 'fixed'
  69. zrUtil.assert(mappingMethod !== 'linear' || thisOption.dataExtent);
  70. normalizeVisualRange(thisOption);
  71. }
  72. }
  73. VisualMapping.prototype.mapValueToVisual = function (value) {
  74. var normalized = this._normalizeData(value);
  75. return this._normalizedToVisual(normalized, value);
  76. };
  77. VisualMapping.prototype.getNormalizer = function () {
  78. return zrUtil.bind(this._normalizeData, this);
  79. };
  80. /**
  81. * List available visual types.
  82. *
  83. * @public
  84. * @return {Array.<string>}
  85. */
  86. VisualMapping.listVisualTypes = function () {
  87. return zrUtil.keys(VisualMapping.visualHandlers);
  88. };
  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;
  179. // value has the higher priority.
  180. for (var i = 0, len = pieceList.length; i < len; i++) {
  181. var pieceValue = pieceList[i].value;
  182. if (pieceValue != null) {
  183. if (pieceValue === value
  184. // FIXME
  185. // It is supposed to compare value according to value type of dimension,
  186. // but currently value type can exactly be string or number.
  187. // Compromise for numeric-like string (like '12'), especially
  188. // in the case that visualMap.categories is ['22', '33'].
  189. || zrUtil.isString(pieceValue) && pieceValue === value + '') {
  190. return i;
  191. }
  192. findClosestWhenOutside && updatePossible(pieceValue, i);
  193. }
  194. }
  195. for (var i = 0, len = pieceList.length; i < len; i++) {
  196. var piece = pieceList[i];
  197. var interval = piece.interval;
  198. var close_1 = piece.close;
  199. if (interval) {
  200. if (interval[0] === -Infinity) {
  201. if (littleThan(close_1[1], value, interval[1])) {
  202. return i;
  203. }
  204. } else if (interval[1] === Infinity) {
  205. if (littleThan(close_1[0], interval[0], value)) {
  206. return i;
  207. }
  208. } else if (littleThan(close_1[0], interval[0], value) && littleThan(close_1[1], value, interval[1])) {
  209. return i;
  210. }
  211. findClosestWhenOutside && updatePossible(interval[0], i);
  212. findClosestWhenOutside && updatePossible(interval[1], i);
  213. }
  214. }
  215. if (findClosestWhenOutside) {
  216. return value === Infinity ? pieceList.length - 1 : value === -Infinity ? 0 : possibleI;
  217. }
  218. function updatePossible(val, index) {
  219. var newAbs = Math.abs(val - value);
  220. if (newAbs < abs) {
  221. abs = newAbs;
  222. possibleI = index;
  223. }
  224. }
  225. };
  226. VisualMapping.visualHandlers = {
  227. color: {
  228. applyVisual: makeApplyVisual('color'),
  229. getColorMapper: function () {
  230. var thisOption = this.option;
  231. return zrUtil.bind(thisOption.mappingMethod === 'category' ? function (value, isNormalized) {
  232. !isNormalized && (value = this._normalizeData(value));
  233. return doMapCategory.call(this, value);
  234. } : function (value, isNormalized, out) {
  235. // If output rgb array
  236. // which will be much faster and useful in pixel manipulation
  237. var returnRGBArray = !!out;
  238. !isNormalized && (value = this._normalizeData(value));
  239. out = zrColor.fastLerp(value, thisOption.parsedVisual, out);
  240. return returnRGBArray ? out : zrColor.stringify(out, 'rgba');
  241. }, this);
  242. },
  243. _normalizedToVisual: {
  244. linear: function (normalized) {
  245. return zrColor.stringify(zrColor.fastLerp(normalized, this.option.parsedVisual), 'rgba');
  246. },
  247. category: doMapCategory,
  248. piecewise: function (normalized, value) {
  249. var result = getSpecifiedVisual.call(this, value);
  250. if (result == null) {
  251. result = zrColor.stringify(zrColor.fastLerp(normalized, this.option.parsedVisual), 'rgba');
  252. }
  253. return result;
  254. },
  255. fixed: doMapFixed
  256. }
  257. },
  258. colorHue: makePartialColorVisualHandler(function (color, value) {
  259. return zrColor.modifyHSL(color, value);
  260. }),
  261. colorSaturation: makePartialColorVisualHandler(function (color, value) {
  262. return zrColor.modifyHSL(color, null, value);
  263. }),
  264. colorLightness: makePartialColorVisualHandler(function (color, value) {
  265. return zrColor.modifyHSL(color, null, null, value);
  266. }),
  267. colorAlpha: makePartialColorVisualHandler(function (color, value) {
  268. return zrColor.modifyAlpha(color, value);
  269. }),
  270. decal: {
  271. applyVisual: makeApplyVisual('decal'),
  272. _normalizedToVisual: {
  273. linear: null,
  274. category: doMapCategory,
  275. piecewise: null,
  276. fixed: null
  277. }
  278. },
  279. opacity: {
  280. applyVisual: makeApplyVisual('opacity'),
  281. _normalizedToVisual: createNormalizedToNumericVisual([0, 1])
  282. },
  283. liftZ: {
  284. applyVisual: makeApplyVisual('liftZ'),
  285. _normalizedToVisual: {
  286. linear: doMapFixed,
  287. category: doMapFixed,
  288. piecewise: doMapFixed,
  289. fixed: doMapFixed
  290. }
  291. },
  292. symbol: {
  293. applyVisual: function (value, getter, setter) {
  294. var symbolCfg = this.mapValueToVisual(value);
  295. setter('symbol', symbolCfg);
  296. },
  297. _normalizedToVisual: {
  298. linear: doMapToArray,
  299. category: doMapCategory,
  300. piecewise: function (normalized, value) {
  301. var result = getSpecifiedVisual.call(this, value);
  302. if (result == null) {
  303. result = doMapToArray.call(this, normalized);
  304. }
  305. return result;
  306. },
  307. fixed: doMapFixed
  308. }
  309. },
  310. symbolSize: {
  311. applyVisual: makeApplyVisual('symbolSize'),
  312. _normalizedToVisual: createNormalizedToNumericVisual([0, 1])
  313. }
  314. };
  315. return VisualMapping;
  316. }();
  317. function preprocessForPiecewise(thisOption) {
  318. var pieceList = thisOption.pieceList;
  319. thisOption.hasSpecialVisual = false;
  320. zrUtil.each(pieceList, function (piece, index) {
  321. piece.originIndex = index;
  322. // piece.visual is "result visual value" but not
  323. // a visual range, so it does not need to be normalized.
  324. if (piece.visual != null) {
  325. thisOption.hasSpecialVisual = true;
  326. }
  327. });
  328. }
  329. function preprocessForSpecifiedCategory(thisOption) {
  330. // Hash categories.
  331. var categories = thisOption.categories;
  332. var categoryMap = thisOption.categoryMap = {};
  333. var visual = thisOption.visual;
  334. each(categories, function (cate, index) {
  335. categoryMap[cate] = index;
  336. });
  337. // Process visual map input.
  338. if (!zrUtil.isArray(visual)) {
  339. var visualArr_1 = [];
  340. if (zrUtil.isObject(visual)) {
  341. each(visual, function (v, cate) {
  342. var index = categoryMap[cate];
  343. visualArr_1[index != null ? index : CATEGORY_DEFAULT_VISUAL_INDEX] = v;
  344. });
  345. } else {
  346. // Is primary type, represents default visual.
  347. visualArr_1[CATEGORY_DEFAULT_VISUAL_INDEX] = visual;
  348. }
  349. visual = setVisualToOption(thisOption, visualArr_1);
  350. }
  351. // Remove categories that has no visual,
  352. // then we can mapping them to CATEGORY_DEFAULT_VISUAL_INDEX.
  353. for (var i = categories.length - 1; i >= 0; i--) {
  354. if (visual[i] == null) {
  355. delete categoryMap[categories[i]];
  356. categories.pop();
  357. }
  358. }
  359. }
  360. function normalizeVisualRange(thisOption, isCategory) {
  361. var visual = thisOption.visual;
  362. var visualArr = [];
  363. if (zrUtil.isObject(visual)) {
  364. each(visual, function (v) {
  365. visualArr.push(v);
  366. });
  367. } else if (visual != null) {
  368. visualArr.push(visual);
  369. }
  370. var doNotNeedPair = {
  371. color: 1,
  372. symbol: 1
  373. };
  374. if (!isCategory && visualArr.length === 1 && !doNotNeedPair.hasOwnProperty(thisOption.type)) {
  375. // Do not care visualArr.length === 0, which is illegal.
  376. visualArr[1] = visualArr[0];
  377. }
  378. setVisualToOption(thisOption, visualArr);
  379. }
  380. function makePartialColorVisualHandler(applyValue) {
  381. return {
  382. applyVisual: function (value, getter, setter) {
  383. // Only used in HSL
  384. var colorChannel = this.mapValueToVisual(value);
  385. // Must not be array value
  386. setter('color', applyValue(getter('color'), colorChannel));
  387. },
  388. _normalizedToVisual: createNormalizedToNumericVisual([0, 1])
  389. };
  390. }
  391. function doMapToArray(normalized) {
  392. var visual = this.option.visual;
  393. return visual[Math.round(linearMap(normalized, [0, 1], [0, visual.length - 1], true))] || {}; // TODO {}?
  394. }
  395. function makeApplyVisual(visualType) {
  396. return function (value, getter, setter) {
  397. setter(visualType, this.mapValueToVisual(value));
  398. };
  399. }
  400. function doMapCategory(normalized) {
  401. var visual = this.option.visual;
  402. return visual[this.option.loop && normalized !== CATEGORY_DEFAULT_VISUAL_INDEX ? normalized % visual.length : normalized];
  403. }
  404. function doMapFixed() {
  405. // visual will be convert to array.
  406. return this.option.visual[0];
  407. }
  408. /**
  409. * Create mapped to numeric visual
  410. */
  411. function createNormalizedToNumericVisual(sourceExtent) {
  412. return {
  413. linear: function (normalized) {
  414. return linearMap(normalized, sourceExtent, this.option.visual, true);
  415. },
  416. category: doMapCategory,
  417. piecewise: function (normalized, value) {
  418. var result = getSpecifiedVisual.call(this, value);
  419. if (result == null) {
  420. result = linearMap(normalized, sourceExtent, this.option.visual, true);
  421. }
  422. return result;
  423. },
  424. fixed: doMapFixed
  425. };
  426. }
  427. function getSpecifiedVisual(value) {
  428. var thisOption = this.option;
  429. var pieceList = thisOption.pieceList;
  430. if (thisOption.hasSpecialVisual) {
  431. var pieceIndex = VisualMapping.findPieceIndex(value, pieceList);
  432. var piece = pieceList[pieceIndex];
  433. if (piece && piece.visual) {
  434. return piece.visual[this.type];
  435. }
  436. }
  437. }
  438. function setVisualToOption(thisOption, visualArr) {
  439. thisOption.visual = visualArr;
  440. if (thisOption.type === 'color') {
  441. thisOption.parsedVisual = zrUtil.map(visualArr, function (item) {
  442. var color = zrColor.parse(item);
  443. if (!color && process.env.NODE_ENV !== 'production') {
  444. warn("'" + item + "' is an illegal color, fallback to '#000000'", true);
  445. }
  446. return color || [0, 0, 0, 1];
  447. });
  448. }
  449. return visualArr;
  450. }
  451. /**
  452. * Normalizers by mapping methods.
  453. */
  454. var normalizers = {
  455. linear: function (value) {
  456. return linearMap(value, this.option.dataExtent, [0, 1], true);
  457. },
  458. piecewise: function (value) {
  459. var pieceList = this.option.pieceList;
  460. var pieceIndex = VisualMapping.findPieceIndex(value, pieceList, true);
  461. if (pieceIndex != null) {
  462. return linearMap(pieceIndex, [0, pieceList.length - 1], [0, 1], true);
  463. }
  464. },
  465. category: function (value) {
  466. var index = this.option.categories ? this.option.categoryMap[value] : value; // ordinal value
  467. return index == null ? CATEGORY_DEFAULT_VISUAL_INDEX : index;
  468. },
  469. fixed: zrUtil.noop
  470. };
  471. function littleThan(close, a, b) {
  472. return close ? a <= b : a < b;
  473. }
  474. export default VisualMapping;