在React中使用(内含实战)
React是一个优秀的前端开发框架,即使您只是开发一些简单的个人页面,也非常推荐您使用React进行开发,在QuickEarth项目中启用TypeScript与普通项目无异,如果您还没有使用经验,您可以先学习React相关知识:
https://zh-hans.reactjs.org/docs/getting-started.html
本教程最终效果
使用环境
本章节假定使用的是TypeScript进行开发,JS可按照逻辑进行类比。
在React项目中初始化地图
QE地图的初始化有多种方式,可以直接将Dom放在index中,然后在合适的地方初始化,也可以使用组件的方式进行初始化,下面分别进行介绍。
不借助React组件进行初始化
由于QE地图只需要一个基础容器组件即可初始化,我们将承载地图的容器放到index.html中。这种方式适合比较简单的单页地图,不需要进行复杂路由,React组件负责渲染地图之外的其他地方,而地图使用原始的方式进行初始化,好处是方便快速,清晰简单,缺点是不适合复杂应用。
QuickEarth云平台中大多数项目使用这种方式进行初始化。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="theme-color" content="#000000">
<meta charset="utf-8" />
<meta HTTP-EQUIV="Pragma" CONTENT="no-cache">
<meta HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
<meta HTTP-EQUIV="Expires" CONTENT="0">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>QuickEarth-Preview</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<!--for 2d -->
<link rel="stylesheet" type="text/css" href="public/lib/node_modules/leaflet/dist/leaflet.css" />
<link rel="stylesheet" type="text/css" href="public/lib/node_modules/antd/dist/antd.min.css" />
<link rel="stylesheet" href="public/config/styles/fonts/fonts.css" />
<!--your custom libs-->
<!--systemjs-->
<!--项目内容开始-->
<div id="map" style="position:absolute;left:0px;right:0px;bottom:0px;top:0px;"></div>
<div id="plugins"></div>
</body>
</html>
import L from "leaflet"
import { init, LMap,createTileLayer, predefinedImageTiles,consts } from "quickearth";
init("f17d186a2e692c9f6f2e79e48b270012");
const map = new LMap("map", { crs: L.CRS.EPSG3857, fadeAnimation: false, zoomControl: false }).setView([35, 110], 3);
const tileLayer = createTileLayer(predefinedImageTiles.windy, { pane: consts.customPanes.topmap.name });
map.addLayer(tileLayer);
在初始化完地图之后可以继续初始化React组件,也可以选择在React组件
const App: React.FC = () => {
return (
<div style={{
position: "fixed",
top: "0px",
width: "100px",
height: "20px",
right: "0px",
backgroundColor:"rebeccapurple",
zIndex: "999999"
}}>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
效果如下
使用React Class Component创建地图
当开发较为复杂的应用时,地图可能需要随着组件的生命周期进行创建和删除,这时候就需要对地图的生命周期进行管理。
我们对上面一个示例进行改造,在同一个应用中显示组件式方式创建的地图。
我们在此同时考虑下一小节使用函数式组件也需要创建地图,所以我们把页面分为上中下三个部分,index.html改造如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="theme-color" content="#000000">
<meta charset="utf-8" />
<meta HTTP-EQUIV="Pragma" CONTENT="no-cache">
<meta HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
<meta HTTP-EQUIV="Expires" CONTENT="0">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>QuickEarth-Preview</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<!--for 2d -->
<link rel="stylesheet" type="text/css" href="public/lib/node_modules/leaflet/dist/leaflet.css" />
<link rel="stylesheet" type="text/css" href="public/lib/node_modules/antd/dist/antd.min.css" />
<link rel="stylesheet" href="public/config/styles/fonts/fonts.css" />
<!--your custom libs-->
<!--项目内容开始-->
<div id="root_fc" style="position:absolute;left:0px;right:0px;height:33%;top:33%;"></div>
<div id="root_class" style="position:absolute;left:0px;right:0px;height:34%;top:66%;"></div>
<div id="map" style="position:absolute;left:0px;right:0px;top:0px;height:33%;"></div>
<div id="plugins"></div>
</body>
</html>
同时加入一个React地图组件:
class ClassicApp extends React.Component {
private map: LMap;
public render() {
return (
<div id="map3" style={{"position":"absolute","left":"0px","right":"0px","top":"0px","bottom":"0px"}}></div>
);
}
public componentDidMount() {
const map = this.map = new LMap("map3", { crs: L.CRS.EPSG3857, fadeAnimation: false, zoomControl: false }).setView([35, 110], 3);
const tileLayer = createTileLayer(predefinedImageTiles.tdtTerrain, { pane: consts.customPanes.topmap.name });
map.addLayer(tileLayer);
}
public componentWillUnmount() {
this.map.remove();
}
}
然后将上一节中的直接创建地图改造为一个创建函数:
function createRawMap() {
const map = new LMap("map", { crs: L.CRS.EPSG3857, fadeAnimation: false, zoomControl: false }).setView([35, 110], 3);
const tileLayer = createTileLayer(predefinedImageTiles.tdtNormal, { pane: consts.customPanes.topmap.name });
map.addLayer(tileLayer);
}
最后,启动组件渲染:
//这个方法只需要全局调用一次,放到外部
init("f17d186a2e692c9f6f2e79e48b270012");
resourceService.loadResourceFromConfigPath("demos/styles/demo.config.json").then(res => {
createRawMap();
ReactDOM.render(<ClassicApp />, document.getElementById("root_class"));
});
在函数式组件中创建地图
函数式组件的生命周期由useEffect函数控制,因此只要在该函数中实现地图的创建和卸载即可,组件代码如下,这个示例我们使用三维地图:
const App: React.FC = () => {
useEffect(() => {
Ion.defaultAccessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5NjE0YzZiNS0wNjJiLTQ5NjEtYmMyZC01YWYzZjk1NmYzMzYiLCJpZCI6OTgxOCwic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTU1NDk5MTkxNn0.RMgKv7MDKkXaV0df21IBBqikp2abPoUYeAPB42fHJes";
const viewer = new CView("map2", {
defaultTiles: [predefinedImageTiles.tdtSatellite, predefinedImageTiles.tdtSatelliteAnnotation],
showGroundAtmosphere: false,
scene3DOnly: true
});
return () => { viewer.container.remove(); viewer.destroy(); }
}, []);
return (
<div id="map2" style={{ "position": "absolute", "left": "0px", "right": "0px", "top": "0px", "bottom": "0px" }}></div>
);
};
接着在启动函数中进行组件渲染:
//这个方法只需要全局调用一次,放到外部
init("f17d186a2e692c9f6f2e79e48b270012");
resourceService.loadResourceFromConfigPath("demos/styles/demo.config.json").then(res => {
createRawMap();
ReactDOM.render(<App />, document.getElementById("root_fc"));
ReactDOM.render(<ClassicApp />, document.getElementById("root_class"));
});
看起来是QE
到此为止,看起来我们是在做React中使用Leaflet的教程,让我们添加一些气象数据吧!
let provider: IFeaturesProvider;
async function createStationLayer(ctor) {
if (!provider) {
provider = new CimissStationFeatureProvider(await getJSON("public/demos/data/autostation011.json"));
}
const layer = new ctor()
.setDataSource(provider)
.setDrawOptions({
point: {
size: 3,
color: "color-temp#res?field=TEM",
}
});
return layer;
}
No Comments