<template>
<MarsMap :url="configUrl" :options="mapOptions" map-key="test" @onload="marsOnload" />
</template>
<script setup lang="ts">
import * as mars3d from 'mars3d'
import MarsMap from '@/components/mars/MarsMap.vue'
const Cesium = mars3d.Cesium
const configUrl = '/mars/config/config.json'
// data
const mapOptions = ref({
// scene: {},
// 地图原生控件
control: {
// 以下是Cesium.Viewer所支持的控件相关的options
// homeButton: { insertIndex: 4 }, // 视角复位按钮
mouseDownView: true,
contextmenu: { preventDefault: true },
geocoder: { insertIndex: 5 }, // POI查询按钮
geocoderConfig: { key: ['ae29a37307840c7ae4a785ac905927e0'] }, // POI查询按钮参数配置
distanceLegend: { left: '35px', bottom: '2px' },
zoom: true,
navigationHelpButton: true // 帮助按钮,显示默认的地图控制帮助
}
})
const graphicLayerMap = ref() // 矢量地图对象graphicLayer
const mapRef = ref() // 地图实例
const DrawPostion = ref([]) // 航线点数据数组
const fenceList = ref([]) // 围栏数据
// methods
const marsOnload = async (map: any) => {
// 获取航线详情数据
map.unbindContextMenu() // 置空鼠标右键默认事件
mars3d.DrawUtil.setEditPointStyle(mars3d.EditPointType.Control, {
pixelSize: 14,
outline: true,
outlineColor: '#ffffff',
outlineWidth: 2,
color: '#145CFC',
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.CENTER
})
// 创建左侧自定义按钮
const toolButton2 = new mars3d.control.ToolButton({
title: '返回原点',
icon: '/mars/img/H.png',
insertIndex: 7, // 插⼊的位置顺序 , 1 是 home 按钮后⾯
click: () => {}
})
// 添加自定义按钮
map.addControl(toolButton2)
mapRef.value = map
// 创建矢量图层
graphicLayerMap.value = new mars3d.layer.GraphicLayer({
hasEdit: true,
isAutoEditing: true // 绘制完成后是否自动激活编辑
})
map.addLayer(graphicLayerMap.value)
// 开启绘面功能
addDrawPolygon(false, graphicLayerMap.value)
// 绑定layer标绘相关事件监听(可以自行加相关代码实现业务需求,此处主要做示例)
graphicLayerMap.value.on(mars3d.EventType.drawStart, function (e: any) {
console.log('开始绘制', e)
})
graphicLayerMap.value.on(mars3d.EventType.drawAddPoint, function (e: any) {
console.log('绘制过程中增加了第' + (e.index + 1) + '个点', e)
if (e.graphic?.name === 'Polyline') return // 修改围栏过程中会触发监听,不再进行更新
postUpdate(e.graphic._positions_draw, e.graphic, null)
})
graphicLayerMap.value.on(mars3d.EventType.drawRemovePoint, function (e: any) {
// console.log('绘制过程中删除了第' + (e.index + 1) + '个点', e)
})
graphicLayerMap.value.on(mars3d.EventType.drawCreated, function (e: any) {
// console.log('创建完成', e)
})
graphicLayerMap.value.on(mars3d.EventType.editStart, function (e: any) {
// console.log('开始编辑', e)
})
graphicLayerMap.value.on(mars3d.EventType.editMovePoint, function (e: any) {
if (e.graphic?.name === 'Polyline') return
postUpdate(e.graphic._positions_draw, e.graphic, e.index)
// console.log('编辑修改了第' + (e.index + 1) + '个点', e, graphicLayerMap.value)
})
// graphicLayerMap.value.on(mars3d.EventType.editAddPoint, function (e: any) {
// console.log('编辑新增了点', e)
// })
graphicLayerMap.value.on(mars3d.EventType.editRemovePoint, function (e: any) {
// console.log('编辑删除了第' + (e.index + 1) + '个点', e)
if (e.graphic?.name === 'Polyline') return
postUpdate(e.graphic._positions_draw, e.graphic, e.index)
})
graphicLayerMap.value.on(mars3d.EventType.editStop, function (e: any) {
// console.log('停止编辑', e)
})
graphicLayerMap.value.on(mars3d.EventType.removeGraphic, function (e: any) {
// console.log('删除了对象', e)
if (e.graphic?.name === 'Polyline') return
DrawPostion.value = []
setTimeout(() => {
// 等待矢量地图销毁后再根据地图状态判断是否重新绘制
if (graphicLayerMap.value.state === 'destroy') {
// graphicLayerMap地图销毁后不再执行重绘模式
return
}
// 清空航线后重新进入绘画模式
addDrawPolygon(false, graphicLayerMap.value)
}, 100)
})
// 初始加载数据, 获取编辑getbyid数据,或者新增数据
// if (props.formState?.id) {
// // 有airRouteId 则代表是二次编辑进入
// const res = await airRouteGetById(route.query?.airRouteId)
// routesData.value = props.routesDataState
// routesForm.value = routesData.value
// fenceList.value = JSON.parse(JSON.stringify(routesData.value.airRouteDotPoints))
// editDrawPolygon(false, routesData.value.airRouteDotPoints, {})
// } else {
// // 无airRouteId 新增进入,首次加载进入后启动绘制功能, 并保存新增弹窗字段addFrom
// addDrawPolygon(false, graphicLayerMap.value)
// }
}
// 围栏计算航线部分---- 压缩代码
const BoundLength = ref(0)
const height = ref(100)
const minHeight = ref(-1500)
const maxHeight = ref(1500)
const speed = ref(5)
const lateralOverlapRate = ref(60) // 旁向重叠率
const courseOverlapRate = ref(75) // 航向重叠率
const mainCourseAngle = ref(90)
const delta = ref(0)
const spaceScale = ref<any>(Cesium.Math.lerp(1, 4, height.value / 500))
const spaceHDistance = ref(Cesium.Math.lerp(90, 3, lateralOverlapRate.value / 100) * spaceScale.value)
/**
* 更新航线经纬度数据
* @param positions index索引 + 1 当前航线坐标集合
* @param graphic 矢量地图对象
* @param index 索引, 点击了第 N 个 航点更新地图并更新第N条数据
*/
const postUpdate = async (positionsData: any, graphic: any, index: any) => {
const oldList = JSON.parse(JSON.stringify(fenceList.value)) // 记录历史航点数据集合
if ([null, undefined, ''].includes(index)) {
// 首次创建时, 不会有索引, 直接添加数据fenceList.value
fenceList.value = positionsData.map((item: any, idx: any) => {
// // 将笛卡尔坐标转换为地理坐标(经纬度)
const positionPoint = Cesium.Ellipsoid.WGS84.cartesianToCartographic(item)
// 将坐标格式化为正常经、纬、高
const longitude = Cesium.Math.toDegrees(positionPoint.longitude).toFixed(6)
const latitude = Cesium.Math.toDegrees(positionPoint.latitude).toFixed(6)
const height = positionPoint.height.toFixed(0)
const position = idx + 1
return { longitude, latitude, height, position }
})
} else {
// 二次编辑,对航点进行增加、删除、修改,都会传索引 index
let indexFrom = {} // 储存对应索引的值
positionsData.forEach((item: any, idx: any) => {
// // 将笛卡尔坐标转换为地理坐标(经纬度)
const positionPoint = Cesium.Ellipsoid.WGS84.cartesianToCartographic(item)
// 将坐标格式化为正常经、纬、高
const longitude = Cesium.Math.toDegrees(positionPoint.longitude).toFixed(6)
const latitude = Cesium.Math.toDegrees(positionPoint.latitude).toFixed(6)
const height = positionPoint.height.toFixed(0)
const position = idx + 1
if (idx === index) {
indexFrom = { longitude, latitude, height, position }
}
})
// 将之前数据集合地图航点长度对比
if (oldList.length < positionsData.length) {
// console.log('add', indexFrom, index)
fenceList.value.splice(index, 0, { ...indexFrom, yawAngle: undefined, airRouteDotActions: [] })
// 插入数据,后面索引被打乱 重新赋值 索引 position
fenceList.value.forEach((item: any, idx) => {
item.position = idx + 1
})
} else if (oldList.length > positionsData.length) {
// console.log('del')
fenceList.value.splice(index, 1)
// 删除数据,后面索引被打乱 重新赋值 索引 position
fenceList.value.forEach((item: any, idx) => {
item.position = idx + 1
})
} else if (oldList.length === positionsData.length) {
// console.log('update', indexFrom)
fenceList.value.forEach((item: any, idx) => {
if (index === idx) {
Object.assign(item, { ...item, ...indexFrom })
}
})
}
}
await setRouteList(fenceList.value)
}
// 机巢位置
const currentDock = ref({ lng: 0, lat: 0, flyHeight: 50 })
// 新增围栏
const addDrawPolygon = (clampToGround: boolean, graphicLayer: any) => {
graphicLayer.startDraw({
type: 'polygon',
name: 'polygon',
attr: { color: '#3388ff' },
hasMoveEdit: false, // 禁用整体平移
style: {
zIndex: 20,
opacity: 0.5,
outline: true,
outlineWidth: 2,
outlineColor: '#3388ff',
color: '#3388ff',
width: 3,
clampToGround
}
})
}
/**
* 已有数据,生成围栏
* @param clampToGround // 是否贴地
* @param graphicLayer // 矢量图对象
* @param airRouteDotPoints // 航线数据集
*/
const editDrawPolygon = (clampToGround: boolean, points: any, from: any) => {
const positions: any = []
points.forEach((item: any) => {
positions.push([item.longitude, item.latitude, item.height])
})
const graphic = new mars3d.graphic.PolygonEntity({
positions,
name: 'polygon',
attr: { attrForm: from, id: from?.dotPointsId, type: from.type, color: +from.type === 1 ? '#3388ff' : '#f00' },
hasMoveEdit: false, // 禁用整体平移
style: {
zIndex: 20,
opacity: 0.5,
outline: true,
outlineWidth: 2.5,
outlineColor: +from.type === 1 ? '#3388ff' : '#f00',
color: +from.type === 1 ? '#3388ff' : '#f00',
// color: clampToGround ? '#ffff00' : '#3388ff',
width: 3,
clampToGround
}
})
graphicLayerMap.value.addGraphic(graphic)
// graphic.startEditing()
// 可在图层绑定右键菜单,对所有加到这个图层的矢量数据都生效
}
/**
* 根据围栏经纬度数据计算航线数据
* @param data 围栏经纬度数组集合
*/
const setRouteList = async (data: any) => {
// 将围栏数据转换成Cartesian3坐标
const fenceData: any = [] // 围栏数据集合
await data.forEach(async (item: any) => {
const ite = await GetC3FromLngLat(item.longitude, item.latitude, item.height)
fenceData.push(ite)
})
// 获取绘制区航线数据
const routeList: any = await GetBrokenPoints(fenceData)
// 获取总里程
// routesForm.value.courseMileage = Number(mars3d.MeasureUtil.formatDistance(graphic.distance, { unit: 'km' })?.split('公里')[0])
// Cartesian3转换航线数据
const newRouteList: any = []
await routeList?.forEach(async (item: any) => {
const itess = await GetLngLatFromC3(item)
newRouteList.push([itess.R, itess.Q, itess.H])
})
DrawPostion.value = newRouteList
// 创建前 先判断是否存在航线,是则直接修改经纬度,否则创建航线
const graphicArr = await graphicLayerMap.value.getGraphics(false)
if (graphicArr?.some((item: any) => item.name === 'Polyline')) {
await graphicArr?.forEach(async (item: any) => {
if (item.name === 'Polyline') {
// 存在航线,则直接修改航线经纬度
item.setCallbackPositions(newRouteList)
}
})
} else {
if (!newRouteList?.length) return
// 首次创建设置
await editDrawPolyline(false, newRouteList)
}
}
/**
* 已有数据,生成航线
* @param clampToGround // 是否贴地
* @param graphicLayer // 矢量图对象
* @param routeDotPoints // 航线数据集
*isDisabled鼠标右键菜单禁用,不传默认false
*/
const editDrawPolyline = async (clampToGround: boolean, routeDotPoints: any) => {
const graphic = await new mars3d.graphic.PolylineEntity({
positions: routeDotPoints,
name: 'Polyline',
hasEdit: false,
hasEditContextMenu: false,
attr: { isDisabled: true },
hasMoveEdit: false, // 禁用整体平移
style: {
zIndex: 80,
color: clampToGround ? '#ffff00' : '#ffff00',
width: 3,
clampToGround
}
})
graphicLayerMap.value.addGraphic(graphic)
// 获取总里程
}
// 围栏数据转换成航线
/**
*
*
*/
const GetBrokenPoints = async (e: any) => {
if (e.length < 2) return
const t = await GetSomeBasePointData(e)
const s = await GetLineSections(e)
const n = GetAllPoints(t.StartPoint, t.StartPoint_End, t.normalVectorA, t.normalVectorB, s)
// eslint-disable-next-line no-sequences
return n.push(t.AnotherStartPoint), n.unshift(t.StartPoint), SetPointHeight(n, t.StartPoint, t.StartPoint_End)
}
function GetSomeBasePointData(e: any) {
const t = Cesium.BoundingSphere.fromPoints(e).center
const s = GetLngLatFromC3(t).R
const n = GetLngLatFromC3(t).Q
const o = GetLngLatFromC3(e[0]).H
const r = GetC3FromLngLat(s, n, o)
const l = mainCourseAngle.value
const u = r
const c = spanVector(r, OriginVector(r), l)
const d = GetFarestPoint(u, c, e)
const v = GetPointDs(d, u, c)
const p = GetFarestPoint(d, v, e)
const I = GetPointDs(p, u, c)
// 未明确变量currentDock
const R = GetC3FromLngLat(currentDock.value.lng, currentDock.value.lat, currentDock.value.flyHeight)
const H = Cesium.Cartesian3.distance(R, d)
const k = Cesium.Cartesian3.distance(R, p)
const b = k > H ? d : p
const m = k > H ? v : I
const O = k > H ? p : d
const U = k > H ? I : v
const w = Get_A_to_BC_Vector(b, O, U)
const P = Get_A_to_BC_Vector(m, O, U)
return (
(BoundLength.value = Cesium.Cartesian3.distance(b, w)),
{
StartPoint: b,
StartPoint_End: m,
AnotherStartPoint: O,
AnotherStartPoint_End: U,
normalVectorA: w,
normalVectorB: P
}
)
}
function GetLineSections(data: any) {
const e = []
const t = []
for (const s of data) {
const n = GetLngLatFromC3(s)
t.push({
x: n.R,
y: n.Q,
z: n.H
})
}
for (let s = 0; s < t.length; s++) {
s === t.length - 1
? e.push({
a: {
x: t[s].x,
y: t[s].y,
z: t[s].z
},
b: {
x: t[0].x,
y: t[0].y,
z: t[s].z
}
})
: e.push({
a: {
x: t[s].x,
y: t[s].y,
z: t[s].z
},
b: {
x: t[s + 1].x,
y: t[s + 1].y,
z: t[s + 1].z
}
})
}
return e
}
function GetAllPoints(e: any, t: any, s: any, n: any, o: any) {
const r = Math.abs(spaceHDistance.value)
let l = r / 2
const u = e
const c = t
const d = s
const v = n
let p = !1
const I = []
let R = !0
let H = !0
const k = Cesium.Cartesian3.subtract(t, e, new Cesium.Cartesian3())
for (Cesium.Cartesian3.normalize(k, new Cesium.Cartesian3()); l < BoundLength.value; ) {
const b = GetNewPointFromVector(u, d, l)
const m = GetNewPointFromVector(c, v, l)
const O = {
x: GetLngLatFromC3(b).R,
y: GetLngLatFromC3(b).Q,
z: GetLngLatFromC3(b).H
}
const U = {
x: GetLngLatFromC3(m).R,
y: GetLngLatFromC3(m).Q,
z: GetLngLatFromC3(m).H
}
const w = []
for (const P of o) {
const V = GetCrossPoint(O, U, P.a, P.b)
V && w.push(V)
}
if (w.length === 2 && H) {
const P = Cesium.Cartesian3.subtract(w[1], w[0], new Cesium.Cartesian3())
const V = Cesium.Cartesian3.subtract(t, e, new Cesium.Cartesian3())
Cesium.Math.toDegrees(Cesium.Cartesian3.angleBetween(V, P)) < 1 ? (R = !0) : (R = !1)
const L = Cesium.Cartesian3.distance(e, w[0])
const q = Cesium.Cartesian3.distance(e, w[1])
L > q && (p = !0), (H = !1)
}
if (w.length == 2 && !H) {
const P = Cesium.Cartesian3.subtract(w[1], w[0], new Cesium.Cartesian3())
const V = Cesium.Cartesian3.subtract(t, e, new Cesium.Cartesian3())
const ee = Cesium.Math.toDegrees(Cesium.Cartesian3.angleBetween(V, P))
R ? ee > 179 && w.reverse() : ee < 1 && w.reverse()
}
;(l += r), p ? (I.push(...w.reverse()), (p = !1)) : (I.push(...w), (p = !0))
}
return I
}
function spanVector(e: any, t: any, s: any) {
const n = Cesium.Cartesian3.subtract(t, e, new Cesium.Cartesian3())
const o = Cesium.Math.toRadians(s)
const r = GetLngLatFromC3(e)
const l = r.H + 1
const u = GetC3FromLngLat(r.R, r.Q, l)
const c = Cesium.Cartesian3.subtract(u, e, new Cesium.Cartesian3())
const d = Cesium.Matrix3.fromQuaternion(Cesium.Quaternion.fromAxisAngle(c, o))
const C = Cesium.Matrix3.multiplyByVector(d, n, new Cesium.Cartesian3())
const p = Cesium.Cartesian3.add(e, C, new Cesium.Cartesian3())
return p
}
function OriginVector(e: any) {
const t = GetLngLatFromC3(e)
const s = t.R + 0.005
const n = GetC3FromLngLat(s, t.Q, t.H)
return Cesium.Cartesian3.subtract(n, e, new Cesium.Cartesian3()), spanVector(e, n, 0)
}
function GetFarestPoint(e: any, t: any, s: any) {
const n = []
const o = Cesium.Cartesian3.subtract(t, e, new Cesium.Cartesian3())
for (const d of s) {
const r = Cesium.Cartesian3.subtract(d, e, new Cesium.Cartesian3())
const l = Cesium.Cartesian3.cross(o, r, new Cesium.Cartesian3())
const u = Cesium.Cartesian3.magnitude(l)
n.push(u)
}
const c = n.indexOf(Math.max(...n))
return s[c]
}
function GetPointDs(e: any, t: any, s: any) {
const n = Cesium.Cartesian3.subtract(s, t, new Cesium.Cartesian3())
const o = 1
const r = Cesium.Cartesian3.multiplyByScalar(n, o, new Cesium.Cartesian3())
const l = Cesium.Cartesian3.add(e, r, new Cesium.Cartesian3())
return l
}
function Get_A_to_BC_Vector(e: any, t: any, s: any) {
const n = GetLngLatFromC3(e)
const o = GetLngLatFromC3(t)
const r = GetLngLatFromC3(s)
if (r.R - o.R !== 0) {
if (r.Q - o.Q !== 0) {
const l = (r.Q - o.Q) / (r.R - o.R)
const u = o.Q - l * o.R
const c = (n.R - l * u + l * n.Q) / (1 + l * l)
const d = (l * n.R + l * l * n.Q + u) / (1 + l * l)
return GetC3FromLngLat(c, d, o.H)
} else return GetC3FromLngLat(n.R, o.Q, o.H)
} else return GetC3FromLngLat(o.R, n.Q, o.H)
}
function GetNewPointFromVector(e: any, t: any, s: any) {
const n = Cesium.Cartesian3.normalize(
Cesium.Cartesian3.subtract(t, e, new Cesium.Cartesian3()),
new Cesium.Cartesian3()
)
return Cesium.Cartesian3.add(
e,
Cesium.Cartesian3.multiplyByScalar(n, s, new Cesium.Cartesian3()),
new Cesium.Cartesian3()
)
}
function SetPointHeight(e: any, t: any, s: any) {
const n = SetDeltaForPoints(e, t, s)
const o = []
for (const r of n) o.push(r)
return o
}
function SetDeltaForPoints(e: any, t: any, s: any) {
const n = delta.value
const o = Cesium.Cartesian3.subtract(s, t, new Cesium.Cartesian3())
const r = Cesium.Cartesian3.normalize(o, new Cesium.Cartesian3())
const l = Cesium.Cartesian3.subtract(e[2], e[1], new Cesium.Cartesian3())
const u = Cesium.Math.toDegrees(Cesium.Cartesian3.angleBetween(o, l))
let c = -1
e.length > 2 && (u < 1 ? (c = 1) : (c = 0))
const d = []
for (let C = 0; C < e.length; C++) {
const p = GetLngLatFromC3(e[C])
const b = GetC3FromLngLat(p.R, p.Q, p.H)
if (C !== 0 && C !== e.length - 1) {
if (C % 4 == 1 || C % 4 == 0) {
const B = Cesium.Cartesian3.add(
b,
Cesium.Cartesian3.multiplyByScalar(r, c == 1 ? -n : n, new Cesium.Cartesian3()),
new Cesium.Cartesian3()
)
d.push(B)
}
if (C % 4 == 2 || C % 4 == 3) {
const B = Cesium.Cartesian3.add(
b,
Cesium.Cartesian3.multiplyByScalar(r, c == 1 ? n : -n, new Cesium.Cartesian3()),
new Cesium.Cartesian3()
)
d.push(B)
}
} else d.push(b)
}
return d
}
function GetCrossPoint(e: any, t: any, s: any, n: any) {
const o = e.z
const r = (t.y - e.y) * (n.x - s.x) - (e.x - t.x) * (s.y - n.y)
if (r === 0) return !1
if (t.x - e.x !== 0) {
const c = (t.y - e.y) / (t.x - e.x)
const d = e.y - c * e.x
const C = c * s.x - s.y + d
const p = c * n.x - n.y + d
if (C * p <= 0) {
var l =
((t.x - e.x) * (n.x - s.x) * (s.y - e.y) + (t.y - e.y) * (n.x - s.x) * e.x - (n.y - s.y) * (t.x - e.x) * s.x) /
r
var u =
-((t.y - e.y) * (n.y - s.y) * (s.x - e.x) + (t.x - e.x) * (n.y - s.y) * e.y - (n.x - s.x) * (t.y - e.y) * s.y) /
r
return GetC3FromLngLat(l, u, o)
} else return !1
} else {
if ((s.x > e.x && n.x > e.x) || (s.x < e.x && n.x < e.x)) return !1
var l =
((t.x - e.x) * (n.x - s.x) * (s.y - e.y) + (t.y - e.y) * (n.x - s.x) * e.x - (n.y - s.y) * (t.x - e.x) * s.x) / r
var u =
-((t.y - e.y) * (n.y - s.y) * (s.x - e.x) + (t.x - e.x) * (n.y - s.y) * e.y - (n.x - s.x) * (t.y - e.y) * s.y) / r
return GetC3FromLngLat(l, u, o)
}
}
// 将Cartesian3转换为经纬高坐标
function GetLngLatFromC3(e: any) {
const viewer = mapRef.value
if (viewer) {
const t = viewer.scene.globe.ellipsoid.cartesianToCartographic(e)
const s = Cesium.Math.toDegrees(t.longitude)
const n = Cesium.Math.toDegrees(t.latitude)
return {
R: s,
Q: n,
H: t.height
}
}
return {
R: 0,
Q: 0,
H: 0
}
}
// 将经纬高转换为Cartesian3坐标
function GetC3FromLngLat(e: any, t: any, s: any) {
return Cesium.Cartesian3.fromDegrees(e, t, s)
}
</script>
通过绘面生成航线数据
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 安装html2canvas 在页面中引入 点击截图按钮后生成图片并下载到本地,但是打开图片之后发现,页面中原有的图...
- 在前面介绍了Tangram框架的历史由来和基本概念后,说明了Tangram解决了什么问题,可以用来做什么,核心是按...
- Detail组件现在能够接受一个传进来的参数来渲染一句话,同时也能简单的渲染其他合法的es6代码。为了证明这一点,...