blob: 4a588586eadf2dbdf737a3c62abe269e043ec844 [file] [log] [blame]
/*
* 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 * as graphic from '../../util/graphic';
import { setStatesStylesFromModel, enableHoverEmphasis } from '../../util/states';
import ChartView from '../../view/Chart';
import FunnelSeriesModel, {FunnelDataItemOption} from './FunnelSeries';
import GlobalModel from '../../model/Global';
import ExtensionAPI from '../../core/ExtensionAPI';
import List from '../../data/List';
import { ColorString } from '../../util/types';
import { setLabelLineStyle, getLabelLineStatesModels } from '../../label/labelGuideHelper';
import { setLabelStyle, getLabelStatesModels } from '../../label/labelStyle';
import { saveOldStyle } from '../../animation/basicTrasition';
const opacityAccessPath = ['itemStyle', 'opacity'] as const;
/**
* Piece of pie including Sector, Label, LabelLine
*/
class FunnelPiece extends graphic.Polygon {
constructor(data: List, idx: number) {
super();
const polygon = this;
const labelLine = new graphic.Polyline();
const text = new graphic.Text();
polygon.setTextContent(text);
this.setTextGuideLine(labelLine);
this.updateData(data, idx, true);
}
updateData(data: List, idx: number, firstCreate?: boolean) {
const polygon = this;
const seriesModel = data.hostModel;
const itemModel = data.getItemModel<FunnelDataItemOption>(idx);
const layout = data.getItemLayout(idx);
const emphasisModel = itemModel.getModel('emphasis');
let opacity = itemModel.get(opacityAccessPath);
opacity = opacity == null ? 1 : opacity;
if (!firstCreate) {
saveOldStyle(polygon);
}
// Update common style
polygon.useStyle(data.getItemVisual(idx, 'style'));
polygon.style.lineJoin = 'round';
if (firstCreate) {
polygon.setShape({
points: layout.points
});
polygon.style.opacity = 0;
graphic.initProps(polygon, {
style: {
opacity: opacity
}
}, seriesModel, idx);
}
else {
graphic.updateProps(polygon, {
style: {
opacity: opacity
},
shape: {
points: layout.points
}
}, seriesModel, idx);
}
setStatesStylesFromModel(polygon, itemModel);
this._updateLabel(data, idx);
enableHoverEmphasis(this, emphasisModel.get('focus'), emphasisModel.get('blurScope'));
}
_updateLabel(data: List, idx: number) {
const polygon = this;
const labelLine = this.getTextGuideLine();
const labelText = polygon.getTextContent();
const seriesModel = data.hostModel;
const itemModel = data.getItemModel<FunnelDataItemOption>(idx);
const layout = data.getItemLayout(idx);
const labelLayout = layout.label;
const style = data.getItemVisual(idx, 'style');
const visualColor = style.fill as ColorString;
setLabelStyle(
// position will not be used in setLabelStyle
labelText,
getLabelStatesModels(itemModel),
{
labelFetcher: data.hostModel as FunnelSeriesModel,
labelDataIndex: idx,
defaultOpacity: style.opacity,
defaultText: data.getName(idx)
},
{ normal: {
align: labelLayout.textAlign,
verticalAlign: labelLayout.verticalAlign
} }
);
polygon.setTextConfig({
local: true,
inside: !!labelLayout.inside,
insideStroke: visualColor,
// insideFill: 'auto',
outsideFill: visualColor
});
const linePoints = labelLayout.linePoints;
labelLine.setShape({
points: linePoints
});
polygon.textGuideLineConfig = {
anchor: linePoints ? new graphic.Point(linePoints[0][0], linePoints[0][1]) : null
};
// Make sure update style on labelText after setLabelStyle.
// Because setLabelStyle will replace a new style on it.
graphic.updateProps(labelText, {
style: {
x: labelLayout.x,
y: labelLayout.y
}
}, seriesModel, idx);
labelText.attr({
rotation: labelLayout.rotation,
originX: labelLayout.x,
originY: labelLayout.y,
z2: 10
});
setLabelLineStyle(polygon, getLabelLineStatesModels(itemModel), {
// Default use item visual color
stroke: visualColor
});
}
}
class FunnelView extends ChartView {
static type = 'funnel' as const;
type = FunnelView.type;
private _data: List;
ignoreLabelLineUpdate = true;
render(seriesModel: FunnelSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) {
const data = seriesModel.getData();
const oldData = this._data;
const group = this.group;
data.diff(oldData)
.add(function (idx) {
const funnelPiece = new FunnelPiece(data, idx);
data.setItemGraphicEl(idx, funnelPiece);
group.add(funnelPiece);
})
.update(function (newIdx, oldIdx) {
const piece = oldData.getItemGraphicEl(oldIdx) as FunnelPiece;
piece.updateData(data, newIdx);
group.add(piece);
data.setItemGraphicEl(newIdx, piece);
})
.remove(function (idx) {
const piece = oldData.getItemGraphicEl(idx);
graphic.removeElementWithFadeOut(piece, seriesModel, idx);
})
.execute();
this._data = data;
}
remove() {
this.group.removeAll();
this._data = null;
}
dispose() {}
}
export default FunnelView;