| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| // Only create one roam controller for each coordinate system. |
| // one roam controller might be refered by two inside data zoom |
| // components (for example, one for x and one for y). When user |
| // pan or zoom, only dispatch one action for those data zoom |
| // components. |
| import * as zrUtil from 'zrender/src/core/util'; |
| import RoamController from '../../component/helper/RoamController'; |
| import * as throttleUtil from '../../util/throttle'; |
| var ATTR = '\0_ec_dataZoom_roams'; |
| /** |
| * @public |
| * @param {module:echarts/ExtensionAPI} api |
| * @param {Object} dataZoomInfo |
| * @param {string} dataZoomInfo.coordId |
| * @param {Function} dataZoomInfo.containsPoint |
| * @param {Array.<string>} dataZoomInfo.allCoordIds |
| * @param {string} dataZoomInfo.dataZoomId |
| * @param {Object} dataZoomInfo.getRange |
| * @param {Function} dataZoomInfo.getRange.pan |
| * @param {Function} dataZoomInfo.getRange.zoom |
| * @param {Function} dataZoomInfo.getRange.scrollMove |
| * @param {boolean} dataZoomInfo.dataZoomModel |
| */ |
| |
| export function register(api, dataZoomInfo) { |
| var store = giveStore(api); |
| var theDataZoomId = dataZoomInfo.dataZoomId; |
| var theCoordId = dataZoomInfo.coordId; // Do clean when a dataZoom changes its target coordnate system. |
| // Avoid memory leak, dispose all not-used-registered. |
| |
| zrUtil.each(store, function (record, coordId) { |
| var dataZoomInfos = record.dataZoomInfos; |
| |
| if (dataZoomInfos[theDataZoomId] && zrUtil.indexOf(dataZoomInfo.allCoordIds, theCoordId) < 0) { |
| delete dataZoomInfos[theDataZoomId]; |
| record.count--; |
| } |
| }); |
| cleanStore(store); |
| var record = store[theCoordId]; // Create if needed. |
| |
| if (!record) { |
| record = store[theCoordId] = { |
| coordId: theCoordId, |
| dataZoomInfos: {}, |
| count: 0 |
| }; |
| record.controller = createController(api, record); |
| record.dispatchAction = zrUtil.curry(dispatchAction, api); |
| } // Update reference of dataZoom. |
| |
| |
| !record.dataZoomInfos[theDataZoomId] && record.count++; |
| record.dataZoomInfos[theDataZoomId] = dataZoomInfo; |
| var controllerParams = mergeControllerParams(record.dataZoomInfos); |
| record.controller.enable(controllerParams.controlType, controllerParams.opt); // Consider resize, area should be always updated. |
| |
| record.controller.setPointerChecker(dataZoomInfo.containsPoint); // Update throttle. |
| |
| throttleUtil.createOrUpdate(record, 'dispatchAction', dataZoomInfo.dataZoomModel.get('throttle', true), 'fixRate'); |
| } |
| /** |
| * @public |
| * @param {module:echarts/ExtensionAPI} api |
| * @param {string} dataZoomId |
| */ |
| |
| export function unregister(api, dataZoomId) { |
| var store = giveStore(api); |
| zrUtil.each(store, function (record) { |
| record.controller.dispose(); |
| var dataZoomInfos = record.dataZoomInfos; |
| |
| if (dataZoomInfos[dataZoomId]) { |
| delete dataZoomInfos[dataZoomId]; |
| record.count--; |
| } |
| }); |
| cleanStore(store); |
| } |
| /** |
| * @public |
| */ |
| |
| export function generateCoordId(coordModel) { |
| return coordModel.type + '\0_' + coordModel.id; |
| } |
| /** |
| * Key: coordId, value: {dataZoomInfos: [], count, controller} |
| * @type {Array.<Object>} |
| */ |
| |
| function giveStore(api) { |
| // Mount store on zrender instance, so that we do not |
| // need to worry about dispose. |
| var zr = api.getZr(); |
| return zr[ATTR] || (zr[ATTR] = {}); |
| } |
| |
| function createController(api, newRecord) { |
| var controller = new RoamController(api.getZr()); |
| zrUtil.each(['pan', 'zoom', 'scrollMove'], function (eventName) { |
| controller.on(eventName, function (event) { |
| var batch = []; |
| zrUtil.each(newRecord.dataZoomInfos, function (info) { |
| // Check whether the behaviors (zoomOnMouseWheel, moveOnMouseMove, |
| // moveOnMouseWheel, ...) enabled. |
| if (!event.isAvailableBehavior(info.dataZoomModel.option)) { |
| return; |
| } |
| |
| var method = (info.getRange || {})[eventName]; |
| var range = method && method(newRecord.controller, event); |
| !info.dataZoomModel.get('disabled', true) && range && batch.push({ |
| dataZoomId: info.dataZoomId, |
| start: range[0], |
| end: range[1] |
| }); |
| }); |
| batch.length && newRecord.dispatchAction(batch); |
| }); |
| }); |
| return controller; |
| } |
| |
| function cleanStore(store) { |
| zrUtil.each(store, function (record, coordId) { |
| if (!record.count) { |
| record.controller.dispose(); |
| delete store[coordId]; |
| } |
| }); |
| } |
| /** |
| * This action will be throttled. |
| */ |
| |
| |
| function dispatchAction(api, batch) { |
| api.dispatchAction({ |
| type: 'dataZoom', |
| batch: batch |
| }); |
| } |
| /** |
| * Merge roamController settings when multiple dataZooms share one roamController. |
| */ |
| |
| |
| function mergeControllerParams(dataZoomInfos) { |
| var controlType; // DO NOT use reserved word (true, false, undefined) as key literally. Even if encapsulated |
| // as string, it is probably revert to reserved word by compress tool. See #7411. |
| |
| var prefix = 'type_'; |
| var typePriority = { |
| 'type_true': 2, |
| 'type_move': 1, |
| 'type_false': 0, |
| 'type_undefined': -1 |
| }; |
| var preventDefaultMouseMove = true; |
| zrUtil.each(dataZoomInfos, function (dataZoomInfo) { |
| var dataZoomModel = dataZoomInfo.dataZoomModel; |
| var oneType = dataZoomModel.get('disabled', true) ? false : dataZoomModel.get('zoomLock', true) ? 'move' : true; |
| |
| if (typePriority[prefix + oneType] > typePriority[prefix + controlType]) { |
| controlType = oneType; |
| } // Prevent default move event by default. If one false, do not prevent. Otherwise |
| // users may be confused why it does not work when multiple insideZooms exist. |
| |
| |
| preventDefaultMouseMove &= dataZoomModel.get('preventDefaultMouseMove', true); |
| }); |
| return { |
| controlType: controlType, |
| opt: { |
| // RoamController will enable all of these functionalities, |
| // and the final behavior is determined by its event listener |
| // provided by each inside zoom. |
| zoomOnMouseWheel: true, |
| moveOnMouseMove: true, |
| moveOnMouseWheel: true, |
| preventDefaultMouseMove: !!preventDefaultMouseMove |
| } |
| }; |
| } |