426 lines
18 KiB
HTML
426 lines
18 KiB
HTML
|
|
<!DOCTYPE html>
|
|||
|
|
<html lang="en">
|
|||
|
|
<head>
|
|||
|
|
<!-- Use correct character set. -->
|
|||
|
|
<meta charset="utf-8" />
|
|||
|
|
<!-- Tell IE to use the latest, best version. -->
|
|||
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|||
|
|
<!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
|
|||
|
|
<meta
|
|||
|
|
name="viewport"
|
|||
|
|
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
|
|||
|
|
/>
|
|||
|
|
<title>Learning Cesium!</title>
|
|||
|
|
<script src="./Build/Cesium/Cesium.js"></script>
|
|||
|
|
<style>
|
|||
|
|
@import url(./Build/Cesium/Widgets/widgets.css);
|
|||
|
|
html,
|
|||
|
|
body,
|
|||
|
|
#app,
|
|||
|
|
#cesiumContainer {
|
|||
|
|
width: 100%;
|
|||
|
|
height: 100%;
|
|||
|
|
margin: 0;
|
|||
|
|
padding: 0;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
.fly-path-box{
|
|||
|
|
position: absolute;
|
|||
|
|
top: 100px;
|
|||
|
|
left: 80px;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
<!-- 引入样式 -->
|
|||
|
|
<link rel="stylesheet" href="./js/elementui/index.css" />
|
|||
|
|
<!-- import Vue before Element -->
|
|||
|
|
<script src="./js/vue2710.js"></script>
|
|||
|
|
<!-- import JavaScript -->
|
|||
|
|
<script src="./js/elementui/index.js"></script>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div id="app">
|
|||
|
|
<div id="cesiumContainer"></div>
|
|||
|
|
<div class="fly-path-box">
|
|||
|
|
<el-row>
|
|||
|
|
<el-button @click="flyPath">开始</el-button>
|
|||
|
|
<el-button @click="pauseFly" type="primary">暂停</el-button>
|
|||
|
|
<!-- <el-button type="success">成功按钮</el-button>
|
|||
|
|
<el-button type="info">信息按钮</el-button>
|
|||
|
|
<el-button type="warning">警告按钮</el-button>
|
|||
|
|
<el-button type="danger">危险按钮</el-button> -->
|
|||
|
|
</el-row>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<script type="module">
|
|||
|
|
import viewUtil from "./js/utils/viewUtil.js";
|
|||
|
|
import {getRiverLevel1,getRiverLevel2,getHanjiangFeature} from "/js/api/hubei.js"
|
|||
|
|
import {
|
|||
|
|
cesiumToken,
|
|||
|
|
geoserverConfig,
|
|||
|
|
geoqConfig,
|
|||
|
|
} from "./js/mapConfig.js";
|
|||
|
|
Cesium.Ion.defaultAccessToken = cesiumToken;
|
|||
|
|
let flyHeight = 13177;
|
|||
|
|
new Vue({
|
|||
|
|
el: "#app",
|
|||
|
|
data: {
|
|||
|
|
regions:[
|
|||
|
|
{ name:"长江干流流域",level:"一级流域",coord:[114.721069,30.855776]},
|
|||
|
|
{ name:"汉江流域",level:"一级流域",coord:[111.319383,32.038113]},
|
|||
|
|
{ name:"清江流域",level:"一级流域",coord:[109.483509,30.107393]},
|
|||
|
|
|
|||
|
|
{ name:"乌江片区",level:"二级流域",coord:[108.870317,29.909681]},
|
|||
|
|
{ name:"清江片区",level:"二级流域",coord:[110.050511,29.912557]},
|
|||
|
|
{ name:"沅江片区",level:"二级流域",coord:[110.210396,30.451736]},
|
|||
|
|
|
|||
|
|
{ name:"三峡库区",level:"二级流域",coord:[110.548268,31.133949]},
|
|||
|
|
{ name:"黄柏河片区",level:"二级流域",coord:[111.337632,30.918915]},
|
|||
|
|
{ name:"荆南四河片区",level:"二级流域",coord:[111.927106,30.038710]},
|
|||
|
|
|
|||
|
|
{ name:"沮漳河片区",level:"二级流域",coord:[111.835033,31.079421]},
|
|||
|
|
|
|||
|
|
{ name:"四湖片区",level:"二级流域",coord:[112.833908,30.004803]},
|
|||
|
|
{ name:"鄂东南片区",level:"二级流域",coord:[114.246797,29.964106]},
|
|||
|
|
{ name:"富水片区",level:"二级流域",coord:[114.794233,29.674242]},
|
|||
|
|
{ name:"鄂东五河片区",level:"二级流域",coord:[115.316260,30.830389]},
|
|||
|
|
|
|||
|
|
{ name:"府澴河片区",level:"二级流域",coord:[113.740907,31.576125]},
|
|||
|
|
{ name:"汉江下游片区",level:"二级流域",coord:[113.321659,30.668325]},
|
|||
|
|
{ name:"唐白河片区",level:"二级流域",coord:[112.329638,32.207771]},
|
|||
|
|
{ name:"汉江中游片区",level:"二级流域",coord:[111.721511,31.839883]},
|
|||
|
|
{ name:"汉江丹库以上片区",level:"二级流域",coord:[110.071016,32.370220]},
|
|||
|
|
],
|
|||
|
|
level1Color:"rgba(65, 110, 255, 0.5)",
|
|||
|
|
level2Color:"rgba(44, 239, 243, 0.5)",
|
|||
|
|
path:[
|
|||
|
|
[106.506124,33.116968,flyHeight],//发源地
|
|||
|
|
[109.852000,33.070824,flyHeight],
|
|||
|
|
[110.615992,32.828365,flyHeight],
|
|||
|
|
[111.069476,32.622887,flyHeight],//中游
|
|||
|
|
[111.710542,32.231320,flyHeight],
|
|||
|
|
[112.143726,31.848392,flyHeight],
|
|||
|
|
[112.447286,31.399614,flyHeight],
|
|||
|
|
[112.565470,31.005892,flyHeight],
|
|||
|
|
[112.825239,30.784890,flyHeight],
|
|||
|
|
[113.651361,30.865274,flyHeight],
|
|||
|
|
[114.282617,30.568286,flyHeight],// 入江口
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
computed:{
|
|||
|
|
regionLevel1: function () {
|
|||
|
|
return this.regions.filter(region=>region.level == "一级流域")
|
|||
|
|
},
|
|||
|
|
regionLevel2: function () {
|
|||
|
|
return this.regions.filter(region=>region.level == "二级流域")
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
methods: {
|
|||
|
|
initViewer() {
|
|||
|
|
var viewer = new Cesium.Viewer("cesiumContainer", {
|
|||
|
|
geocoder: false, //位置查找
|
|||
|
|
homeButton: false, //视图返回初始位置
|
|||
|
|
sceneModePicker: false, //视角选择器
|
|||
|
|
baseLayerPicker:false,//底图选择器
|
|||
|
|
navigationHelpButton: false, //导航帮助按钮
|
|||
|
|
animation: false, //动画控制器
|
|||
|
|
creditContainer:document.createElement("div"),//版权显示
|
|||
|
|
timeline: true, //时间线
|
|||
|
|
fullscreenButton: false, //全屏控件
|
|||
|
|
vrButton: false,
|
|||
|
|
infoBox: false,
|
|||
|
|
selectionIndicator: false,
|
|||
|
|
terrainProvider: Cesium.createWorldTerrain({
|
|||
|
|
requestVertexNormal: true, //添加地形光照
|
|||
|
|
requestWaterMask: true, //添加水面波浪效果
|
|||
|
|
}),
|
|||
|
|
});
|
|||
|
|
window.viewer = viewer;
|
|||
|
|
this._viewer = viewer;
|
|||
|
|
let imageryLayers = viewer.imageryLayers;
|
|||
|
|
imageryLayers.removeAll();
|
|||
|
|
viewUtil.addGeoVisImagerLayer(viewer,"yingxiang");
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 将三维球定位到汉江
|
|||
|
|
viewer.camera.flyTo({
|
|||
|
|
destination: new Cesium.Cartesian3(
|
|||
|
|
-2568409.0296040955, 6087054.075714171, 3869940.8638977357
|
|||
|
|
),
|
|||
|
|
orientation: {
|
|||
|
|
heading: 0.1017466880023612,
|
|||
|
|
pitch: -1.5281789831506378,
|
|||
|
|
roll: 0,
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
this.initEvent(viewer);
|
|||
|
|
|
|||
|
|
// 创建自定义数据源
|
|||
|
|
this.level1DataSource = new Cesium.CustomDataSource("level1");
|
|||
|
|
viewer.dataSources.add(this.level1DataSource);
|
|||
|
|
|
|||
|
|
// 创建自定义数据源
|
|||
|
|
this.level2DataSource = new Cesium.CustomDataSource("level2");
|
|||
|
|
viewer.dataSources.add(this.level2DataSource);
|
|||
|
|
|
|||
|
|
// 用于存储汉江图元的集合
|
|||
|
|
this.riverPrimitives = viewer.scene.primitives.add(new Cesium.PrimitiveCollection());
|
|||
|
|
|
|||
|
|
this.drawShap();
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 创建轨迹实体数据源
|
|||
|
|
window.pathSource = new Cesium.CustomDataSource("pathSource");
|
|||
|
|
viewer.dataSources.add(window.pathSource);
|
|||
|
|
},
|
|||
|
|
async drawShap(){
|
|||
|
|
// 添加一级、二级流域面和注记
|
|||
|
|
let level1 = await getRiverLevel1();
|
|||
|
|
level1.features.forEach(feature=>{
|
|||
|
|
feature.properties.layerName = "riverLevel";
|
|||
|
|
feature.properties.selectedColor = this.level1Color;
|
|||
|
|
viewUtil.createOutlinePolygon(this.level1DataSource,feature,"rgba(255,255,255,0)","rgba(255,255,255)",2,true)
|
|||
|
|
})
|
|||
|
|
let level2 = await getRiverLevel2();
|
|||
|
|
level2.features.forEach(feature=>{
|
|||
|
|
feature.properties.layerName = "riverLevel";
|
|||
|
|
feature.properties.selectedColor = this.level2Color;
|
|||
|
|
viewUtil.createOutlinePolygon(this.level2DataSource,feature,"rgba(255,255,255,0)","#2CEFF3",2,true)
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
this.addPoiData(this.level1DataSource,this.regionLevel1);
|
|||
|
|
this.addPoiData(this.level2DataSource,this.regionLevel2);
|
|||
|
|
this.level2DataSource.show = false;//默认显示一级
|
|||
|
|
|
|||
|
|
// 添加汉江水面动态效果
|
|||
|
|
let hanjiang = await getHanjiangFeature();
|
|||
|
|
hanjiang.features.forEach(feature=>{
|
|||
|
|
viewUtil.addWaterFeature(this.riverPrimitives,feature)
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
initEvent(viewer){
|
|||
|
|
let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
|
|||
|
|
handler.setInputAction((evt) => {
|
|||
|
|
//捕获椭球体,将笛卡尔二维平面坐标转为椭球体的笛卡尔三维坐标,返回球体表面的点
|
|||
|
|
var cartesian3 = viewer.camera.pickEllipsoid(evt.position);
|
|||
|
|
// let cartesian3 = viewer.scene.pickPosition(evt.position);
|
|||
|
|
if (cartesian3) {
|
|||
|
|
//将笛卡尔三维坐标转为地图坐标(弧度)
|
|||
|
|
var cartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian3);
|
|||
|
|
//将地图坐标(弧度)转为十进制的度数
|
|||
|
|
var lat_String = Cesium.Math.toDegrees(cartographic.latitude).toFixed(6);
|
|||
|
|
var log_String = Cesium.Math.toDegrees(cartographic.longitude).toFixed(6);
|
|||
|
|
var alti_String = (viewer.camera.positionCartographic.height / 1000).toFixed(2);
|
|||
|
|
console.log(log_String+","+lat_String)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var picks = viewer.scene.drillPick(evt.position);
|
|||
|
|
console.log(picks)
|
|||
|
|
if(picks.length){
|
|||
|
|
picks.forEach(item=>{
|
|||
|
|
let attr = JSON.parse(item.id.id);
|
|||
|
|
if(attr.layerName == "riverLevel"){
|
|||
|
|
item.id.polygon.material = new Cesium.ColorMaterialProperty(Cesium.Color.fromCssColorString(attr.selectedColor)) ;
|
|||
|
|
if(this.selectedEntity ){
|
|||
|
|
this.selectedEntity.polygon.material = new Cesium.ColorMaterialProperty(Cesium.Color.fromCssColorString("rgba(0,0,0,0)")) ;
|
|||
|
|
}
|
|||
|
|
this.selectedEntity = item.id;
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}else{
|
|||
|
|
if(this.selectedEntity ){
|
|||
|
|
this.selectedEntity.polygon.material = new Cesium.ColorMaterialProperty(Cesium.Color.fromCssColorString("rgba(0,0,0,0)")) ;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
|
|||
|
|
|
|||
|
|
// 监听地图缩放控制实体的显示,另一种方案是使用 DistanceDisplayCondition 参数配置
|
|||
|
|
viewer.scene.camera.moveEnd.addEventListener(()=>{
|
|||
|
|
//获取当前相机高度
|
|||
|
|
let height = Math.ceil(viewer.camera.positionCartographic.height);
|
|||
|
|
console.log('height:' + height);
|
|||
|
|
// 获取相机位置的大小
|
|||
|
|
var currentMagnitude = viewer.camera.getMagnitude();
|
|||
|
|
console.log('currentMagnitude:' + currentMagnitude);
|
|||
|
|
|
|||
|
|
if(height>1200000){
|
|||
|
|
this.level1DataSource.show = true;
|
|||
|
|
this.level2DataSource.show = false;
|
|||
|
|
}else{
|
|||
|
|
this.level1DataSource.show = false;
|
|||
|
|
this.level2DataSource.show = true;
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
async createRiverLabel(text){
|
|||
|
|
// 创建画布对象
|
|||
|
|
let canvas = document.createElement("canvas");
|
|||
|
|
let url1 = "/images/hanjiang/river_location.png";
|
|||
|
|
const image = await new Cesium.Resource.fetchImage(url1);
|
|||
|
|
let padding = 8;
|
|||
|
|
let len = text.split("").length;
|
|||
|
|
let ww = 14*len+padding*2;
|
|||
|
|
|
|||
|
|
canvas.width = ww>image.width?ww:image.width;
|
|||
|
|
canvas.height = image.height;
|
|||
|
|
|
|||
|
|
let ctx = canvas.getContext("2d");
|
|||
|
|
ctx.drawImage(image, 0, 0, ww>image.width?ww:image.width, image.height);
|
|||
|
|
ctx.font = 'bold 14px Arial';
|
|||
|
|
ctx.textAlign = 'left';
|
|||
|
|
ctx.textBaseline = 'middle';
|
|||
|
|
ctx.fillStyle = 'rgba(255, 255, 255, 1)';
|
|||
|
|
ctx.fillText(text, ww>image.width?8:(image.width-ww+2*padding)/2, image.height/4);
|
|||
|
|
return canvas;
|
|||
|
|
},
|
|||
|
|
addPoiData(source,data,option){
|
|||
|
|
data.forEach(item=>{
|
|||
|
|
let image = this.createRiverLabel(item.name)
|
|||
|
|
|
|||
|
|
let opt = {
|
|||
|
|
id: JSON.stringify({ ...item, layerName: "poi" }),
|
|||
|
|
position: Cesium.Cartesian3.fromDegrees(item.coord[0], item.coord[1], 0),
|
|||
|
|
billboard: {
|
|||
|
|
eyeOffset: new Cesium.Cartesian3(0.0, 1.0, 0.0),
|
|||
|
|
image:image, // default: undefined
|
|||
|
|
show: true, // default
|
|||
|
|
// pixelOffset:new Cesium.Cartesian2(-60, 0),
|
|||
|
|
// width: 120, // default: undefined
|
|||
|
|
// height: 80, // default: undefined
|
|||
|
|
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
|||
|
|
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
|
|||
|
|
// 10.0,
|
|||
|
|
// 30000.0
|
|||
|
|
// ), //根据到相机的距离确定可见性。
|
|||
|
|
scaleByDistance: new Cesium.NearFarScalar(10, 1, 60000000, 0.0),
|
|||
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|||
|
|
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
|||
|
|
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
|||
|
|
},
|
|||
|
|
}
|
|||
|
|
source.entities.add(opt)
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
initTimeline(len){
|
|||
|
|
var start = Cesium.JulianDate.fromDate(new Date("2023-2-13"));
|
|||
|
|
var stop = Cesium.JulianDate.addSeconds( start, len, new Cesium.JulianDate() );
|
|||
|
|
this.start = start;
|
|||
|
|
this.stop = stop;
|
|||
|
|
//Make sure viewer is at the desired time.
|
|||
|
|
this._viewer.clock.startTime = start.clone();
|
|||
|
|
this._viewer.clock.stopTime = stop.clone();
|
|||
|
|
this._viewer.clock.currentTime = start.clone();
|
|||
|
|
this._viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; //Loop at the end
|
|||
|
|
this._viewer.clock.multiplier = 0.1;
|
|||
|
|
//Set timeline to simulation bounds
|
|||
|
|
this._viewer.timeline.zoomTo(start, stop);
|
|||
|
|
this._viewer.clock.shouldAnimate = false
|
|||
|
|
},
|
|||
|
|
flyPath(){
|
|||
|
|
// 设置时间
|
|||
|
|
this.initTimeline(this.path.length - 1);
|
|||
|
|
// 设置坐标的时间,使用 SampledPositionProperty进行插值
|
|||
|
|
let positions = this.getPositionProperty(this.path);
|
|||
|
|
let orientation = new Cesium.VelocityOrientationProperty( positions );
|
|||
|
|
|
|||
|
|
// 创建轨迹实体
|
|||
|
|
let flyEntity = window.pathSource.entities.add({
|
|||
|
|
show: true,
|
|||
|
|
//Set the entity availability to the same interval as the simulation time.
|
|||
|
|
availability: new Cesium.TimeIntervalCollection([
|
|||
|
|
new Cesium.TimeInterval({
|
|||
|
|
start: this.start,
|
|||
|
|
stop: this.stop,
|
|||
|
|
}),
|
|||
|
|
]),
|
|||
|
|
//使用计算的位置
|
|||
|
|
position: positions,
|
|||
|
|
//Automatically compute orientation based on position movement.
|
|||
|
|
orientation: orientation,
|
|||
|
|
//Load the Cesium plane model to represent the entity
|
|||
|
|
model: {
|
|||
|
|
show: false,
|
|||
|
|
uri:"./SampleData/models/CesiumAir/Cesium_Air.glb",
|
|||
|
|
minimumPixelSize: 64,
|
|||
|
|
},
|
|||
|
|
path: {
|
|||
|
|
show:true,
|
|||
|
|
resolution: 1,
|
|||
|
|
material: new Cesium.PolylineGlowMaterialProperty({
|
|||
|
|
glowPower: 0.1,
|
|||
|
|
color: Cesium.Color.YELLOW,
|
|||
|
|
}),
|
|||
|
|
width: 10,
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
flyEntity.position.setInterpolationOptions({
|
|||
|
|
interpolationDegree: 5,
|
|||
|
|
interpolationAlgorithm: Cesium.HermitePolynomialApproximation,
|
|||
|
|
});
|
|||
|
|
//监听时间变化,【关键代码】。保存返回值,是一个移除事件的回调函数
|
|||
|
|
this.tickCallBack&&this.tickCallBack();
|
|||
|
|
this.tickCallBack = viewer.clock.onTick.addEventListener( (e)=> {
|
|||
|
|
if (viewer.clock.shouldAnimate === true) {
|
|||
|
|
let ori = orientation.getValue(viewer.clock.currentTime); //获取偏向角
|
|||
|
|
let center = positions.getValue(viewer.clock.currentTime); //获取位置
|
|||
|
|
let transform = Cesium.Matrix4.fromRotationTranslation(
|
|||
|
|
Cesium.Matrix3.fromQuaternion(ori),
|
|||
|
|
center
|
|||
|
|
); //将偏向角转为3*3矩阵,利用实时点位转为4*4矩阵
|
|||
|
|
viewer.camera.lookAtTransform(
|
|||
|
|
transform,
|
|||
|
|
new Cesium.Cartesian3(-10, 0, 3)
|
|||
|
|
); //将相机向后面放一点, 第二个参数可以调整相机的姿态 [前后,左右,上下]
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
// 修改飞行状态
|
|||
|
|
// path.playing = true;
|
|||
|
|
// 飞行的时候隐藏轨迹相关的实体
|
|||
|
|
window.pathSource.show = false;
|
|||
|
|
this._viewer.trackedEntity = flyEntity;
|
|||
|
|
this._viewer.clock.shouldAnimate = true;
|
|||
|
|
},
|
|||
|
|
getPositionProperty(coords){
|
|||
|
|
// 给轨迹点关联时间和插值
|
|||
|
|
const property = new Cesium.SampledPositionProperty();
|
|||
|
|
for (var i = 0; i < coords.length; i++) {
|
|||
|
|
var time = Cesium.JulianDate.addSeconds( this.start, i, new Cesium.JulianDate() );
|
|||
|
|
var position = Cesium.Cartesian3.fromDegrees( coords[i][0], coords[i][1], coords[i][2] );
|
|||
|
|
property.addSample(time, position);
|
|||
|
|
window.pathSource.entities.add({
|
|||
|
|
position: position,
|
|||
|
|
point: {
|
|||
|
|
color: Cesium.Color.SKYBLUE,
|
|||
|
|
pixelSize: 10,
|
|||
|
|
outlineColor: Cesium.Color.YELLOW,
|
|||
|
|
outlineWidth: 3,
|
|||
|
|
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
|||
|
|
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
return property;
|
|||
|
|
},
|
|||
|
|
pauseFly(){
|
|||
|
|
window.pathSource.show = true;
|
|||
|
|
this._viewer.trackedEntity = null;
|
|||
|
|
this._viewer.clock.shouldAnimate = false;
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
mounted() {
|
|||
|
|
this.initViewer();
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|