/* * 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. */ import { __extends } from "tslib"; import Path from 'zrender/lib/graphic/Path.js'; import Group from 'zrender/lib/graphic/Group.js'; import { extend, each, map } from 'zrender/lib/core/util.js'; import { Rect, Sector, updateProps, initProps, removeElementWithFadeOut, traverseElements } from '../../util/graphic.js'; import { getECData } from '../../util/innerStore.js'; import { setStatesStylesFromModel, toggleHoverEmphasis } from '../../util/states.js'; import { setLabelStyle, getLabelStatesModels, setLabelValueAnimation, labelInner } from '../../label/labelStyle.js'; import { throttle } from '../../util/throttle.js'; import { createClipPath } from '../helper/createClipPathFromCoordSys.js'; import Sausage from '../../util/shape/sausage.js'; import ChartView from '../../view/Chart.js'; import { isCoordinateSystemType } from '../../coord/CoordinateSystem.js'; import { getDefaultLabel, getDefaultInterpolatedLabel } from '../helper/labelHelper.js'; import { warn } from '../../util/log.js'; import { createSectorCalculateTextPosition, setSectorTextRotation } from '../../label/sectorLabel.js'; import { saveOldStyle } from '../../animation/basicTransition.js'; import { getSectorCornerRadius } from '../helper/sectorHelper.js'; var mathMax = Math.max; var mathMin = Math.min; function getClipArea(coord, data) { var coordSysClipArea = coord.getArea && coord.getArea(); if (isCoordinateSystemType(coord, 'cartesian2d')) { var baseAxis = coord.getBaseAxis(); // When boundaryGap is false or using time axis. bar may exceed the grid. // We should not clip this part. // See test/bar2.html if (baseAxis.type !== 'category' || !baseAxis.onBand) { var expandWidth = data.getLayout('bandWidth'); if (baseAxis.isHorizontal()) { coordSysClipArea.x -= expandWidth; coordSysClipArea.width += expandWidth * 2; } else { coordSysClipArea.y -= expandWidth; coordSysClipArea.height += expandWidth * 2; } } } return coordSysClipArea; } var BarView = /** @class */ function (_super) { __extends(BarView, _super); function BarView() { var _this = _super.call(this) || this; _this.type = BarView.type; _this._isFirstFrame = true; return _this; } BarView.prototype.render = function (seriesModel, ecModel, api, payload) { this._model = seriesModel; this._removeOnRenderedListener(api); this._updateDrawMode(seriesModel); var coordinateSystemType = seriesModel.get('coordinateSystem'); if (coordinateSystemType === 'cartesian2d' || coordinateSystemType === 'polar') { // Clear previously rendered progressive elements. this._progressiveEls = null; this._isLargeDraw ? this._renderLarge(seriesModel, ecModel, api) : this._renderNormal(seriesModel, ecModel, api, payload); } else if (process.env.NODE_ENV !== 'production') { warn('Only cartesian2d and polar supported for bar.'); } }; BarView.prototype.incrementalPrepareRender = function (seriesModel) { this._clear(); this._updateDrawMode(seriesModel); // incremental also need to clip, otherwise might be overlow. // But must not set clip in each frame, otherwise all of the children will be marked redraw. this._updateLargeClip(seriesModel); }; BarView.prototype.incrementalRender = function (params, seriesModel) { // Reset this._progressiveEls = []; // Do not support progressive in normal mode. this._incrementalRenderLarge(params, seriesModel); }; BarView.prototype.eachRendered = function (cb) { traverseElements(this._progressiveEls || this.group, cb); }; BarView.prototype._updateDrawMode = function (seriesModel) { var isLargeDraw = seriesModel.pipelineContext.large; if (this._isLargeDraw == null || isLargeDraw !== this._isLargeDraw) { this._isLargeDraw = isLargeDraw; this._clear(); } }; BarView.prototype._renderNormal = function (seriesModel, ecModel, api, payload) { var group = this.group; var data = seriesModel.getData(); var oldData = this._data; var coord = seriesModel.coordinateSystem; var baseAxis = coord.getBaseAxis(); var isHorizontalOrRadial; if (coord.type === 'cartesian2d') { isHorizontalOrRadial = baseAxis.isHorizontal(); } else if (coord.type === 'polar') { isHorizontalOrRadial = baseAxis.dim === 'angle'; } var animationModel = seriesModel.isAnimationEnabled() ? seriesModel : null; var realtimeSortCfg = shouldRealtimeSort(seriesModel, coord); if (realtimeSortCfg) { this._enableRealtimeSort(realtimeSortCfg, data, api); } var needsClip = seriesModel.get('clip', true) || realtimeSortCfg; var coordSysClipArea = getClipArea(coord, data); // If there is clipPath created in large mode. Remove it. group.removeClipPath(); // We don't use clipPath in normal mode because we needs a perfect animation // And don't want the label are clipped. var roundCap = seriesModel.get('roundCap', true); var drawBackground = seriesModel.get('showBackground', true); var backgroundModel = seriesModel.getModel('backgroundStyle'); var barBorderRadius = backgroundModel.get('borderRadius') || 0; var bgEls = []; var oldBgEls = this._backgroundEls; var isInitSort = payload && payload.isInitSort; var isChangeOrder = payload && payload.type === 'changeAxisOrder'; function createBackground(dataIndex) { var bgLayout = getLayout[coord.type](data, dataIndex); var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout); bgEl.useStyle(backgroundModel.getItemStyle()); // Only cartesian2d support borderRadius. if (coord.type === 'cartesian2d') { bgEl.setShape('r', barBorderRadius); } else { bgEl.setShape('cornerRadius', barBorderRadius); } bgEls[dataIndex] = bgEl; return bgEl; } ; data.diff(oldData).add(function (dataIndex) { var itemModel = data.getItemModel(dataIndex); var layout = getLayout[coord.type](data, dataIndex, itemModel); if (drawBackground) { createBackground(dataIndex); } // If dataZoom in filteMode: 'empty', the baseValue can be set as NaN in "axisProxy". if (!data.hasValue(dataIndex) || !isValidLayout[coord.type](layout)) { return; } var isClipped = false; if (needsClip) { // Clip will modify the layout params. // And return a boolean to determine if the shape are fully clipped. isClipped = clip[coord.type](coordSysClipArea, layout); } var el = elementCreator[coord.type](seriesModel, data, dataIndex, layout, isHorizontalOrRadial, animationModel, baseAxis.model, false, roundCap); if (realtimeSortCfg) { /** * Force label animation because even if the element is * ignored because it's clipped, it may not be clipped after * changing order. Then, if not using forceLabelAnimation, * the label animation was never started, in which case, * the label will be the final value and doesn't have label * animation. */ el.forceLabelAnimation = true; } updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar'); if (isInitSort) { el.attr({ shape: layout }); } else if (realtimeSortCfg) { updateRealtimeAnimation(realtimeSortCfg, animationModel, el, layout, dataIndex, isHorizontalOrRadial, false, false); } else { initProps(el, { shape: layout }, seriesModel, dataIndex); } data.setItemGraphicEl(dataIndex, el); group.add(el); el.ignore = isClipped; }).update(function (newIndex, oldIndex) { var itemModel = data.getItemModel(newIndex); var layout = getLayout[coord.type](data, newIndex, itemModel); if (drawBackground) { var bgEl = void 0; if (oldBgEls.length === 0) { bgEl = createBackground(oldIndex); } else { bgEl = oldBgEls[oldIndex]; bgEl.useStyle(backgroundModel.getItemStyle()); // Only cartesian2d support borderRadius. if (coord.type === 'cartesian2d') { bgEl.setShape('r', barBorderRadius); } else { bgEl.setShape('cornerRadius', barBorderRadius); } bgEls[newIndex] = bgEl; } var bgLayout = getLayout[coord.type](data, newIndex); var shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord); updateProps(bgEl, { shape: shape }, animationModel, newIndex); } var el = oldData.getItemGraphicEl(oldIndex); if (!data.hasValue(newIndex) || !isValidLayout[coord.type](layout)) { group.remove(el); return; } var isClipped = false; if (needsClip) { isClipped = clip[coord.type](coordSysClipArea, layout); if (isClipped) { group.remove(el); } } if (!el) { el = elementCreator[coord.type](seriesModel, data, newIndex, layout, isHorizontalOrRadial, animationModel, baseAxis.model, !!el, roundCap); } else { saveOldStyle(el); } if (realtimeSortCfg) { el.forceLabelAnimation = true; } if (isChangeOrder) { var textEl = el.getTextContent(); if (textEl) { var labelInnerStore = labelInner(textEl); if (labelInnerStore.prevValue != null) { /** * Set preValue to be value so that no new label * should be started, otherwise, it will take a full * `animationDurationUpdate` time to finish the * animation, which is not expected. */ labelInnerStore.prevValue = labelInnerStore.value; } } } // Not change anything if only order changed. // Especially not change label. else { updateStyle(el, data, newIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar'); } if (isInitSort) { el.attr({ shape: layout }); } else if (realtimeSortCfg) { updateRealtimeAnimation(realtimeSortCfg, animationModel, el, layout, newIndex, isHorizontalOrRadial, true, isChangeOrder); } else { updateProps(el, { shape: layout }, seriesModel, newIndex, null); } data.setItemGraphicEl(newIndex, el); el.ignore = isClipped; group.add(el); }).remove(function (dataIndex) { var el = oldData.getItemGraphicEl(dataIndex); el && removeElementWithFadeOut(el, seriesModel, dataIndex); }).execute(); var bgGroup = this._backgroundGroup || (this._backgroundGroup = new Group()); bgGroup.removeAll(); for (var i = 0; i < bgEls.length; ++i) { bgGroup.add(bgEls[i]); } group.add(bgGroup); this._backgroundEls = bgEls; this._data = data; }; BarView.prototype._renderLarge = function (seriesModel, ecModel, api) { this._clear(); createLarge(seriesModel, this.group); this._updateLargeClip(seriesModel); }; BarView.prototype._incrementalRenderLarge = function (params, seriesModel) { this._removeBackground(); createLarge(seriesModel, this.group, this._progressiveEls, true); }; BarView.prototype._updateLargeClip = function (seriesModel) { // Use clipPath in large mode. var clipPath = seriesModel.get('clip', true) && createClipPath(seriesModel.coordinateSystem, false, seriesModel); var group = this.group; if (clipPath) { group.setClipPath(clipPath); } else { group.removeClipPath(); } }; BarView.prototype._enableRealtimeSort = function (realtimeSortCfg, data, api) { var _this = this; // If no data in the first frame, wait for data to initSort if (!data.count()) { return; } var baseAxis = realtimeSortCfg.baseAxis; if (this._isFirstFrame) { this._dispatchInitSort(data, realtimeSortCfg, api); this._isFirstFrame = false; } else { var orderMapping_1 = function (idx) { var el = data.getItemGraphicEl(idx); var shape = el && el.shape; return shape && // The result should be consistent with the initial sort by data value. // Do not support the case that both positive and negative exist. Math.abs(baseAxis.isHorizontal() ? shape.height : shape.width) // If data is NaN, shape.xxx may be NaN, so use || 0 here in case || 0; }; this._onRendered = function () { _this._updateSortWithinSameData(data, orderMapping_1, baseAxis, api); }; api.getZr().on('rendered', this._onRendered); } }; BarView.prototype._dataSort = function (data, baseAxis, orderMapping) { var info = []; data.each(data.mapDimension(baseAxis.dim), function (ordinalNumber, dataIdx) { var mappedValue = orderMapping(dataIdx); mappedValue = mappedValue == null ? NaN : mappedValue; info.push({ dataIndex: dataIdx, mappedValue: mappedValue, ordinalNumber: ordinalNumber }); }); info.sort(function (a, b) { // If NaN, it will be treated as min val. return b.mappedValue - a.mappedValue; }); return { ordinalNumbers: map(info, function (item) { return item.ordinalNumber; }) }; }; BarView.prototype._isOrderChangedWithinSameData = function (data, orderMapping, baseAxis) { var scale = baseAxis.scale; var ordinalDataDim = data.mapDimension(baseAxis.dim); var lastValue = Number.MAX_VALUE; for (var tickNum = 0, len = scale.getOrdinalMeta().categories.length; tickNum < len; ++tickNum) { var rawIdx = data.rawIndexOf(ordinalDataDim, scale.getRawOrdinalNumber(tickNum)); var value = rawIdx < 0 // If some tick have no bar, the tick will be treated as min. ? Number.MIN_VALUE // PENDING: if dataZoom on baseAxis exits, is it a performance issue? : orderMapping(data.indexOfRawIndex(rawIdx)); if (value > lastValue) { return true; } lastValue = value; } return false; }; /* * Consider the case when A and B changed order, whose representing * bars are both out of sight, we don't wish to trigger reorder action * as long as the order in the view doesn't change. */ BarView.prototype._isOrderDifferentInView = function (orderInfo, baseAxis) { var scale = baseAxis.scale; var extent = scale.getExtent(); var tickNum = Math.max(0, extent[0]); var tickMax = Math.min(extent[1], scale.getOrdinalMeta().categories.length - 1); for (; tickNum <= tickMax; ++tickNum) { if (orderInfo.ordinalNumbers[tickNum] !== scale.getRawOrdinalNumber(tickNum)) { return true; } } }; BarView.prototype._updateSortWithinSameData = function (data, orderMapping, baseAxis, api) { if (!this._isOrderChangedWithinSameData(data, orderMapping, baseAxis)) { return; } var sortInfo = this._dataSort(data, baseAxis, orderMapping); if (this._isOrderDifferentInView(sortInfo, baseAxis)) { this._removeOnRenderedListener(api); api.dispatchAction({ type: 'changeAxisOrder', componentType: baseAxis.dim + 'Axis', axisId: baseAxis.index, sortInfo: sortInfo }); } }; BarView.prototype._dispatchInitSort = function (data, realtimeSortCfg, api) { var baseAxis = realtimeSortCfg.baseAxis; var sortResult = this._dataSort(data, baseAxis, function (dataIdx) { return data.get(data.mapDimension(realtimeSortCfg.otherAxis.dim), dataIdx); }); api.dispatchAction({ type: 'changeAxisOrder', componentType: baseAxis.dim + 'Axis', isInitSort: true, axisId: baseAxis.index, sortInfo: sortResult }); }; BarView.prototype.remove = function (ecModel, api) { this._clear(this._model); this._removeOnRenderedListener(api); }; BarView.prototype.dispose = function (ecModel, api) { this._removeOnRenderedListener(api); }; BarView.prototype._removeOnRenderedListener = function (api) { if (this._onRendered) { api.getZr().off('rendered', this._onRendered); this._onRendered = null; } }; BarView.prototype._clear = function (model) { var group = this.group; var data = this._data; if (model && model.isAnimationEnabled() && data && !this._isLargeDraw) { this._removeBackground(); this._backgroundEls = []; data.eachItemGraphicEl(function (el) { removeElementWithFadeOut(el, model, getECData(el).dataIndex); }); } else { group.removeAll(); } this._data = null; this._isFirstFrame = true; }; BarView.prototype._removeBackground = function () { this.group.remove(this._backgroundGroup); this._backgroundGroup = null; }; BarView.type = 'bar'; return BarView; }(ChartView); var clip = { cartesian2d: function (coordSysBoundingRect, layout) { var signWidth = layout.width < 0 ? -1 : 1; var signHeight = layout.height < 0 ? -1 : 1; // Needs positive width and height if (signWidth < 0) { layout.x += layout.width; layout.width = -layout.width; } if (signHeight < 0) { layout.y += layout.height; layout.height = -layout.height; } var coordSysX2 = coordSysBoundingRect.x + coordSysBoundingRect.width; var coordSysY2 = coordSysBoundingRect.y + coordSysBoundingRect.height; var x = mathMax(layout.x, coordSysBoundingRect.x); var x2 = mathMin(layout.x + layout.width, coordSysX2); var y = mathMax(layout.y, coordSysBoundingRect.y); var y2 = mathMin(layout.y + layout.height, coordSysY2); var xClipped = x2 < x; var yClipped = y2 < y; // When xClipped or yClipped, the element will be marked as `ignore`. // But we should also place the element at the edge of the coord sys bounding rect. // Because if data changed and the bar shows again, its transition animation // will begin at this place. layout.x = xClipped && x > coordSysX2 ? x2 : x; layout.y = yClipped && y > coordSysY2 ? y2 : y; layout.width = xClipped ? 0 : x2 - x; layout.height = yClipped ? 0 : y2 - y; // Reverse back if (signWidth < 0) { layout.x += layout.width; layout.width = -layout.width; } if (signHeight < 0) { layout.y += layout.height; layout.height = -layout.height; } return xClipped || yClipped; }, polar: function (coordSysClipArea, layout) { var signR = layout.r0 <= layout.r ? 1 : -1; // Make sure r is larger than r0 if (signR < 0) { var tmp = layout.r; layout.r = layout.r0; layout.r0 = tmp; } var r = mathMin(layout.r, coordSysClipArea.r); var r0 = mathMax(layout.r0, coordSysClipArea.r0); layout.r = r; layout.r0 = r0; var clipped = r - r0 < 0; // Reverse back if (signR < 0) { var tmp = layout.r; layout.r = layout.r0; layout.r0 = tmp; } return clipped; } }; var elementCreator = { cartesian2d: function (seriesModel, data, newIndex, layout, isHorizontal, animationModel, axisModel, isUpdate, roundCap) { var rect = new Rect({ shape: extend({}, layout), z2: 1 }); rect.__dataIndex = newIndex; rect.name = 'item'; if (animationModel) { var rectShape = rect.shape; var animateProperty = isHorizontal ? 'height' : 'width'; rectShape[animateProperty] = 0; } return rect; }, polar: function (seriesModel, data, newIndex, layout, isRadial, animationModel, axisModel, isUpdate, roundCap) { var ShapeClass = !isRadial && roundCap ? Sausage : Sector; var sector = new ShapeClass({ shape: layout, z2: 1 }); sector.name = 'item'; var positionMap = createPolarPositionMapping(isRadial); sector.calculateTextPosition = createSectorCalculateTextPosition(positionMap, { isRoundCap: ShapeClass === Sausage }); // Animation if (animationModel) { var sectorShape = sector.shape; var animateProperty = isRadial ? 'r' : 'endAngle'; var animateTarget = {}; sectorShape[animateProperty] = isRadial ? layout.r0 : layout.startAngle; animateTarget[animateProperty] = layout[animateProperty]; (isUpdate ? updateProps : initProps)(sector, { shape: animateTarget // __value: typeof dataValue === 'string' ? parseInt(dataValue, 10) : dataValue }, animationModel); } return sector; } }; function shouldRealtimeSort(seriesModel, coordSys) { var realtimeSortOption = seriesModel.get('realtimeSort', true); var baseAxis = coordSys.getBaseAxis(); if (process.env.NODE_ENV !== 'production') { if (realtimeSortOption) { if (baseAxis.type !== 'category') { warn('`realtimeSort` will not work because this bar series is not based on a category axis.'); } if (coordSys.type !== 'cartesian2d') { warn('`realtimeSort` will not work because this bar series is not on cartesian2d.'); } } } if (realtimeSortOption && baseAxis.type === 'category' && coordSys.type === 'cartesian2d') { return { baseAxis: baseAxis, otherAxis: coordSys.getOtherAxis(baseAxis) }; } } function updateRealtimeAnimation(realtimeSortCfg, seriesAnimationModel, el, layout, newIndex, isHorizontal, isUpdate, isChangeOrder) { var seriesTarget; var axisTarget; if (isHorizontal) { axisTarget = { x: layout.x, width: layout.width }; seriesTarget = { y: layout.y, height: layout.height }; } else { axisTarget = { y: layout.y, height: layout.height }; seriesTarget = { x: layout.x, width: layout.width }; } if (!isChangeOrder) { // Keep the original growth animation if only axis order changed. // Not start a new animation. (isUpdate ? updateProps : initProps)(el, { shape: seriesTarget }, seriesAnimationModel, newIndex, null); } var axisAnimationModel = seriesAnimationModel ? realtimeSortCfg.baseAxis.model : null; (isUpdate ? updateProps : initProps)(el, { shape: axisTarget }, axisAnimationModel, newIndex); } function checkPropertiesNotValid(obj, props) { for (var i = 0; i < props.length; i++) { if (!isFinite(obj[props[i]])) { return true; } } return false; } var rectPropties = ['x', 'y', 'width', 'height']; var polarPropties = ['cx', 'cy', 'r', 'startAngle', 'endAngle']; var isValidLayout = { cartesian2d: function (layout) { return !checkPropertiesNotValid(layout, rectPropties); }, polar: function (layout) { return !checkPropertiesNotValid(layout, polarPropties); } }; var getLayout = { // itemModel is only used to get borderWidth, which is not needed // when calculating bar background layout. cartesian2d: function (data, dataIndex, itemModel) { var layout = data.getItemLayout(dataIndex); var fixedLineWidth = itemModel ? getLineWidth(itemModel, layout) : 0; // fix layout with lineWidth var signX = layout.width > 0 ? 1 : -1; var signY = layout.height > 0 ? 1 : -1; return { x: layout.x + signX * fixedLineWidth / 2, y: layout.y + signY * fixedLineWidth / 2, width: layout.width - signX * fixedLineWidth, height: layout.height - signY * fixedLineWidth }; }, polar: function (data, dataIndex, itemModel) { var layout = data.getItemLayout(dataIndex); return { cx: layout.cx, cy: layout.cy, r0: layout.r0, r: layout.r, startAngle: layout.startAngle, endAngle: layout.endAngle, clockwise: layout.clockwise }; } }; function isZeroOnPolar(layout) { return layout.startAngle != null && layout.endAngle != null && layout.startAngle === layout.endAngle; } function createPolarPositionMapping(isRadial) { return function (isRadial) { var arcOrAngle = isRadial ? 'Arc' : 'Angle'; return function (position) { switch (position) { case 'start': case 'insideStart': case 'end': case 'insideEnd': return position + arcOrAngle; default: return position; } }; }(isRadial); } function updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, isPolar) { var style = data.getItemVisual(dataIndex, 'style'); if (!isPolar) { var borderRadius = itemModel.get(['itemStyle', 'borderRadius']) || 0; el.setShape('r', borderRadius); } else if (!seriesModel.get('roundCap')) { var sectorShape = el.shape; var cornerRadius = getSectorCornerRadius(itemModel.getModel('itemStyle'), sectorShape, true); extend(sectorShape, cornerRadius); el.setShape(sectorShape); } el.useStyle(style); var cursorStyle = itemModel.getShallow('cursor'); cursorStyle && el.attr('cursor', cursorStyle); var labelPositionOutside = isPolar ? isHorizontalOrRadial ? layout.r >= layout.r0 ? 'endArc' : 'startArc' : layout.endAngle >= layout.startAngle ? 'endAngle' : 'startAngle' : isHorizontalOrRadial ? layout.height >= 0 ? 'bottom' : 'top' : layout.width >= 0 ? 'right' : 'left'; var labelStatesModels = getLabelStatesModels(itemModel); setLabelStyle(el, labelStatesModels, { labelFetcher: seriesModel, labelDataIndex: dataIndex, defaultText: getDefaultLabel(seriesModel.getData(), dataIndex), inheritColor: style.fill, defaultOpacity: style.opacity, defaultOutsidePosition: labelPositionOutside }); var label = el.getTextContent(); if (isPolar && label) { var position = itemModel.get(['label', 'position']); el.textConfig.inside = position === 'middle' ? true : null; setSectorTextRotation(el, position === 'outside' ? labelPositionOutside : position, createPolarPositionMapping(isHorizontalOrRadial), itemModel.get(['label', 'rotate'])); } setLabelValueAnimation(label, labelStatesModels, seriesModel.getRawValue(dataIndex), function (value) { return getDefaultInterpolatedLabel(data, value); }); var emphasisModel = itemModel.getModel(['emphasis']); toggleHoverEmphasis(el, emphasisModel.get('focus'), emphasisModel.get('blurScope'), emphasisModel.get('disabled')); setStatesStylesFromModel(el, itemModel); if (isZeroOnPolar(layout)) { el.style.fill = 'none'; el.style.stroke = 'none'; each(el.states, function (state) { if (state.style) { state.style.fill = state.style.stroke = 'none'; } }); } } // In case width or height are too small. function getLineWidth(itemModel, rawLayout) { // Has no border. var borderColor = itemModel.get(['itemStyle', 'borderColor']); if (!borderColor || borderColor === 'none') { return 0; } var lineWidth = itemModel.get(['itemStyle', 'borderWidth']) || 0; // width or height may be NaN for empty data var width = isNaN(rawLayout.width) ? Number.MAX_VALUE : Math.abs(rawLayout.width); var height = isNaN(rawLayout.height) ? Number.MAX_VALUE : Math.abs(rawLayout.height); return Math.min(lineWidth, width, height); } var LagePathShape = /** @class */ function () { function LagePathShape() {} return LagePathShape; }(); var LargePath = /** @class */ function (_super) { __extends(LargePath, _super); function LargePath(opts) { var _this = _super.call(this, opts) || this; _this.type = 'largeBar'; return _this; } LargePath.prototype.getDefaultShape = function () { return new LagePathShape(); }; LargePath.prototype.buildPath = function (ctx, shape) { // Drawing lines is more efficient than drawing // a whole line or drawing rects. var points = shape.points; var baseDimIdx = this.baseDimIdx; var valueDimIdx = 1 - this.baseDimIdx; var startPoint = []; var size = []; var barWidth = this.barWidth; for (var i = 0; i < points.length; i += 3) { size[baseDimIdx] = barWidth; size[valueDimIdx] = points[i + 2]; startPoint[baseDimIdx] = points[i + baseDimIdx]; startPoint[valueDimIdx] = points[i + valueDimIdx]; ctx.rect(startPoint[0], startPoint[1], size[0], size[1]); } }; return LargePath; }(Path); function createLarge(seriesModel, group, progressiveEls, incremental) { // TODO support polar var data = seriesModel.getData(); var baseDimIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0; var largeDataIndices = data.getLayout('largeDataIndices'); var barWidth = data.getLayout('size'); var backgroundModel = seriesModel.getModel('backgroundStyle'); var bgPoints = data.getLayout('largeBackgroundPoints'); if (bgPoints) { var bgEl = new LargePath({ shape: { points: bgPoints }, incremental: !!incremental, silent: true, z2: 0 }); bgEl.baseDimIdx = baseDimIdx; bgEl.largeDataIndices = largeDataIndices; bgEl.barWidth = barWidth; bgEl.useStyle(backgroundModel.getItemStyle()); group.add(bgEl); progressiveEls && progressiveEls.push(bgEl); } var el = new LargePath({ shape: { points: data.getLayout('largePoints') }, incremental: !!incremental, ignoreCoarsePointer: true, z2: 1 }); el.baseDimIdx = baseDimIdx; el.largeDataIndices = largeDataIndices; el.barWidth = barWidth; group.add(el); el.useStyle(data.getVisual('style')); // Enable tooltip and user mouse/touch event handlers. getECData(el).seriesIndex = seriesModel.seriesIndex; if (!seriesModel.get('silent')) { el.on('mousedown', largePathUpdateDataIndex); el.on('mousemove', largePathUpdateDataIndex); } progressiveEls && progressiveEls.push(el); } // Use throttle to avoid frequently traverse to find dataIndex. var largePathUpdateDataIndex = throttle(function (event) { var largePath = this; var dataIndex = largePathFindDataIndex(largePath, event.offsetX, event.offsetY); getECData(largePath).dataIndex = dataIndex >= 0 ? dataIndex : null; }, 30, false); function largePathFindDataIndex(largePath, x, y) { var baseDimIdx = largePath.baseDimIdx; var valueDimIdx = 1 - baseDimIdx; var points = largePath.shape.points; var largeDataIndices = largePath.largeDataIndices; var startPoint = []; var size = []; var barWidth = largePath.barWidth; for (var i = 0, len = points.length / 3; i < len; i++) { var ii = i * 3; size[baseDimIdx] = barWidth; size[valueDimIdx] = points[ii + 2]; startPoint[baseDimIdx] = points[ii + baseDimIdx]; startPoint[valueDimIdx] = points[ii + valueDimIdx]; if (size[valueDimIdx] < 0) { startPoint[valueDimIdx] += size[valueDimIdx]; size[valueDimIdx] = -size[valueDimIdx]; } if (x >= startPoint[0] && x <= startPoint[0] + size[0] && y >= startPoint[1] && y <= startPoint[1] + size[1]) { return largeDataIndices[i]; } } return -1; } function createBackgroundShape(isHorizontalOrRadial, layout, coord) { if (isCoordinateSystemType(coord, 'cartesian2d')) { var rectShape = layout; var coordLayout = coord.getArea(); return { x: isHorizontalOrRadial ? rectShape.x : coordLayout.x, y: isHorizontalOrRadial ? coordLayout.y : rectShape.y, width: isHorizontalOrRadial ? rectShape.width : coordLayout.width, height: isHorizontalOrRadial ? coordLayout.height : rectShape.height }; } else { var coordLayout = coord.getArea(); var sectorShape = layout; return { cx: coordLayout.cx, cy: coordLayout.cy, r0: isHorizontalOrRadial ? coordLayout.r0 : sectorShape.r0, r: isHorizontalOrRadial ? coordLayout.r : sectorShape.r, startAngle: isHorizontalOrRadial ? sectorShape.startAngle : 0, endAngle: isHorizontalOrRadial ? sectorShape.endAngle : Math.PI * 2 }; } } function createBackgroundEl(coord, isHorizontalOrRadial, layout) { var ElementClz = coord.type === 'polar' ? Sector : Rect; return new ElementClz({ shape: createBackgroundShape(isHorizontalOrRadial, layout, coord), silent: true, z2: 0 }); } export default BarView;