wafer-map
v7.0.27
Published
English | [简体中文](./README.zh-CN.md)
Readme
English | 简体中文
wafer-map
SVG Map for React. It supports element (station / meeting room, etc.) state coloring, single / multiple selection, rubber-band selection, search marking, cross-floor path guidance, area jumping and legend exporting.
Table of Contents
- Using
- Features
- Props
- Methods (via ref)
- onClickError Error Code
- Examples
- tooltipContent example of use
- Publish
Using
- install
npm i wafer-map
yarn add wafer-map
- using in react
import React, { Component } from 'react';
import WaferMap from 'wafer-map';
class App extends Component {
render() {
const mapProps = {
mapId: '1',
componentWidth: 1920,
componentHeight: 1080
};
return (
<div className="App">
<WaferMap {...mapProps}/>
</div>
);
}
}notice: mapId is the only mark on the map.
Calling component methods with ref:
import React, { useRef } from 'react';
import WaferMap from 'wafer-map';
function App() {
const mapRef = useRef(null);
const handleClear = () => {
// clear selected elements
mapRef.current.clearSelectElement();
// read the internal state
console.log(mapRef.current.state.selectedEle);
};
return (
<div style={{ width: 1920, height: 1080 }}>
<WaferMap
ref={mapRef}
mapId="1"
componentWidth={1920}
componentHeight={1080}
onClick={(element, selected) => console.log('single select', element, selected)}
onClickError={(code, element) => console.warn('not clickable', code, element)}
/>
<button onClick={handleClear}>Clear</button>
</div>
);
}Features
| Feature | Description | Props |
|---------|-------------|-------|
| Base map | Renders an SVG base map or an image URL base map returned by the API, or a fully external base map | mapId, customBaseMap, mapKey |
| Element rendering | Renders map elements (station / meeting room, etc.) with material SVG, supports rotation, state coloring and area binding | mapElementsList, elementsColor, showStateIds |
| Element text | Multi-line text, ellipsis when overflowing, i18n, gender avatars, tooltip instead of text | noName, textColor, textShadow, isGenders, hideNameType, isTextToolTip |
| Visibility / clickability | Controls visibility and clickability separately by element id, element type and element state | visibleElement, visibleType, visibleState, clickableElement, clickableType, clickableState |
| Single / multiple selection | Single select replaces the current one; multiple select accumulates and renders a numbered icon | multiple, onClick, onSelect |
| Rubber-band selection | Drag a rectangle to select elements in batch, with element type filtering | selectMode, selectableType, setSelectMode |
| Selection echo | Echoes the selection from outside through selectedEle or selectedIds | selectedEle, selectedIds, setSelectedEleFinish |
| Search mark | Highlights the target element by markId, accepts a single id or an id array | markId, markSvg, markStateId, markStateSvg |
| Path guide | Same-floor / cross-floor path drawing, flowing dash animation, start & end icons, path layer on top | showPath, pathStyle, pathAnimType, pathEdges, guideFirstSvg, etc. |
| Area jumping | Emits the target area mapId when clicking an area-bound element to switch maps | mapSpaceJump, reSetMapId |
| Zoom / pan | Wheel, gesture and touch zoom & pan, with scale factor and pan boundary limits | mapZoom, mapMove, scaleFactorMax, panBoundary |
| Center & zoom element | Centers and zooms an element after clicking | clickToCenter, centerElement, centerEleRate |
| Tooltip | Displays a custom SVG tooltip when hovering an element | tooltipContent, defaultTooltipKey |
| Custom render | Custom rendering before / after element text, extra svg, legend | elementRenderHandle, elementRenderTextAfterHandle, AppendSvg, legendRender |
| Multiple maps | Supports rendering two maps at the same time | isDoubleMap |
Props
Basic
| Prop | default value | is required | description |
|------|---------------|-------------|-------------|
| mapId | | true | map id, the only mark on the map |
| componentWidth | 1920 | false | Map container width |
| componentHeight | 1080 | false | Map container height |
| background | #ddd | false | Map container background color |
| SVGBackground | #fff | false | SVG background color |
| SVGStyle | {} | false | SVG element style |
| style | {} | false | Outer container style |
| mapExtraProps | | false | Extra props, currently used to add extra width / height to leave blank margins, e.g. { width: 100, height: 100 } |
| defaultPath | vsk/ | false | API path prefix |
| requestPrefix | '' | false | Request URL prefix |
| signatureKey | null | false | Signature key |
| restfulSignature | false | false | Controls whether to sign or not, when set to true the signature key must be valid |
| lang | cn | false | Language, cn Chinese, en English, tw Traditional Chinese |
| customBaseMap | null | false | External base map data, the base map API will not be requested when provided |
| reloadMap | false | false | Reload the map |
| reloadFinish | () => {} | false | Callback when reloading the map is finished |
Zoom & Pan
| Prop | default value | is required | description |
|------|---------------|-------------|-------------|
| mapZoom | true | false | Whether the map can be zoomed |
| mapMove | true | false | Whether the map can be moved |
| touchable | true | false | Touch control |
| isTouchDevice | false | false | Whether it is an all-in-one device |
| windowsTouchSupport | false | false | Whether Windows touch screen is supported |
| scaleFactorMax | undefined | false | Maximum amount of scale a user can zoom in to, e.g. 5 |
| scaleFactorMin | undefined | false | Minimum amount of scale a user can zoom out of, e.g. 0.5 |
| zoomRate | 1 | false | Map fit magnification |
| panBoundary | false | false | Pan boundary limit.false no limit; undefined keeps the original limit (bufferX = centerX / 2); 'auto' calculates automatically, keeping 1/10 outside the viewport; a number uses centerX / panBoundary as the boundary buffer |
| fitWidthOrHeight | '' | false | Fit by height or width (not effective in the current version) |
Element Visibility & Clickability
| Prop | default value | is required | description |
|------|---------------|-------------|-------------|
| visibleElement | undefined | false | Displayable collection of element ids, no restriction when empty or not passed |
| visibleType | undefined | false | Displayable collection of element types, no restriction when empty or not passed |
| visibleState | undefined | false | Displayable collection of element states, no restriction when empty or not passed |
| clickableElement | undefined | false | Clickable collection of element ids, no restriction when empty or not passed |
| clickableType | undefined | false | Clickable collection of element types, no restriction when empty or not passed |
| clickableState | undefined | false | Clickable collection of element states, no restriction when empty or not passed |
| isNotAllowedEle | false | false | Shows a not-allowed cursor for elements that cannot be clicked |
| noName | false | false | Element names are not displayed on the map |
| hideNameType | [] | false | Material types whose content is hidden |
| elementsColor | [] | false | Set color according to element id, data structure: [{ id: 1, color: '#fff' }, {}] |
| showStateIds | [] | false | Display different states of different elements, data structure: [{ id: 1, state: 'XX', color: '#fff', text: '' }, {}] |
| isShowSvgDefaultColor | false | false | Whether to display the default color of elements without material |
| textColor | '' | false | Element text color |
| textShadow | false | false | Whether the element text has a shadow, slight performance cost when there are many elements |
| isGenders | false | false | Display male and female outsourcing type avatars before the name of the material |
| isShowArea | false | false | Whether to display the map area (depends on areaAge returned by the API) |
Selection
| Prop | default value | is required | description |
|------|---------------|-------------|-------------|
| multiple | false | false | Multiple switch |
| selectMode | false | false | Whether rubber-band selection is enabled |
| setSelectMode | () => {} | false | Reset the rubber-band selection state |
| selectableType | '' | false | Batch operation type, used to restrict multi-select to the same element type |
| selectedEle | [] | false | Selected element collection, used to echo the selection from outside |
| setSelectedEleFinish | () => {} | false | Callback after echoing the selected elements, the parent should clear the echoed collection afterwards |
| selectedIds | [] | false | Selected element id collection, used to echo the selection from outside |
| deleteId | '' | false | Delete the selected element id |
| deleteFinish | () => {} | false | Callback after deleting the selected element |
| onClick | () => {} | false | Single select callback, arguments (element, selected) |
| onSelect | () => {} | false | Multi-select callback, returns all selected objects every time |
| onClickError | () => {} | false | Callback for a failed selection, arguments (code, element) |
| fixedSelectedIcon | false | false | Whether the selected icon keeps a fixed size and does not scale with the base map, false follows the base map |
Marks & Icons
| Prop | default value | is required | description |
|------|---------------|-------------|-------------|
| markId | '' | false | The element id that needs to be tagged, such as '1'; if multiple, use string array format, such as ['1', '2'] |
| markSvg | undefined | false | Search anchor or mark icon, this icon contains only elements inside svg, without svg tags |
| selectedSvg | undefined | false | Selected icon, this icon contains only elements inside svg, without svg tags |
| markStateId | [] | false | Tagged element state id collection |
| markStateSvg | undefined | false | Tagged element state svg icon function |
| pathStartSvg | undefined | false | Guide start icon, this icon contains only elements inside svg, without svg tags |
| pathEndSvg | undefined | false | Guide end icon, this icon contains only elements inside svg, without svg tags |
Note: when
markIdand the selected state hit the same element,markSvgis used in single select mode andselectedSvgis used in multiple select mode.
Note: the location icon scale (
iconScale) and the multiple-select index color (iconOrderColor) are read from the base map API response, at the same level asicon/iconUrl, and are not passed as props.
Path Guide & Navigation
| Prop | default value | is required | description |
|------|---------------|-------------|-------------|
| showPath | false | false | Display the guide path |
| pathStyle | {} | false | Guide path style, style setting reference svg element attributes |
| pathExStyle | {} | false | Style of the second guide path on the same floor |
| pathAnimType | undefined | false | Guide path animation type: 1 straight line, 2 flowing dash, 3 dash + flowing arrow, 4 straight line + flowing arrow. Takes precedence over colors.guidesStyle returned by the API |
| pathEdges | null | false | Path point collection, each item is { x1, y1, x2, y2 }. When provided, the path is drawn from these points and overrides the path returned by the API |
| pathLineKey | { start: 'lineStart', end: 'lineEnd', mid: 'lineMid' } | false | Field mapping of the guide path |
| pathLevelUp | false | false | Whether the navigation layer is on top |
| isStartGuide | false | false | Whether to start navigation |
| refreshGuide | -1 | false | Whether to refresh the navigation |
| guideFirstSvg | undefined | false | First navigation segment svg icon function, current floor |
| guideSecondSvg | undefined | false | Second navigation segment svg icon function, displayed on the lower map by design. Should check going up or down and modify the path start / end points |
| guideThirdSvg | undefined | false | Third navigation segment svg icon function, target floor |
| guideFirstSvgEx | undefined | false | The second navigation of the current floor |
| handleGetPathInfo | () => {} | false | Path callback method |
| appGetPathByUrl | false | false | Whether the mobile side gets the path info from the API |
| mapSpaceJump | false | false | Whether the area jumping switch is enabled |
| reSetMapId | () => {} | false | Callback of the target area mapId of an area-bound element |
| isDoubleMap | false | false | Whether it is a double map |
Data Source
| Prop | default value | is required | description |
|------|---------------|-------------|-------------|
| mapDataSource | false | false | Element source, false means fetched inside the component, true means passed from outside |
| mapElementsList | [] | false | Map element collection. It cannot be empty when mapDataSource is true |
| mapKey | { url: 'baseMapUrl' } | false | Field mapping of the map |
| onElementsLoad | () => {} | false | Callback when the material loading is finished |
Custom Render & Legend
| Prop | default value | is required | description |
|------|---------------|-------------|-------------|
| tooltipContent | () => {} | false | Content and style of the tooltip when hovering an element |
| defaultTooltipKey | '' | false | You can customize the default key in the bubble, such as orgName |
| isTextToolTip | false | false | Whether the element text is displayed with a tooltip |
| textToolTipList | [] | false | List of the element text tooltip |
| textToolTipRender | undefined | false | Render method of the whole element text tooltip |
| elementRenderHandle | undefined | false | Custom handling when rendering an element (before the text) |
| elementRenderTextAfterHandle | undefined | false | Custom handling when rendering an element (after the text) |
| AppendSvg | undefined | false | Extra svg to append, mainly used to display map areas |
| centerElement | {} | false | Set the central material |
| centerEleRate | 1 | false | Set the center material magnification |
| clickToCenter | false | false | If set true, clicking an element will center it and zoom in |
| legendList | [] | false | Legend added when exporting PDF, data structure [{ color, text }] |
| legendRender | undefined | false | Legend render function |
| getSvgDom | () => {} | false | Callback to get the viewerDOM of the SVG |
Methods (via ref)
Get the component instance through ref and then call the following methods or read the internal state:
| Method / Property | props | return | description |
|------|-------|--------|-------------|
| fitToViewerReSet | | | Fit the map zoom and position to the current container again |
| clearSelectElement | | | Clears the selected set of elements |
| state | | object | Internal state object of the component, see the table below |
Fields of the state object:
| Field | description | |-------|-------------| | mapElementState | Element collection on the map | | baseMap | Base map info (width, height, base map content, area, etc.) | | selectedEle | Currently selected elements | | showTip / tipObj | Tooltip visibility and tooltip data | | path / start / end | Path, start point and end point of the first guide line | | path2 / start2 / end2 | Path, start point and end point of the second guide line | | mapId | Current map id | | rateZoom | Current zoom rate | | locationSvgMark | Mark icon data | | mapColorSet | Map color config | | allElements | All element materials | | selectedCenter | Start point of the rubber-band selection | | selectedArea | Range of the rubber-band selection | | tool | Current tool type | | svgValue | Map view state | | zoom | Current zoom value |
onClickError Error Code
| code | description |
|------|-------------|
| 100 | Selected elements that cannot be displayed |
| 101 | Selected elements that the ID cannot be selected |
| 102 | Selected elements that the types cannot be selected |
| 103 | Selected elements that the states cannot be selected |
| 104 | Multi-select mode cannot select different types at the same time |
| 105 | Multi-select mode without a valid batch operation type (selectableType) |
Examples
1. Multiple selection + rubber-band selection
<WaferMap
mapId="1"
componentWidth={1920}
componentHeight={1080}
multiple
selectMode={selectMode}
selectableType="station"
setSelectMode={setSelectMode}
onSelect={(list) => console.log('selected', list)}
/>2. Search mark
<WaferMap
mapId="1"
markId={['1', '2']}
markSvg={() => (
<circle cx="0" cy="0" r="8" fill="#FFC13D" />
)}
/>3. Guide path
<WaferMap
mapId="1"
showPath
pathAnimType={3}
pathStyle={{ stroke: '#00ba00', strokeWidth: 3 }}
pathStartSvg={() => <circle r="6" fill="#00ba00" />}
pathEndSvg={() => <circle r="6" fill="#ff0000" />}
/>4. External element data
<WaferMap
mapId="1"
mapDataSource
mapElementsList={elements}
visibleElement={visibleList}
onElementsLoad={(list) => console.log('elements loaded', list)}
/>tooltipContent example of use
tipObj is the object returned by this method. When tooltipContent is null, the tooltip shows the defaultTooltipKey value; if defaultTooltipKey is empty or missing, the tooltip is not displayed.
tooltipContent = (tooltipObj)=>{
const radius = 5;
const width = 150;
const height = 45;
return (
<g>
<path
fill="black"
fillOpacity="0.7"
d={`M0 0 l10 10 h ${width / 2 - 10 - radius}
a ${radius} ${radius} 90 0 1 ${radius} ${radius} v ${height}
a ${radius} ${radius} 90 0 1 ${-radius} ${radius} h ${2 * radius - width}
a ${radius} ${radius} 90 0 1 ${-radius} ${-radius} v ${-height}
a ${radius} ${radius} 90 0 1 ${radius} ${-radius} h ${width / 2 - 10 - radius} Z`}
/>
<text
dy="23"
dominantBaseline="text-before-edge"
fill="white"
textAnchor="middle"
>
{tooltipObj.orgName}
</text>
</g>
)
}The tipObj object needs to get data from the getMapStationList method and store it into the contentObj object to get the complete object:
*getMapStationList({ payload }, { call, put, select }) {
const { locationId } = yield select(state => state.swsCommon);
const param = payload || { locationId };
const { info } = yield select(state => state.login);
if (info && info.tenant_id) {
param.domainId = info.tenant_id;
}
const result = yield call(service.getMapStationList, { payload: param });
if (result && result.code === 0) {
const onMapList = [];
const visibleList = [];
result.data.forEach(item => {
if (item && item.elementId) {
visibleList.push(item.elementId);
onMapList.push({
id: item.elementId,
state: item.statusCode,
color: item.statusColor,
text: item.userNames || item.stationNum,
contentObj: item
});
}
});
yield put({
type: 'saveOrUpdateData',
payload: {
mapStationList: result.data,
stationsOnMap: onMapList,
visibleList,
},
});
}
} Publish
yarn build
yarn publish