@wayz/react-gl
Version:
React Component for DeckGL, Base on AMap, Mapbox GL
189 lines (188 loc) • 7.04 kB
JavaScript
import { CompositeLayer } from '@deck.gl/core';
import { TextLayer } from '@deck.gl/layers';
import TextMapWrapper from './textmap-wrapper';
const MAX_CACHED_ZOOM_LEVEL = 5;
const defaultProps = {
getWeight: { type: 'accessor', value: (x) => x.weight || 1 },
minFontSize: 14,
maxFontSize: 32,
weightThreshold: 1,
};
class TextmapLayer extends CompositeLayer {
initializeState() {
this.state = {
// Cached tags per zoom level
tagsCache: {},
tags: [],
};
}
shouldUpdateState({ changeFlags }) {
return changeFlags.somethingChanged;
}
updateState({ props, oldProps, changeFlags }) {
super.updateState({ props, oldProps, changeFlags });
let needsUpdate = changeFlags.viewportChanged;
if (changeFlags.dataChanged) {
this.updateTagMapData();
needsUpdate = true;
}
else if (props.minFontSize !== oldProps.minFontSize ||
props.maxFontSize !== oldProps.maxFontSize ||
props.weightThreshold !== oldProps.weightThreshold) {
this.setState({ tagsCache: {} });
needsUpdate = true;
}
if (needsUpdate) {
this.updateTagMapVis();
}
}
updateTagMapData() {
const { data, getText, getPosition, getWeight } = this.props;
const tagMap = new TextMapWrapper();
tagMap.setData(data, { getLabel: getText, getPosition, getWeight });
this.setState({ tagMap, tagsCache: {} });
}
updateTagMapVis() {
const { tagMap, tagsCache } = this.state;
if (!tagMap) {
return;
}
const { viewport } = this.context;
const discreteZoomLevel = Math.floor(viewport.zoom);
let tags = tagsCache[discreteZoomLevel];
if (tags) {
this.setState(tags);
return;
}
const { minFontSize, maxFontSize, weightThreshold } = this.props;
let bbox = null;
if (discreteZoomLevel > MAX_CACHED_ZOOM_LEVEL) {
const { unproject, width, height } = viewport;
const corners = [
unproject([0, 0]),
unproject([width, 0]),
unproject([0, height]),
unproject([width, height]),
];
bbox = {
minX: Math.min.apply(null, corners.map((p) => p[0])),
minY: Math.min.apply(null, corners.map((p) => p[1])),
maxX: Math.max.apply(null, corners.map((p) => p[0])),
maxY: Math.max.apply(null, corners.map((p) => p[1])),
};
}
tags = tagMap.getTags({
bbox,
minFontSize,
maxFontSize,
weightThreshold,
zoom: discreteZoomLevel,
});
const characterSet = new Set();
// 转化tags为输入的初始数据
const data = tags.map((tag) => {
this.setCharacterSet(tag.originValue, characterSet);
return Object.assign({}, tag.originValue, { position: tag.position });
});
if (discreteZoomLevel <= MAX_CACHED_ZOOM_LEVEL) {
tagsCache[discreteZoomLevel] = { tags, data, characterSet };
}
this.setState({ tags, data, characterSet });
}
// 设置characterSet
setCharacterSet(f, characterSet) {
let { getText } = this.props;
getText = getText ? getText : (f) => f.text;
getText(f)
.split('')
.forEach((s) => characterSet.add(s));
}
renderLayers() {
const { updateTriggers, characterSet } = this.props;
// const {
// sizeScale,
// sizeUnits,
// sizeMinPixels,
// sizeMaxPixels,
// billboard,
// // @ts-expect-error
// background,
// // @ts-expect-error
// backgroundPadding,
// fontFamily,
// characterSet,
// fontWeight,
// lineHeight,
// fontSettings,
// wordBreak,
// maxWidth,
// // @ts-expect-error
// outlineWidth,
// // @ts-expect-error
// outlineColor,
// } = this.props
const {
//Data Accessors
getText, getSize, getColor,
// getAngle,
//Text Alignment Options
// getTextAnchor,
// getAlignmentBaseline,
// getPixelOffset,
getBackgroundColor, getBorderColor, getBorderWidth, } = this.props;
const TextMapLayer = this.getSubLayerClass('textmap', TextLayer);
return [
new TextMapLayer(
// {
// sizeScale,
// sizeUnits,
// sizeMinPixels,
// sizeMaxPixels,
// billboard,
// background,
// backgroundPadding,
// fontFamily,
// fontWeight,
// lineHeight,
// fontSettings,
// wordBreak,
// maxWidth,
// outlineWidth,
// outlineColor,
// },
this.props, this.getSubLayerProps({
id: 'textmap',
updateTriggers: {
getText: updateTriggers.getText,
getPosition: updateTriggers.getPosition,
getSize: updateTriggers.getSize,
getColor: updateTriggers.getColor,
getAngle: updateTriggers.getAngle,
getTextAnchor: updateTriggers.getTextAnchor,
getAlignmentBaseline: updateTriggers.getAlignmentBaseline,
getPixelOffset: updateTriggers.getPixelOffset,
getBackgroundColor: updateTriggers.getBackgroundColor,
getBorderColor: updateTriggers.getBorderColor,
getBorderWidth: updateTriggers.getBorderWidth,
},
}), {
data: this.state.data,
characterSet: characterSet ? characterSet : this.state.characterSet,
getPosition: (x) => x.position,
getText: this.getSubLayerAccessor(getText),
getSize: this.getSubLayerAccessor(getSize),
getColor: this.getSubLayerAccessor(getColor),
// getAngle: this.getSubLayerAccessor(getAngle),
// getTextAnchor: this.getSubLayerAccessor(getTextAnchor),
// getAlignmentBaseline: this.getSubLayerAccessor(getAlignmentBaseline),
// getPixelOffset: this.getSubLayerAccessor(getPixelOffset),
getBackgroundColor: this.getSubLayerAccessor(getBackgroundColor),
getBorderColor: this.getSubLayerAccessor(getBorderColor),
getBorderWidth: this.getSubLayerAccessor(getBorderWidth),
}),
];
}
}
TextmapLayer.layerName = 'TextmapLayer';
TextmapLayer.defaultProps = defaultProps;
export default TextmapLayer;