in src/component/dataZoom/SliderZoomView.ts [349:467]
private _renderDataShadow() {
const info = this._dataShadowInfo = this._prepareDataShadowInfo();
this._displayables.dataShadowSegs = [];
if (!info) {
return;
}
const size = this._size;
const oldSize = this._shadowSize || [];
const seriesModel = info.series;
const data = seriesModel.getRawData();
const candlestickDim = seriesModel.getShadowDim && seriesModel.getShadowDim();
const otherDim: string = candlestickDim && data.getDimensionInfo(candlestickDim)
? seriesModel.getShadowDim() // @see candlestick
: info.otherDim;
if (otherDim == null) {
return;
}
let polygonPts = this._shadowPolygonPts;
let polylinePts = this._shadowPolylinePts;
// Not re-render if data doesn't change.
if (
data !== this._shadowData || otherDim !== this._shadowDim
|| size[0] !== oldSize[0] || size[1] !== oldSize[1]
) {
let otherDataExtent = data.getDataExtent(otherDim);
// Nice extent.
const otherOffset = (otherDataExtent[1] - otherDataExtent[0]) * 0.3;
otherDataExtent = [
otherDataExtent[0] - otherOffset,
otherDataExtent[1] + otherOffset
];
const otherShadowExtent = [0, size[1]];
const thisShadowExtent = [0, size[0]];
const areaPoints = [[size[0], 0], [0, 0]];
const linePoints: number[][] = [];
const step = thisShadowExtent[1] / (data.count() - 1);
let thisCoord = 0;
// Optimize for large data shadow
const stride = Math.round(data.count() / size[0]);
let lastIsEmpty: boolean;
data.each([otherDim], function (value: ParsedValue, index) {
if (stride > 0 && (index % stride)) {
thisCoord += step;
return;
}
// FIXME
// Should consider axis.min/axis.max when drawing dataShadow.
// FIXME
// 应该使用统一的空判断?还是在list里进行空判断?
const isEmpty = value == null || isNaN(value as number) || value === '';
// See #4235.
const otherCoord = isEmpty
? 0 : linearMap(value as number, otherDataExtent, otherShadowExtent, true);
// Attempt to draw data shadow precisely when there are empty value.
if (isEmpty && !lastIsEmpty && index) {
areaPoints.push([areaPoints[areaPoints.length - 1][0], 0]);
linePoints.push([linePoints[linePoints.length - 1][0], 0]);
}
else if (!isEmpty && lastIsEmpty) {
areaPoints.push([thisCoord, 0]);
linePoints.push([thisCoord, 0]);
}
areaPoints.push([thisCoord, otherCoord]);
linePoints.push([thisCoord, otherCoord]);
thisCoord += step;
lastIsEmpty = isEmpty;
});
polygonPts = this._shadowPolygonPts = areaPoints;
polylinePts = this._shadowPolylinePts = linePoints;
}
this._shadowData = data;
this._shadowDim = otherDim;
this._shadowSize = [size[0], size[1]];
const dataZoomModel = this.dataZoomModel;
function createDataShadowGroup(isSelectedArea?: boolean) {
const model = dataZoomModel.getModel(isSelectedArea ? 'selectedDataBackground' : 'dataBackground');
const group = new graphic.Group();
const polygon = new graphic.Polygon({
shape: {points: polygonPts},
segmentIgnoreThreshold: 1,
style: model.getModel('areaStyle').getAreaStyle(),
silent: true,
z2: -20
});
const polyline = new graphic.Polyline({
shape: {points: polylinePts},
segmentIgnoreThreshold: 1,
style: model.getModel('lineStyle').getLineStyle(),
silent: true,
z2: -19
});
group.add(polygon);
group.add(polyline);
return group;
}
// let dataBackgroundModel = dataZoomModel.getModel('dataBackground');
for (let i = 0; i < 3; i++) {
const group = createDataShadowGroup(i === 1);
this._displayables.sliderGroup.add(group);
this._displayables.dataShadowSegs.push(group);
}
}