595 lines
21 KiB
JavaScript
595 lines
21 KiB
JavaScript
|
|
/*
|
|
* 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.
|
|
*/
|
|
|
|
|
|
/**
|
|
* AUTO-GENERATED FILE. DO NOT MODIFY.
|
|
*/
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
// Layout helpers for each component positioning
|
|
import * as zrUtil from 'zrender/lib/core/util.js';
|
|
import BoundingRect from 'zrender/lib/core/BoundingRect.js';
|
|
import { parsePercent } from './number.js';
|
|
import * as formatUtil from './format.js';
|
|
import { error } from './log.js';
|
|
import { BoxCoordinateSystemCoordFrom, getCoordForBoxCoordSys } from '../core/CoordinateSystem.js';
|
|
var each = zrUtil.each;
|
|
/**
|
|
* @public
|
|
*/
|
|
export var LOCATION_PARAMS = ['left', 'right', 'top', 'bottom', 'width', 'height'];
|
|
/**
|
|
* @public
|
|
*/
|
|
export var HV_NAMES = [['width', 'left', 'right'], ['height', 'top', 'bottom']];
|
|
function boxLayout(orient, group, gap, maxWidth, maxHeight) {
|
|
var x = 0;
|
|
var y = 0;
|
|
if (maxWidth == null) {
|
|
maxWidth = Infinity;
|
|
}
|
|
if (maxHeight == null) {
|
|
maxHeight = Infinity;
|
|
}
|
|
var currentLineMaxSize = 0;
|
|
group.eachChild(function (child, idx) {
|
|
var rect = child.getBoundingRect();
|
|
var nextChild = group.childAt(idx + 1);
|
|
var nextChildRect = nextChild && nextChild.getBoundingRect();
|
|
var nextX;
|
|
var nextY;
|
|
if (orient === 'horizontal') {
|
|
var moveX = rect.width + (nextChildRect ? -nextChildRect.x + rect.x : 0);
|
|
nextX = x + moveX;
|
|
// Wrap when width exceeds maxWidth or meet a `newline` group
|
|
// FIXME compare before adding gap?
|
|
if (nextX > maxWidth || child.newline) {
|
|
x = 0;
|
|
nextX = moveX;
|
|
y += currentLineMaxSize + gap;
|
|
currentLineMaxSize = rect.height;
|
|
} else {
|
|
// FIXME: consider rect.y is not `0`?
|
|
currentLineMaxSize = Math.max(currentLineMaxSize, rect.height);
|
|
}
|
|
} else {
|
|
var moveY = rect.height + (nextChildRect ? -nextChildRect.y + rect.y : 0);
|
|
nextY = y + moveY;
|
|
// Wrap when width exceeds maxHeight or meet a `newline` group
|
|
if (nextY > maxHeight || child.newline) {
|
|
x += currentLineMaxSize + gap;
|
|
y = 0;
|
|
nextY = moveY;
|
|
currentLineMaxSize = rect.width;
|
|
} else {
|
|
currentLineMaxSize = Math.max(currentLineMaxSize, rect.width);
|
|
}
|
|
}
|
|
if (child.newline) {
|
|
return;
|
|
}
|
|
child.x = x;
|
|
child.y = y;
|
|
child.markRedraw();
|
|
orient === 'horizontal' ? x = nextX + gap : y = nextY + gap;
|
|
});
|
|
}
|
|
/**
|
|
* VBox or HBox layouting
|
|
* @param {string} orient
|
|
* @param {module:zrender/graphic/Group} group
|
|
* @param {number} gap
|
|
* @param {number} [width=Infinity]
|
|
* @param {number} [height=Infinity]
|
|
*/
|
|
export var box = boxLayout;
|
|
/**
|
|
* VBox layouting
|
|
* @param {module:zrender/graphic/Group} group
|
|
* @param {number} gap
|
|
* @param {number} [width=Infinity]
|
|
* @param {number} [height=Infinity]
|
|
*/
|
|
export var vbox = zrUtil.curry(boxLayout, 'vertical');
|
|
/**
|
|
* HBox layouting
|
|
* @param {module:zrender/graphic/Group} group
|
|
* @param {number} gap
|
|
* @param {number} [width=Infinity]
|
|
* @param {number} [height=Infinity]
|
|
*/
|
|
export var hbox = zrUtil.curry(boxLayout, 'horizontal');
|
|
export function getBoxLayoutParams(boxLayoutModel, ignoreParent) {
|
|
return {
|
|
left: boxLayoutModel.getShallow('left', ignoreParent),
|
|
top: boxLayoutModel.getShallow('top', ignoreParent),
|
|
right: boxLayoutModel.getShallow('right', ignoreParent),
|
|
bottom: boxLayoutModel.getShallow('bottom', ignoreParent),
|
|
width: boxLayoutModel.getShallow('width', ignoreParent),
|
|
height: boxLayoutModel.getShallow('height', ignoreParent)
|
|
};
|
|
}
|
|
function getViewRectAndCenterForCircleLayout(seriesModel, api) {
|
|
var layoutRef = createBoxLayoutReference(seriesModel, api, {
|
|
enableLayoutOnlyByCenter: true
|
|
});
|
|
var boxLayoutParams = seriesModel.getBoxLayoutParams();
|
|
var viewRect;
|
|
var center;
|
|
if (layoutRef.type === BoxLayoutReferenceType.point) {
|
|
center = layoutRef.refPoint;
|
|
// `viewRect` is required in `pie/labelLayout.ts`.
|
|
viewRect = getLayoutRect(boxLayoutParams, {
|
|
width: api.getWidth(),
|
|
height: api.getHeight()
|
|
});
|
|
} else {
|
|
// layoutRef.type === layout.BoxLayoutReferenceType.rect
|
|
var centerOption = seriesModel.get('center');
|
|
var centerOptionArr = zrUtil.isArray(centerOption) ? centerOption : [centerOption, centerOption];
|
|
viewRect = getLayoutRect(boxLayoutParams, layoutRef.refContainer);
|
|
center = layoutRef.boxCoordFrom === BoxCoordinateSystemCoordFrom.coord2 ? layoutRef.refPoint // option `series.center` has been used as coord.
|
|
: [parsePercent(centerOptionArr[0], viewRect.width) + viewRect.x, parsePercent(centerOptionArr[1], viewRect.height) + viewRect.y];
|
|
}
|
|
return {
|
|
viewRect: viewRect,
|
|
center: center
|
|
};
|
|
}
|
|
export function getCircleLayout(seriesModel, api) {
|
|
// center can be string or number when coordinateSystem is specified
|
|
var _a = getViewRectAndCenterForCircleLayout(seriesModel, api),
|
|
viewRect = _a.viewRect,
|
|
center = _a.center;
|
|
var radius = seriesModel.get('radius');
|
|
if (!zrUtil.isArray(radius)) {
|
|
radius = [0, radius];
|
|
}
|
|
var width = parsePercent(viewRect.width, api.getWidth());
|
|
var height = parsePercent(viewRect.height, api.getHeight());
|
|
var size = Math.min(width, height);
|
|
var r0 = parsePercent(radius[0], size / 2);
|
|
var r = parsePercent(radius[1], size / 2);
|
|
return {
|
|
cx: center[0],
|
|
cy: center[1],
|
|
r0: r0,
|
|
r: r,
|
|
viewRect: viewRect
|
|
};
|
|
}
|
|
/**
|
|
* Parse position info.
|
|
*/
|
|
export function getLayoutRect(positionInfo, containerRect,
|
|
// This is the space from the `containerRect` to the returned bounding rect.
|
|
// Commonly used in option `legend.padding`, `timeline.padding`, `title.padding`,
|
|
// `visualMap.padding`, ...
|
|
// [NOTICE]:
|
|
// It's named `margin`, because it's the space that outside the bounding rect. But from
|
|
// the perspective of the the caller, it's commonly used as the `padding` of a component,
|
|
// because conventionally background color covers this space.
|
|
// [BEHAVIOR]:
|
|
// - If width/height is specified, `margin` does not effect them.
|
|
// - Otherwise, they are calculated based on the rect that `containerRect` shrinked by `margin`.
|
|
// - left/right/top/bottom are based on the rect that `containerRect` shrinked by `margin`.
|
|
margin) {
|
|
margin = formatUtil.normalizeCssArray(margin || 0);
|
|
var containerWidth = containerRect.width;
|
|
var containerHeight = containerRect.height;
|
|
var left = parsePercent(positionInfo.left, containerWidth);
|
|
var top = parsePercent(positionInfo.top, containerHeight);
|
|
var right = parsePercent(positionInfo.right, containerWidth);
|
|
var bottom = parsePercent(positionInfo.bottom, containerHeight);
|
|
var width = parsePercent(positionInfo.width, containerWidth);
|
|
var height = parsePercent(positionInfo.height, containerHeight);
|
|
var verticalMargin = margin[2] + margin[0];
|
|
var horizontalMargin = margin[1] + margin[3];
|
|
var aspect = positionInfo.aspect;
|
|
// If width is not specified, calculate width from left and right
|
|
if (isNaN(width)) {
|
|
width = containerWidth - right - horizontalMargin - left;
|
|
}
|
|
if (isNaN(height)) {
|
|
height = containerHeight - bottom - verticalMargin - top;
|
|
}
|
|
if (aspect != null) {
|
|
// If width and height are not given
|
|
// 1. Graph should not exceeds the container
|
|
// 2. Aspect must be keeped
|
|
// 3. Graph should take the space as more as possible
|
|
// FIXME
|
|
// Margin is not considered, because there is no case that both
|
|
// using margin and aspect so far.
|
|
if (isNaN(width) && isNaN(height)) {
|
|
// PENDING: if only `left` or `right` is defined, perhaps it's more preferable to
|
|
// calculate size based on `containerWidth - left` or `containerWidth - left` here,
|
|
// but for backward compatibility we do not change it.
|
|
if (aspect > containerWidth / containerHeight) {
|
|
width = containerWidth * 0.8;
|
|
} else {
|
|
height = containerHeight * 0.8;
|
|
}
|
|
}
|
|
// Calculate width or height with given aspect
|
|
if (isNaN(width)) {
|
|
width = aspect * height;
|
|
}
|
|
if (isNaN(height)) {
|
|
height = width / aspect;
|
|
}
|
|
}
|
|
// If left is not specified, calculate left from right and width
|
|
if (isNaN(left)) {
|
|
left = containerWidth - right - width - horizontalMargin;
|
|
}
|
|
if (isNaN(top)) {
|
|
top = containerHeight - bottom - height - verticalMargin;
|
|
}
|
|
// Align left and top
|
|
switch (positionInfo.left || positionInfo.right) {
|
|
case 'center':
|
|
left = containerWidth / 2 - width / 2 - margin[3];
|
|
break;
|
|
case 'right':
|
|
left = containerWidth - width - horizontalMargin;
|
|
break;
|
|
}
|
|
switch (positionInfo.top || positionInfo.bottom) {
|
|
case 'middle':
|
|
case 'center':
|
|
top = containerHeight / 2 - height / 2 - margin[0];
|
|
break;
|
|
case 'bottom':
|
|
top = containerHeight - height - verticalMargin;
|
|
break;
|
|
}
|
|
// If something is wrong and left, top, width, height are calculated as NaN
|
|
left = left || 0;
|
|
top = top || 0;
|
|
if (isNaN(width)) {
|
|
// Width may be NaN if only one value is given except width
|
|
width = containerWidth - horizontalMargin - left - (right || 0);
|
|
}
|
|
if (isNaN(height)) {
|
|
// Height may be NaN if only one value is given except height
|
|
height = containerHeight - verticalMargin - top - (bottom || 0);
|
|
}
|
|
var rect = new BoundingRect((containerRect.x || 0) + left + margin[3], (containerRect.y || 0) + top + margin[0], width, height);
|
|
rect.margin = margin;
|
|
return rect;
|
|
}
|
|
/**
|
|
* PENDING:
|
|
* when preserveAspect: 'cover' and aspect is near Infinity
|
|
* or when preserveAspect: 'contain' and aspect is near 0,
|
|
* the result width or height is near Inifity. It's logically correct,
|
|
* Therefore currently we do not handle it, until bad cases arise.
|
|
*/
|
|
export function applyPreserveAspect(component, layoutRect,
|
|
// That is, `width / height`.
|
|
// Assume `aspect` is positive.
|
|
aspect) {
|
|
var preserveAspect = component.getShallow('preserveAspect', true);
|
|
if (!preserveAspect) {
|
|
return layoutRect;
|
|
}
|
|
var actualAspect = layoutRect.width / layoutRect.height;
|
|
if (Math.abs(Math.atan(aspect) - Math.atan(actualAspect)) < 1e-9) {
|
|
return layoutRect;
|
|
}
|
|
var preserveAspectAlign = component.getShallow('preserveAspectAlign', true);
|
|
var preserveAspectVerticalAlign = component.getShallow('preserveAspectVerticalAlign', true);
|
|
var layoutOptInner = {
|
|
width: layoutRect.width,
|
|
height: layoutRect.height
|
|
};
|
|
var isCover = preserveAspect === 'cover';
|
|
if (actualAspect > aspect && !isCover || actualAspect < aspect && isCover) {
|
|
layoutOptInner.width = layoutRect.height * aspect;
|
|
preserveAspectAlign === 'left' ? layoutOptInner.left = 0 : preserveAspectAlign === 'right' ? layoutOptInner.right = 0 : layoutOptInner.left = 'center';
|
|
} else {
|
|
layoutOptInner.height = layoutRect.width / aspect;
|
|
preserveAspectVerticalAlign === 'top' ? layoutOptInner.top = 0 : preserveAspectVerticalAlign === 'bottom' ? layoutOptInner.bottom = 0 : layoutOptInner.top = 'middle';
|
|
}
|
|
return getLayoutRect(layoutOptInner, layoutRect);
|
|
}
|
|
export var BoxLayoutReferenceType = {
|
|
rect: 1,
|
|
point: 2
|
|
};
|
|
/**
|
|
* Uniformly calculate layout reference (rect or center) based on either:
|
|
* - viewport:
|
|
* - Get `refContainer` as `{x: 0, y: 0, width: api.getWidth(), height: api.getHeight()}`
|
|
* - coordinate system, which can serve in several ways:
|
|
* - Use `dataToPoint` to get the `refPoint`, such as, in cartesian2d coord sys.
|
|
* - Use `dataToLayout` to get the `refContainer`, such as, in matrix coord sys.
|
|
*/
|
|
export function createBoxLayoutReference(model, api, opt) {
|
|
var refContainer;
|
|
var refPoint;
|
|
var layoutRefType;
|
|
var boxCoordSys = model.boxCoordinateSystem;
|
|
var boxCoordFrom;
|
|
if (boxCoordSys) {
|
|
var _a = getCoordForBoxCoordSys(model),
|
|
coord = _a.coord,
|
|
from = _a.from;
|
|
// Do not use `clamp` in `dataToLayout` and `dataToPoint`, because:
|
|
// 1. Should support overflow (such as, by dataZoom), where NaN should be in the result.
|
|
// 2. Be consistent with the way used in `series.data`
|
|
if (boxCoordSys.dataToLayout) {
|
|
layoutRefType = BoxLayoutReferenceType.rect;
|
|
boxCoordFrom = from;
|
|
var result = boxCoordSys.dataToLayout(coord);
|
|
refContainer = result.contentRect || result.rect;
|
|
} else if (opt && opt.enableLayoutOnlyByCenter && boxCoordSys.dataToPoint) {
|
|
layoutRefType = BoxLayoutReferenceType.point;
|
|
boxCoordFrom = from;
|
|
refPoint = boxCoordSys.dataToPoint(coord);
|
|
} else {
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
error(model.type + "[" + model.componentIndex + "]" + (" layout based on " + boxCoordSys.type + " is not supported."));
|
|
}
|
|
}
|
|
}
|
|
if (layoutRefType == null) {
|
|
layoutRefType = BoxLayoutReferenceType.rect;
|
|
}
|
|
if (layoutRefType === BoxLayoutReferenceType.rect) {
|
|
if (!refContainer) {
|
|
refContainer = {
|
|
x: 0,
|
|
y: 0,
|
|
width: api.getWidth(),
|
|
height: api.getHeight()
|
|
};
|
|
}
|
|
refPoint = [refContainer.x + refContainer.width / 2, refContainer.y + refContainer.height / 2];
|
|
}
|
|
return {
|
|
type: layoutRefType,
|
|
refContainer: refContainer,
|
|
refPoint: refPoint,
|
|
boxCoordFrom: boxCoordFrom
|
|
};
|
|
}
|
|
/**
|
|
* Position a zr element in viewport
|
|
* Group position is specified by either
|
|
* {left, top}, {right, bottom}
|
|
* If all properties exists, right and bottom will be igonred.
|
|
*
|
|
* Logic:
|
|
* 1. Scale (against origin point in parent coord)
|
|
* 2. Rotate (against origin point in parent coord)
|
|
* 3. Translate (with el.position by this method)
|
|
* So this method only fixes the last step 'Translate', which does not affect
|
|
* scaling and rotating.
|
|
*
|
|
* If be called repeatedly with the same input el, the same result will be gotten.
|
|
*
|
|
* Return true if the layout happened.
|
|
*
|
|
* @param el Should have `getBoundingRect` method.
|
|
* @param positionInfo
|
|
* @param positionInfo.left
|
|
* @param positionInfo.top
|
|
* @param positionInfo.right
|
|
* @param positionInfo.bottom
|
|
* @param positionInfo.width Only for opt.boundingModel: 'raw'
|
|
* @param positionInfo.height Only for opt.boundingModel: 'raw'
|
|
* @param containerRect
|
|
* @param margin
|
|
* @param opt
|
|
* @param opt.hv Only horizontal or only vertical. Default to be [1, 1]
|
|
* @param opt.boundingMode
|
|
* Specify how to calculate boundingRect when locating.
|
|
* 'all': Position the boundingRect that is transformed and uioned
|
|
* both itself and its descendants.
|
|
* This mode simplies confine the elements in the bounding
|
|
* of their container (e.g., using 'right: 0').
|
|
* 'raw': Position the boundingRect that is not transformed and only itself.
|
|
* This mode is useful when you want a element can overflow its
|
|
* container. (Consider a rotated circle needs to be located in a corner.)
|
|
* In this mode positionInfo.width/height can only be number.
|
|
*/
|
|
export function positionElement(el, positionInfo, containerRect, margin, opt, out) {
|
|
var h = !opt || !opt.hv || opt.hv[0];
|
|
var v = !opt || !opt.hv || opt.hv[1];
|
|
var boundingMode = opt && opt.boundingMode || 'all';
|
|
out = out || el;
|
|
out.x = el.x;
|
|
out.y = el.y;
|
|
if (!h && !v) {
|
|
return false;
|
|
}
|
|
var rect;
|
|
if (boundingMode === 'raw') {
|
|
rect = el.type === 'group' ? new BoundingRect(0, 0, +positionInfo.width || 0, +positionInfo.height || 0) : el.getBoundingRect();
|
|
} else {
|
|
rect = el.getBoundingRect();
|
|
if (el.needLocalTransform()) {
|
|
var transform = el.getLocalTransform();
|
|
// Notice: raw rect may be inner object of el,
|
|
// which should not be modified.
|
|
rect = rect.clone();
|
|
rect.applyTransform(transform);
|
|
}
|
|
}
|
|
// The real width and height can not be specified but calculated by the given el.
|
|
var layoutRect = getLayoutRect(zrUtil.defaults({
|
|
width: rect.width,
|
|
height: rect.height
|
|
}, positionInfo), containerRect, margin);
|
|
// Because 'tranlate' is the last step in transform
|
|
// (see zrender/core/Transformable#getLocalTransform),
|
|
// we can just only modify el.position to get final result.
|
|
var dx = h ? layoutRect.x - rect.x : 0;
|
|
var dy = v ? layoutRect.y - rect.y : 0;
|
|
if (boundingMode === 'raw') {
|
|
out.x = dx;
|
|
out.y = dy;
|
|
} else {
|
|
out.x += dx;
|
|
out.y += dy;
|
|
}
|
|
if (out === el) {
|
|
el.markRedraw();
|
|
}
|
|
return true;
|
|
}
|
|
/**
|
|
* @param option Contains some of the properties in HV_NAMES.
|
|
* @param hvIdx 0: horizontal; 1: vertical.
|
|
*/
|
|
export function sizeCalculable(option, hvIdx) {
|
|
return option[HV_NAMES[hvIdx][0]] != null || option[HV_NAMES[hvIdx][1]] != null && option[HV_NAMES[hvIdx][2]] != null;
|
|
}
|
|
export function fetchLayoutMode(ins) {
|
|
var layoutMode = ins.layoutMode || ins.constructor.layoutMode;
|
|
return zrUtil.isObject(layoutMode) ? layoutMode : layoutMode ? {
|
|
type: layoutMode
|
|
} : null;
|
|
}
|
|
/**
|
|
* Consider Case:
|
|
* When default option has {left: 0, width: 100}, and we set {right: 0}
|
|
* through setOption or media query, using normal zrUtil.merge will cause
|
|
* {right: 0} does not take effect.
|
|
*
|
|
* @example
|
|
* ComponentModel.extend({
|
|
* init: function () {
|
|
* ...
|
|
* let inputPositionParams = layout.getLayoutParams(option);
|
|
* this.mergeOption(inputPositionParams);
|
|
* },
|
|
* mergeOption: function (newOption) {
|
|
* newOption && zrUtil.merge(thisOption, newOption, true);
|
|
* layout.mergeLayoutParam(thisOption, newOption);
|
|
* }
|
|
* });
|
|
*
|
|
* @param targetOption
|
|
* @param newOption
|
|
* @param opt
|
|
*/
|
|
export function mergeLayoutParam(targetOption, newOption, opt) {
|
|
var ignoreSize = opt && opt.ignoreSize;
|
|
!zrUtil.isArray(ignoreSize) && (ignoreSize = [ignoreSize, ignoreSize]);
|
|
var hResult = merge(HV_NAMES[0], 0);
|
|
var vResult = merge(HV_NAMES[1], 1);
|
|
copy(HV_NAMES[0], targetOption, hResult);
|
|
copy(HV_NAMES[1], targetOption, vResult);
|
|
function merge(names, hvIdx) {
|
|
var newParams = {};
|
|
var newValueCount = 0;
|
|
var merged = {};
|
|
var mergedValueCount = 0;
|
|
var enoughParamNumber = 2;
|
|
each(names, function (name) {
|
|
merged[name] = targetOption[name];
|
|
});
|
|
each(names, function (name) {
|
|
// Consider case: newOption.width is null, which is
|
|
// set by user for removing width setting.
|
|
zrUtil.hasOwn(newOption, name) && (newParams[name] = merged[name] = newOption[name]);
|
|
hasValue(newParams, name) && newValueCount++;
|
|
hasValue(merged, name) && mergedValueCount++;
|
|
});
|
|
if (ignoreSize[hvIdx]) {
|
|
// Only one of left/right is premitted to exist.
|
|
if (hasValue(newOption, names[1])) {
|
|
merged[names[2]] = null;
|
|
} else if (hasValue(newOption, names[2])) {
|
|
merged[names[1]] = null;
|
|
}
|
|
return merged;
|
|
}
|
|
// Case: newOption: {width: ..., right: ...},
|
|
// or targetOption: {right: ...} and newOption: {width: ...},
|
|
// There is no conflict when merged only has params count
|
|
// little than enoughParamNumber.
|
|
if (mergedValueCount === enoughParamNumber || !newValueCount) {
|
|
return merged;
|
|
}
|
|
// Case: newOption: {width: ..., right: ...},
|
|
// Than we can make sure user only want those two, and ignore
|
|
// all origin params in targetOption.
|
|
else if (newValueCount >= enoughParamNumber) {
|
|
return newParams;
|
|
} else {
|
|
// Chose another param from targetOption by priority.
|
|
for (var i = 0; i < names.length; i++) {
|
|
var name_1 = names[i];
|
|
if (!zrUtil.hasOwn(newParams, name_1) && zrUtil.hasOwn(targetOption, name_1)) {
|
|
newParams[name_1] = targetOption[name_1];
|
|
break;
|
|
}
|
|
}
|
|
return newParams;
|
|
}
|
|
}
|
|
function hasValue(obj, name) {
|
|
return obj[name] != null && obj[name] !== 'auto';
|
|
}
|
|
function copy(names, target, source) {
|
|
each(names, function (name) {
|
|
target[name] = source[name];
|
|
});
|
|
}
|
|
}
|
|
/**
|
|
* Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object.
|
|
*/
|
|
export function getLayoutParams(source) {
|
|
return copyLayoutParams({}, source);
|
|
}
|
|
/**
|
|
* Retrieve 'left', 'right', 'top', 'bottom', 'width', 'height' from object.
|
|
* @param {Object} source
|
|
* @return {Object} Result contains those props.
|
|
*/
|
|
export function copyLayoutParams(target, source) {
|
|
source && target && each(LOCATION_PARAMS, function (name) {
|
|
zrUtil.hasOwn(source, name) && (target[name] = source[name]);
|
|
});
|
|
return target;
|
|
} |