Commit af570879 by wanghao

增加示例及修复问题

parent f42eff5b
...@@ -37,8 +37,8 @@ module.exports = { ...@@ -37,8 +37,8 @@ module.exports = {
"no-use-before-define": "off", // 允许 方法在未定义前使用 "no-use-before-define": "off", // 允许 方法在未定义前使用
"multiline-ternary": "off", "multiline-ternary": "off",
"no-restricted-globals": "off", "no-restricted-globals": "off",
"react-hooks/exhaustive-deps": "off", // 检查 effect 的依赖
"react-hooks/rules-of-hooks": "error", // 检查 Hook 的规则 "react-hooks/rules-of-hooks": "error", // 检查 Hook 的规则
"react-hooks/exhaustive-deps": "warn", // 检查 effect 的依赖
// mars3d-react-example项目专用的配置(目的便于示例的开发调试) end // mars3d-react-example项目专用的配置(目的便于示例的开发调试) end
"@typescript-eslint/no-explicit-any": "off", // ts:允许用any "@typescript-eslint/no-explicit-any": "off", // ts:允许用any
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
}, },
"dependencies": { "dependencies": {
"@icon-park/react": "^1.3.5", "@icon-park/react": "^1.3.5",
"@marsgis/editor": "^1.0.4", "@marsgis/editor": "^1.0.7",
"@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/eslint-plugin": "^4.33.0",
"@typescript-eslint/parser": "^4.33.0", "@typescript-eslint/parser": "^4.33.0",
"antd": "^4.19.3", "antd": "^4.19.3",
......
...@@ -2897,6 +2897,14 @@ ...@@ -2897,6 +2897,14 @@
"libs": ["mars3d", "mars3d-heatmap"] "libs": ["mars3d", "mars3d-heatmap"]
}, },
{ {
"name": "动态热力图",
"thumbnail": "layero-heatmap-heatLayer-dynamic.gif",
"main_es5": "layero-heatmap-heatLayer-dynamic",
"main": "layer-other/heatmap/heatLayer-dynamic",
"hasPannel": true,
"libs": ["mars3d", "mars3d-heatmap"]
},
{
"name": "立体曲面热力图", "name": "立体曲面热力图",
"thumbnail": "layero-heatmap-heatLayer-arc.jpg", "thumbnail": "layero-heatmap-heatLayer-arc.jpg",
"main_es5": "layero-heatmap-heatLayer-arc", "main_es5": "layero-heatmap-heatLayer-arc",
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Mars3D三维可视化平台 mars3d * Mars3D三维可视化平台 mars3d
* *
* 版本信息:v3.3.9 * 版本信息:v3.3.9
* 编译日期:2022-05-18 19:45:00 * 编译日期:2022-05-22 14:42:11
* 版权所有:Copyright by 火星科技 http://mars3d.cn * 版权所有:Copyright by 火星科技 http://mars3d.cn
* 使用单位:免费公开版 ,2022-02-01 * 使用单位:免费公开版 ,2022-02-01
*/ */
...@@ -22,6 +22,16 @@ ...@@ -22,6 +22,16 @@
.mars3d-container .mars3d-vrButton { .mars3d-container .mars3d-vrButton {
right: auto !important; right: auto !important;
} }
/**隐藏的div对象,如 DivBillboardEntity、HeatLayer 等*/
.mars3d-hideDiv {
z-index: -1;
position: absolute !important;
top: 0;
left: 0;
margin: 0;
padding: 0;
pointer-events: none;
}
/**右键菜单*/ /**右键菜单*/
.mars3d-contextmenu { .mars3d-contextmenu {
position: absolute; position: absolute;
...@@ -485,12 +495,6 @@ ...@@ -485,12 +495,6 @@
margin: -2px; margin: -2px;
box-sizing: content-box; box-sizing: content-box;
} }
.mars3d-divBillboardEntity {
position: absolute;
top: 0;
left: 0;
z-index: -1;
}
/**内置的DivGraphic通用样式【动画点】*/ /**内置的DivGraphic通用样式【动画点】*/
.mars3d-animation-point, .mars3d-animation-point,
.mars3d-animation-point:after, .mars3d-animation-point:after,
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -18,7 +18,7 @@ Mars3D平台插件, 结合supermap超图库使用的功能插件 ...@@ -18,7 +18,7 @@ Mars3D平台插件, 结合supermap超图库使用的功能插件
"mars3d/plugins/supermap/mars3d-supermap.js",//mars3d-supermap简化调用封装 "mars3d/plugins/supermap/mars3d-supermap.js",//mars3d-supermap简化调用封装
], ],
``` ```
更多参考mars3d功能示例中[S3M图层示例](https://mars3d.cn/editor.html?id=layer-other/s3m/basis) 更多参考mars3d功能示例中[S3M图层示例](https://mars3d.cn/editor-vue.html?id=layer-other/s3m/basis)
#### 此方式的特别说明 #### 此方式的特别说明
经过测试,[SuperMap3D](https://github.com/SuperMap/iClient3D-for-WebGL/tree/main/Cesium_S3MLayer_Plugins/S3MTilesLayer)插件代码不是最新的,超图官网API很多在此插件中都没有。 经过测试,[SuperMap3D](https://github.com/SuperMap/iClient3D-for-WebGL/tree/main/Cesium_S3MLayer_Plugins/S3MTilesLayer)插件代码不是最新的,超图官网API很多在此插件中都没有。
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -22,18 +22,13 @@ class CanvasBillboard extends mars3d.graphic.BillboardEntity { ...@@ -22,18 +22,13 @@ class CanvasBillboard extends mars3d.graphic.BillboardEntity {
_mountedHook() { _mountedHook() {
super._mountedHook() super._mountedHook()
// 图片对象 if (this._pngImage) {
this.style.imageUrl = "img/marker/textPnl.png" this._updateCanvas()
} else {
this.style.imageUrl = "img/marker/textPnl.png" // 图片对象
this.style.width = 300 this.style.width = 300
this.style.height = 140 this.style.height = 140
if (!this._canvas) {
this._canvas = document.createElement("canvas")
this._canvas.width = this.style.width
this._canvas.height = this.style.height
}
if (!this._pngImage) {
const img = new Image(this.style.width, this.style.height) const img = new Image(this.style.width, this.style.height)
img.crossOrigin = "Anonymous" img.crossOrigin = "Anonymous"
img.src = this.style.imageUrl img.src = this.style.imageUrl
...@@ -42,16 +37,18 @@ class CanvasBillboard extends mars3d.graphic.BillboardEntity { ...@@ -42,16 +37,18 @@ class CanvasBillboard extends mars3d.graphic.BillboardEntity {
this._updateCanvas() this._updateCanvas()
} }
} }
this._updateCanvas()
} }
// 创建canvas // 创建canvas
_updateCanvas() { _updateCanvas() {
if (!this._pngImage || !this._canvas) { if (!this._pngImage) {
return return
} }
const canvas = this._canvas const canvas = document.createElement("canvas")
canvas.width = this.style.width
canvas.height = this.style.height
const ctx = canvas.getContext("2d") const ctx = canvas.getContext("2d")
ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.clearRect(0, 0, canvas.width, canvas.height)
// 绘制图片 // 绘制图片
...@@ -65,11 +62,8 @@ class CanvasBillboard extends mars3d.graphic.BillboardEntity { ...@@ -65,11 +62,8 @@ class CanvasBillboard extends mars3d.graphic.BillboardEntity {
ctx.fillText(this.style.text, 160, canvas.height / 2) ctx.fillText(this.style.text, 160, canvas.height / 2)
ctx.fillText("℃", 220, canvas.height / 2) ctx.fillText("℃", 220, canvas.height / 2)
const newImg = new Image(canvas.width, canvas.height)
newImg.src = canvas.toDataURL("image/png")
// 将图片赋予给矢量对象进行显示,this.image是父类的属性 // 将图片赋予给矢量对象进行显示,this.image是父类的属性
this.image = newImg this.image = canvas
} }
} }
mars3d.graphic.CanvasBillboard = CanvasBillboard mars3d.graphic.CanvasBillboard = CanvasBillboard
...@@ -168,7 +168,6 @@ function addDemoGraphic5(graphicLayer) { ...@@ -168,7 +168,6 @@ function addDemoGraphic5(graphicLayer) {
topRadius: 0.0, topRadius: 0.0,
bottomRadius: 3000, bottomRadius: 3000,
material: mars3d.MaterialUtil.createMaterialProperty(mars3d.MaterialType.CircleWave, { material: mars3d.MaterialUtil.createMaterialProperty(mars3d.MaterialType.CircleWave, {
duration: 2000,
color: "#02ff00" color: "#02ff00"
}) })
}, },
......
...@@ -151,27 +151,36 @@ function addDemoGraphic5(graphicLayer) { ...@@ -151,27 +151,36 @@ function addDemoGraphic5(graphicLayer) {
position: [116.1, 30.9, 1000], position: [116.1, 30.9, 1000],
style: { style: {
radii: 2500, radii: 2500,
innerRadii: 1500,
maximumConeDegree: 90, // 半球 maximumConeDegree: 90, // 半球
fill: false, material: mars3d.MaterialUtil.createMaterialProperty(mars3d.MaterialType.WallScroll, {
image: "img/textures/line-color3.png",
count: 1.0,
color: "#00ffff",
speed: 20,
direction: -1,
axisY: true,
bloom: true
}),
subdivisions: 128, subdivisions: 128,
stackPartitions: 32, stackPartitions: 32,
slicePartitions: 32, slicePartitions: 32,
outline: true, outline: true,
outlineColor: "#f33349" outlineColor: "#00ffff"
}, },
attr: { remark: "示例5" } attr: { remark: "示例5" }
}) })
graphicLayer.addGraphic(graphic) // 还可以另外一种写法: graphic.addTo(graphicLayer) graphicLayer.addGraphic(graphic) // 还可以另外一种写法: graphic.addTo(graphicLayer)
// 添加扫描面 // 添加扫描面
graphic.addScanPlane({ // graphic.addScanPlane({
type: "roll", // 扫描类型 // type: "roll", // 扫描类型
step: 0.5, // 步长 // step: 0.5, // 步长
style: { // style: {
minimumConeDegree: -90.0, // minimumConeDegree: -90.0,
maximumConeDegree: 90.0 // maximumConeDegree: 90.0
} // }
}) // })
} }
// 半圆顶球体 // 半圆顶球体
...@@ -181,24 +190,32 @@ function addDemoGraphic6(graphicLayer) { ...@@ -181,24 +190,32 @@ function addDemoGraphic6(graphicLayer) {
style: { style: {
radii: 2500, radii: 2500,
maximumConeDegree: 90, maximumConeDegree: 90,
fill: false, material: mars3d.MaterialUtil.createMaterialProperty(mars3d.MaterialType.WallScroll, {
outline: true, image: "img/textures/poly-san.png",
outlineColor: Cesium.Color.BLUE.withAlpha(0.6) count: 1.0,
color: "#00ffff",
speed: 20,
direction: 1,
axisY: false,
bloom: true
})
// outline: true,
// outlineColor: Cesium.Color.BLUE.withAlpha(0.6)
}, },
attr: { remark: "示例6" } attr: { remark: "示例6" }
}) })
graphicLayer.addGraphic(graphic) graphicLayer.addGraphic(graphic)
// 添加扫描面 // // 添加扫描面
graphic.addScanPlane({ // graphic.addScanPlane({
type: "pitch", // 扫描类型 // type: "pitch", // 扫描类型
step: 0.5, // 步长 // step: 0.5, // 步长
style: { // style: {
roll: 90, // roll: 90,
minimumConeDegree: 0.0, // minimumConeDegree: 0.0,
maximumConeDegree: 180.0 // maximumConeDegree: 180.0
} // }
}) // })
} }
// 含内半径 半圆顶球体 // 含内半径 半圆顶球体
......
...@@ -2,7 +2,7 @@ import { MarsPannel, MarsButton, MarsSlider, MarsInput } from "@mars/components/ ...@@ -2,7 +2,7 @@ import { MarsPannel, MarsButton, MarsSlider, MarsInput } from "@mars/components/
import { Space } from "antd" import { Space } from "antd"
import * as mapWork from "./map.js" import * as mapWork from "./map.js"
import "./index.less" import "./index.less"
import { useWidget } from "@mars/common/store/widget" import { activate, disable, updateWidget, isActive } from "@mars/widgets/common/store/widget"
import { useMemo, useState, useCallback } from "react" import { useMemo, useState, useCallback } from "react"
const onClickDrawWall = () => { const onClickDrawWall = () => {
...@@ -26,7 +26,6 @@ function UIComponent() { ...@@ -26,7 +26,6 @@ function UIComponent() {
const [text, setText] = useState("Mars3D 火星科技 2017") const [text, setText] = useState("Mars3D 火星科技 2017")
const { disable, activate, setWidgetData } = useWidget()
const showEditor = useCallback( const showEditor = useCallback(
(e: any) => { (e: any) => {
activate({ activate({
...@@ -43,7 +42,7 @@ function UIComponent() { ...@@ -43,7 +42,7 @@ function UIComponent() {
}) })
// 编辑修改了模型 // 编辑修改了模型
mapWork.eventTarget.on("graphicEditor-update", async (e: any) => { mapWork.eventTarget.on("graphicEditor-update", async (e: any) => {
setWidgetData("graphic-editor", { updateWidget("graphic-editor", {
data: { graphic: e.graphic } data: { graphic: e.graphic }
}) })
showEditor(e) showEditor(e)
......
...@@ -38,6 +38,7 @@ export function onMounted(mapInstance) { ...@@ -38,6 +38,7 @@ export function onMounted(mapInstance) {
addDemoGraphic7(graphicLayer) addDemoGraphic7(graphicLayer)
addDemoGraphic8(graphicLayer) addDemoGraphic8(graphicLayer)
addDemoGraphic9(graphicLayer) addDemoGraphic9(graphicLayer)
addDemoGraphic10(graphicLayer)
} }
/** /**
...@@ -232,7 +233,7 @@ function addDemoGraphic7(graphicLayer) { ...@@ -232,7 +233,7 @@ function addDemoGraphic7(graphicLayer) {
positions: [ positions: [
[117.192113, 31.80998, 32.2], [117.192113, 31.80998, 32.2],
[117.228145, 31.792757, 26.7], [117.228145, 31.792757, 26.7],
[117.2717, 31.798397, 20.7] [117.261023, 31.776821, 19.8]
], ],
style: { style: {
diffHeight: 500, diffHeight: 500,
...@@ -326,6 +327,31 @@ function addDemoGraphic9(graphicLayer) { ...@@ -326,6 +327,31 @@ function addDemoGraphic9(graphicLayer) {
}) })
} }
function addDemoGraphic10() {
const primitive = new mars3d.graphic.WallEntity({
positions: [
[117.251382, 31.824055, 28.4],
[117.278989, 31.819766, 27.3],
[117.279566, 31.799699, 3.9],
[117.265249, 31.797702, 26.3],
[117.245146, 31.811783, 29]
],
style: {
closure: true,
diffHeight: 500,
material: mars3d.MaterialUtil.createMaterialProperty(mars3d.MaterialType.WallScroll, {
image: "img/textures/fence.png",
color: Cesium.Color.CHARTREUSE,
count: 3,
speed: 20,
bloom: true
})
},
attr: { remark: "示例10" }
})
graphicLayer.addGraphic(primitive)
}
// 边界墙绘制 - 数据获取 // 边界墙绘制 - 数据获取
function queryAreasData() { function queryAreasData() {
return mars3d.Util.fetchJson({ url: "//data.mars3d.cn/file/geojson/areas/340100.json" }) return mars3d.Util.fetchJson({ url: "//data.mars3d.cn/file/geojson/areas/340100.json" })
......
...@@ -98,7 +98,6 @@ function addDemoGraphic2(graphicLayer) { ...@@ -98,7 +98,6 @@ function addDemoGraphic2(graphicLayer) {
length: 4000, length: 4000,
angle: 5, // 半场角度 angle: 5, // 半场角度
material: mars3d.MaterialUtil.createMaterial(mars3d.MaterialType.CircleWave, { material: mars3d.MaterialUtil.createMaterial(mars3d.MaterialType.CircleWave, {
duration: 2000,
color: "#02ff00" color: "#02ff00"
}) })
} }
......
...@@ -164,7 +164,6 @@ function addDemoGraphic6(graphicLayer) { ...@@ -164,7 +164,6 @@ function addDemoGraphic6(graphicLayer) {
topRadius: 0.0, topRadius: 0.0,
bottomRadius: 3000, bottomRadius: 3000,
material: mars3d.MaterialUtil.createMaterial(mars3d.MaterialType.CircleWave, { material: mars3d.MaterialUtil.createMaterial(mars3d.MaterialType.CircleWave, {
duration: 2000,
color: "#02ff00" color: "#02ff00"
}) })
} }
......
...@@ -36,7 +36,12 @@ export function onMounted(mapInstance) { ...@@ -36,7 +36,12 @@ export function onMounted(mapInstance) {
addDemoGraphic6() addDemoGraphic6()
addDemoGraphic7() addDemoGraphic7()
addDemoGraphic8() addDemoGraphic8()
queryAreasData() addDemoGraphic9()
addDemoGraphic10()
mars3d.Util.fetchJson({ url: "//data.mars3d.cn/file/geojson/areas/340100.json" }).then(function (data) {
addDemoGraphic11(data)
})
} }
/** /**
...@@ -240,7 +245,8 @@ function addDemoGraphic8() { ...@@ -240,7 +245,8 @@ function addDemoGraphic8() {
image: "img/textures/fence.png", image: "img/textures/fence.png",
color: Cesium.Color.CHARTREUSE, color: Cesium.Color.CHARTREUSE,
count: 3, count: 3,
speed: 20 speed: 20,
bloom: false
}) })
}, },
attr: { remark: "示例8" } attr: { remark: "示例8" }
...@@ -248,8 +254,59 @@ function addDemoGraphic8() { ...@@ -248,8 +254,59 @@ function addDemoGraphic8() {
graphicLayer.addGraphic(primitive) graphicLayer.addGraphic(primitive)
} }
function addDemoGraphic9() {
const primitive = new mars3d.graphic.WallPrimitive({
positions: [
[117.31104, 31.821121, 14],
[117.330257, 31.823798, 9.9],
[117.334015, 31.804235, 9.8],
[117.317901, 31.802142, 14.9],
[117.312515, 31.807128, 6.2]
],
style: {
closure: true,
diffHeight: 500,
material: mars3d.MaterialUtil.createMaterial(mars3d.MaterialType.WallScroll, {
image: "img/textures/poly-san.png",
color: Cesium.Color.RED,
count: 2,
direction: 1,
speed: 20,
bloom: true
})
},
attr: { remark: "示例9" }
})
graphicLayer.addGraphic(primitive)
}
function addDemoGraphic10() {
const primitive = new mars3d.graphic.WallPrimitive({
positions: [
[117.374042, 31.838945, 11.6],
[117.392644, 31.835948, 4.7],
[117.397659, 31.820042, 8],
[117.378515, 31.810404, 2]
],
style: {
closure: true,
diffHeight: 500,
material: mars3d.MaterialUtil.createMaterial(mars3d.MaterialType.WallScroll, {
image: "img/textures/line-color3.png",
color: Cesium.Color.BLUE,
count: 5,
direction: -1,
speed: 20,
bloom: true
})
},
attr: { remark: "示例9" }
})
graphicLayer.addGraphic(primitive)
}
// 显示合肥市边界 // 显示合肥市边界
function addDemoGraphic9(data) { function addDemoGraphic11(data) {
const arr = mars3d.Util.geoJsonToGraphics(data) // 解析geojson const arr = mars3d.Util.geoJsonToGraphics(data) // 解析geojson
for (let i = 0; i < arr.length; i++) { for (let i = 0; i < arr.length; i++) {
const item = arr[i] const item = arr[i]
...@@ -272,17 +329,6 @@ function addDemoGraphic9(data) { ...@@ -272,17 +329,6 @@ function addDemoGraphic9(data) {
} }
} }
// 数据获取
function queryAreasData() {
mars3d.Util.fetchJson({ url: "//data.mars3d.cn/file/geojson/areas/340100.json" })
.then(function (data) {
addDemoGraphic9(data)
})
.catch(function (error) {
console.log("加载JSON出错", error)
})
}
// 在图层绑定Popup弹窗 // 在图层绑定Popup弹窗
export function bindLayerPopup() { export function bindLayerPopup() {
graphicLayer.bindPopup(function (event) { graphicLayer.bindPopup(function (event) {
...@@ -295,8 +341,6 @@ export function bindLayerPopup() { ...@@ -295,8 +341,6 @@ export function bindLayerPopup() {
}) })
} }
// 在图层级处理一些事物 // 在图层级处理一些事物
function bindLayerEvent() { function bindLayerEvent() {
// 在layer上绑定监听事件 // 在layer上绑定监听事件
......
...@@ -22,7 +22,19 @@ export const mapOptions = { ...@@ -22,7 +22,19 @@ export const mapOptions = {
clockAnimate: true, // 时钟动画控制(左下角) clockAnimate: true, // 时钟动画控制(左下角)
timeline: true, // 是否显示时间线控件 timeline: true, // 是否显示时间线控件
compass: { top: "10px", left: "5px" } compass: { top: "10px", left: "5px" }
},
layers: [
{
name: "夜晚图片",
icon: "img/basemaps/blackMarble.png",
type: "image",
url: "//data.mars3d.cn/file/img/world/night2.jpg",
dayAlpha: 0.1,
nightAlpha: 1.0,
brightness: 3.5,
show: true
} }
]
} }
/** /**
......
...@@ -7,6 +7,7 @@ let weixin ...@@ -7,6 +7,7 @@ let weixin
export const mapOptions = { export const mapOptions = {
scene: { scene: {
center: { lat: 12.845055, lng: 112.931363, alt: 24286797, heading: 3, pitch: -90 }, center: { lat: 12.845055, lng: 112.931363, alt: 24286797, heading: 3, pitch: -90 },
globe: { enableLighting: true },
cameraController: { cameraController: {
zoomFactor: 3.0, zoomFactor: 3.0,
minimumZoomDistance: 1000, minimumZoomDistance: 1000,
...@@ -18,7 +19,19 @@ export const mapOptions = { ...@@ -18,7 +19,19 @@ export const mapOptions = {
clockAnimate: true, // 时钟动画控制(左下角) clockAnimate: true, // 时钟动画控制(左下角)
timeline: true, // 是否显示时间线控件 timeline: true, // 是否显示时间线控件
compass: { top: "10px", left: "5px" } compass: { top: "10px", left: "5px" }
},
layers: [
{
name: "夜晚图片",
icon: "img/basemaps/blackMarble.png",
type: "image",
url: "//data.mars3d.cn/file/img/world/night2.jpg",
dayAlpha: 0.1,
nightAlpha: 1.0,
brightness: 3.5,
show: true
} }
]
} }
export const eventTarget = new mars3d.BaseClass() // 事件对象,用于抛出事件到面板中 export const eventTarget = new mars3d.BaseClass() // 事件对象,用于抛出事件到面板中
......
...@@ -23,7 +23,19 @@ export const mapOptions = { ...@@ -23,7 +23,19 @@ export const mapOptions = {
clockAnimate: true, // 时钟动画控制(左下角) clockAnimate: true, // 时钟动画控制(左下角)
timeline: true, // 是否显示时间线控件 timeline: true, // 是否显示时间线控件
compass: { top: "10px", left: "5px" } compass: { top: "10px", left: "5px" }
},
layers: [
{
name: "夜晚图片",
icon: "img/basemaps/blackMarble.png",
type: "image",
url: "//data.mars3d.cn/file/img/world/night2.jpg",
dayAlpha: 0.1,
nightAlpha: 1.0,
brightness: 3.5,
show: true
} }
]
} }
/** /**
......
...@@ -14,12 +14,25 @@ const converter = Cesium.Transforms.eastNorthUpToFixedFrame ...@@ -14,12 +14,25 @@ const converter = Cesium.Transforms.eastNorthUpToFixedFrame
// 需要覆盖config.json中地图属性参数(当前示例框架中自动处理合并) // 需要覆盖config.json中地图属性参数(当前示例框架中自动处理合并)
export const mapOptions = { export const mapOptions = {
scene: { scene: {
center: { lat: 0.072832, lng: 151.409367, alt: 29330818, heading: 10, pitch: -90 } center: { lat: 0.072832, lng: 151.409367, alt: 29330818, heading: 10, pitch: -90 },
globe: { enableLighting: true }
}, },
cameraController: { cameraController: {
maximumZoomDistance: 9000000000, maximumZoomDistance: 9000000000,
constrainedAxis: false // 解除在南北极区域鼠标操作限制 constrainedAxis: false // 解除在南北极区域鼠标操作限制
},
layers: [
{
name: "夜晚图片",
icon: "img/basemaps/blackMarble.png",
type: "image",
url: "//data.mars3d.cn/file/img/world/night2.jpg",
dayAlpha: 0.1,
nightAlpha: 1.0,
brightness: 3.5,
show: true
} }
]
} }
export const eventTarget = new mars3d.BaseClass() // 事件对象,用于抛出事件到面板中 export const eventTarget = new mars3d.BaseClass() // 事件对象,用于抛出事件到面板中
......
.gltfImg { .gltfImg {
width: 90%; width: 90%;
margin-top: 10px; margin-top: 10px;
margin-left: 10px; margin-left: 24px;
max-height: 600px; max-height: 600px;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
......
...@@ -3,7 +3,6 @@ import * as mapWork from "./map.js" ...@@ -3,7 +3,6 @@ import * as mapWork from "./map.js"
import { useState, useCallback, useEffect } from "react" import { useState, useCallback, useEffect } from "react"
import { Space, Upload } from "antd" import { Space, Upload } from "antd"
import "./index.less" import "./index.less"
function UIComponent() { function UIComponent() {
const [modelData, setmodelData] = useState([]) const [modelData, setmodelData] = useState([])
const [selectOptions, setSelectOptions] = useState([]) const [selectOptions, setSelectOptions] = useState([])
...@@ -50,12 +49,31 @@ function UIComponent() { ...@@ -50,12 +49,31 @@ function UIComponent() {
[modelData] [modelData]
) )
const props = {
name: "file",
accept: "json,geojson", // 接受文件类型
multiple: false, // 不支持多选
showUploadList: false,
beforeUpload() {
return false
},
onChange(info: any) {
const item = info.file
const fileName = item.name
const fileType = fileName?.substring(fileName.lastIndexOf(".") + 1, fileName.length).toLowerCase()
if (fileType !== "json") {
alert("文件类型不合法,请选择json格式标注文件!")
}
mapWork.openGeoJSON(item)
}
}
return ( return (
<MarsPannel visible={true} right={10} top={10} width="270"> <MarsPannel visible={true} right={10} top={10} width="270">
<MarsForm> <MarsForm>
<MarsFormItem label="模型列表"> <MarsFormItem label="模型列表">
<Space style={{ cursor: "pointer" }}> <Space style={{ cursor: "pointer" }}>
<Upload onChange={(e) => mapWork.openGeoJSON(e.file)} multiple={false} name={"file"} accept={"json,geojson"} showUploadList={false}> <Upload {...props}>
<MarsIcon icon="folder-upload" width="19"></MarsIcon> <MarsIcon icon="folder-upload" width="19"></MarsIcon>
</Upload> </Upload>
<MarsIcon onClick={() => mapWork.saveGeoJSON()} icon="disk" width="17" color="#f2f2f2"></MarsIcon> <MarsIcon onClick={() => mapWork.saveGeoJSON()} icon="disk" width="17" color="#f2f2f2"></MarsIcon>
......
...@@ -2,7 +2,7 @@ import { MarsButton, MarsCheckbox, MarsForm, MarsFormItem, MarsInput, MarsPannel ...@@ -2,7 +2,7 @@ import { MarsButton, MarsCheckbox, MarsForm, MarsFormItem, MarsInput, MarsPannel
import * as mapWork from "./map.js" import * as mapWork from "./map.js"
import { useMemo, useState, useCallback } from "react" import { useMemo, useState, useCallback } from "react"
import { Space, Upload } from "antd" import { Space, Upload } from "antd"
import { useWidget } from "@mars/common/store/widget" import { disable, activate, isActive, updateWidget } from "@mars/widgets/common/store/widget"
// *****************************属性面板***************************// // *****************************属性面板***************************//
...@@ -10,7 +10,6 @@ function UIComponent() { ...@@ -10,7 +10,6 @@ function UIComponent() {
const [isProxy, setIsProxy] = useState(false) const [isProxy, setIsProxy] = useState(false)
const [modelUrl, setModelUrl] = useState("//data.mars3d.cn/gltf/mars/feiji.glb") const [modelUrl, setModelUrl] = useState("//data.mars3d.cn/gltf/mars/feiji.glb")
const { disable, activate, isActive, setWidgetData } = useWidget()
const showEditor = useCallback( const showEditor = useCallback(
(e: any) => { (e: any) => {
...@@ -27,7 +26,7 @@ function UIComponent() { ...@@ -27,7 +26,7 @@ function UIComponent() {
}) })
// 编辑修改了模型 // 编辑修改了模型
mapWork.eventTarget.on("graphicEditor-update", async (e: any) => { mapWork.eventTarget.on("graphicEditor-update", async (e: any) => {
setWidgetData("graphic-editor", { updateWidget("graphic-editor", {
data: { graphic: e.graphic } data: { graphic: e.graphic }
}) })
showEditor(e) showEditor(e)
......
...@@ -3,7 +3,7 @@ import { Space, Upload } from "antd" ...@@ -3,7 +3,7 @@ import { Space, Upload } from "antd"
import { useEffect } from "react" import { useEffect } from "react"
import * as mapWork from "./map.js" import * as mapWork from "./map.js"
import { LocationTo } from "@mars/components/MarsSample/LocationTo" import { LocationTo } from "@mars/components/MarsSample/LocationTo"
// import { activate, disable, updateWidget, isActive } from "@mars/common/store/widgetnew" import { activate, disable, updateWidget, isActive } from "@mars/widgets/common/store/widget"
interface FileItem { interface FileItem {
uid: string uid: string
...@@ -18,38 +18,30 @@ interface FileInfo { ...@@ -18,38 +18,30 @@ interface FileInfo {
fileList: FileItem[] fileList: FileItem[]
} }
// let needOpen = true
function UIComponent() { function UIComponent() {
// useEffect(() => { useEffect(() => {
// // 编辑修改了模型 // 编辑修改了模型
// mapWork.eventTarget.on("graphicEditor-update", async (e: any) => { mapWork.eventTarget.on("graphicEditor-update", async (e: any) => {
// needOpen = true if (isActive("GraphicEditor")) {
// if (isActive("GraphicEditor")) { updateWidget("GraphicEditor", { graphic: e.graphic })
// updateWidget("GraphicEditor", { graphic: e.graphic }) } else {
// } else { activate({
// activate({ name: "GraphicEditor",
// name: "GraphicEditor", data: { graphic: e.graphic }
// data: { graphic: e.graphic } })
// }) }
// } })
// setTimeout(() => {
// needOpen = false
// }, 200)
// })
// // 停止编辑修改模型 // 停止编辑修改模型
// mapWork.eventTarget.on("graphicEditor-stop", async (e: any) => { mapWork.eventTarget.on("graphicEditor-stop", async (e: any) => {
// setTimeout(() => { setTimeout(() => {
// if (!needOpen) { if (!mapWork.graphicLayer.isEditing) {
// disable("GraphicEditor") disable("GraphicEditor")
// } else { }
// needOpen = true }, 100)
// } })
// }, 100) }, [])
// })
// }, [])
return ( return (
<> <>
......
...@@ -3,7 +3,7 @@ import { Space, Upload } from "antd" ...@@ -3,7 +3,7 @@ import { Space, Upload } from "antd"
import { useCallback, useEffect, useState } from "react" import { useCallback, useEffect, useState } from "react"
import * as mapWork from "./map.js" import * as mapWork from "./map.js"
import { LocationTo } from "@mars/components/MarsSample/LocationTo" import { LocationTo } from "@mars/components/MarsSample/LocationTo"
// import { activate, disable, updateWidget, isActive } from "@mars/common/store/widgetnew" import { activate, disable, updateWidget, isActive } from "@mars/widgets/common/store/widget"
interface FileItem { interface FileItem {
uid: string uid: string
...@@ -17,38 +17,30 @@ interface FileInfo { ...@@ -17,38 +17,30 @@ interface FileInfo {
file: FileItem file: FileItem
fileList: FileItem[] fileList: FileItem[]
} }
// let needOpen = true
function UIComponent() { function UIComponent() {
// useEffect(() => { useEffect(() => {
// // 编辑修改了模型 // 编辑修改了模型
// mapWork.eventTarget.on("graphicEditor-update", async (e: any) => { mapWork.eventTarget.on("graphicEditor-update", async (e: any) => {
// needOpen = true if (isActive("GraphicEditor")) {
// if (isActive("GraphicEditor")) { updateWidget("GraphicEditor", { graphic: e.graphic })
// updateWidget("GraphicEditor", { graphic: e.graphic }) } else {
// } else { activate({
// activate({ name: "GraphicEditor",
// name: "GraphicEditor", data: { graphic: e.graphic }
// data: { graphic: e.graphic } })
// }) }
// } })
// setTimeout(() => {
// needOpen = false
// }, 200)
// })
// // 停止编辑修改模型 // 停止编辑修改模型
// mapWork.eventTarget.on("graphicEditor-stop", async (e: any) => { mapWork.eventTarget.on("graphicEditor-stop", async (e: any) => {
// setTimeout(() => { setTimeout(() => {
// if (!needOpen) { if (!mapWork.graphicLayer.isEditing) {
// disable("GraphicEditor") disable("GraphicEditor")
// } else { }
// needOpen = true }, 100)
// } })
// }, 100) }, [])
// })
// }, [])
return ( return (
<> <>
<MarsPannel visible={true} right="10" top="10" width="345px"> <MarsPannel visible={true} right="10" top="10" width="345px">
......
import { MarsCheckbox, MarsPannel } from "@mars/components/MarsUI"
import * as mapWork from "./map.js"
function UIComponent() {
return (
<>
<MarsPannel visible={true} right={10} top={10} height="45">
<MarsCheckbox onChange={(e) => mapWork.chkUnderground(e.target.checked)}>是否动态</MarsCheckbox>
</MarsPannel>
<div style={{ position: "absolute", bottom: "40px", right: "20px" }}>
<img style={{ height: "200px" }} src="/img/legend/heatmap.png" alt="" />
</div>
</>
)
}
export default UIComponent
import * as mars3d from "mars3d"
export let map // mars3d.Map三维地图对象
let heatLayer
// 需要覆盖config.json中地图属性参数(当前示例框架中自动处理合并)
export const mapOptions = {
scene: {
center: { lat: 31.823087, lng: 117.236208, alt: 2383, heading: 3, pitch: -61 }
}
}
/**
* 初始化地图业务,生命周期钩子函数(必须)
* 框架在地图初始化完成后自动调用该函数
* @param {mars3d.Map} mapInstance 地图对象
* @returns {void} 无
*/
export function onMounted(mapInstance) {
map = mapInstance // 记录map
map.basemap = 2017 // 蓝色底图
showHeatMap()
}
/**
* 释放当前地图业务的生命周期函数
* @returns {void} 无
*/
export function onUnmounted() {
map = null
}
function showHeatMap() {
// 随机数据的生成
const heatMapData0 = getRandomPoints()
const heatMapData1 = getRandomPoints()
const resultHeatMapData = getRandomPoints()
// 热力图 图层
heatLayer = new mars3d.layer.HeatLayer({
positions: heatMapData0,
rectangle: rectangle,
// 以下为热力图本身的样式参数,可参阅api:https://www.patrick-wied.at/static/heatmapjs/docs.html
heatStyle: {
radius: 40,
blur: 0.85
},
// 以下为矩形矢量对象的样式参数
style: {
// arc: true, // 是否为曲面
height: 200.0
}
})
map.addLayer(heatLayer)
// 为了演示动态更新
let ratio = 0
map.on(mars3d.EventType.preUpdate, (e) => {
if (!isDynamic) {
return
}
ratio += 0.003
if (ratio > 1.0) {
ratio = 0.0
}
const gridData = new Array(100 * 100)
gridData.fill(0)
lerpHeatMapData(heatMapData0, heatMapData1, ratio, resultHeatMapData)
// 更新数据
heatLayer.setPositions(resultHeatMapData, true)
})
}
let isDynamic = true
export function chkUnderground(enabled) {
isDynamic = enabled
}
const rectangle = {
xmin: 117.226189,
xmax: 117.245831,
ymin: 31.828858,
ymax: 31.842967
}
const heatCount = 1000
// 获取bbox矩形区域内的count个随机点
function getRandomPoints() {
const arr = []
const arrPoint = turf.randomPoint(heatCount, { bbox: [rectangle.xmin, rectangle.ymin, rectangle.xmax, rectangle.ymax] }).features // 随机点
for (let i = 0; i < arrPoint.length; i++) {
const item = arrPoint[i].geometry.coordinates
const val = Math.floor(Math.random() * 100) // 热力值
arr.push({ lng: item[0], lat: item[1], value: val })
}
return arr
}
function lerpHeatMapData(startArr, endArr, ratio, result) {
for (let i = 0; i < heatCount; i++) {
const start = startArr[i]
const end = endArr[i]
result[i] = {
lng: start.lng * (1 - ratio) + end.lng * ratio,
lat: start.lat * (1 - ratio) + end.lat * ratio,
value: start.value * (1 - ratio) + end.value * ratio
}
}
}
...@@ -41,6 +41,7 @@ function showHeatMap(arrPoints, height) { ...@@ -41,6 +41,7 @@ function showHeatMap(arrPoints, height) {
// 热力图 图层 // 热力图 图层
heatLayer = new mars3d.layer.HeatLayer({ heatLayer = new mars3d.layer.HeatLayer({
positions: arrPoints, positions: arrPoints,
rectangle: rectangle,
// 以下为热力图本身的样式参数,可参阅api:https://www.patrick-wied.at/static/heatmapjs/docs.html // 以下为热力图本身的样式参数,可参阅api:https://www.patrick-wied.at/static/heatmapjs/docs.html
heatStyle: { heatStyle: {
radius: 40, radius: 40,
...@@ -56,17 +57,22 @@ function showHeatMap(arrPoints, height) { ...@@ -56,17 +57,22 @@ function showHeatMap(arrPoints, height) {
// 更新数据 // 更新数据
export function btnUpdate() { export function btnUpdate() {
heatLayer.positions = getRandomPoints(1000) const arr = getRandomPoints(1000)
heatLayer.setPositions(arr, true)
}
const rectangle = {
xmin: 117.226189,
xmax: 117.245831,
ymin: 31.828858,
ymax: 31.842967
} }
// 获取bbox矩形区域内的count个随机点 // 获取bbox矩形区域内的count个随机点
function getRandomPoints(count) { function getRandomPoints(count) {
const xmin = 117.226189
const xmax = 117.245831
const ymin = 31.828858
const ymax = 31.842967
const arr = [] const arr = []
const arrPoint = turf.randomPoint(count, { bbox: [xmin, ymin, xmax, ymax] }).features // 随机点 const arrPoint = turf.randomPoint(count, { bbox: [rectangle.xmin, rectangle.ymin, rectangle.xmax, rectangle.ymax] }).features // 随机点
for (let i = 0; i < arrPoint.length; i++) { for (let i = 0; i < arrPoint.length; i++) {
const item = arrPoint[i].geometry.coordinates const item = arrPoint[i].geometry.coordinates
const val = Math.floor(Math.random() * 100) // 热力值 const val = Math.floor(Math.random() * 100) // 热力值
......
...@@ -20,7 +20,10 @@ export const mapOptions = { ...@@ -20,7 +20,10 @@ export const mapOptions = {
name: "夜晚图片", name: "夜晚图片",
icon: "img/basemaps/blackMarble.png", icon: "img/basemaps/blackMarble.png",
type: "image", type: "image",
url: "//data.mars3d.cn/file/img/world/night.jpg" url: "//data.mars3d.cn/file/img/world/night.jpg",
dayAlpha: 0.1,
nightAlpha: 1.0,
brightness: 3.5
}, },
{ {
name: "蓝色底图", name: "蓝色底图",
......
...@@ -2,7 +2,7 @@ import { MarsButton, MarsPannel, MarsRadio, MarsRadioGroup } from "@mars/compone ...@@ -2,7 +2,7 @@ import { MarsButton, MarsPannel, MarsRadio, MarsRadioGroup } from "@mars/compone
import * as mapWork from "./map.js" import * as mapWork from "./map.js"
import { Space, Upload } from "antd" import { Space, Upload } from "antd"
import { useCallback, useMemo } from "react" import { useCallback, useMemo } from "react"
import { useWidget } from "@mars/common/store/widget" import { disable, activate } from "@mars/widgets/common/store/widget"
interface FileItem { interface FileItem {
uid: string uid: string
...@@ -37,7 +37,6 @@ const openGeoJSON = (info: FileInfo) => { ...@@ -37,7 +37,6 @@ const openGeoJSON = (info: FileInfo) => {
} }
function UIComponent() { function UIComponent() {
const { disable, activate } = useWidget()
const showEditor = useCallback( const showEditor = useCallback(
(e: any) => { (e: any) => {
......
...@@ -91,7 +91,9 @@ function UIComponent() { ...@@ -91,7 +91,9 @@ function UIComponent() {
键盘漫游 键盘漫游
</MarsCheckbox> </MarsCheckbox>
<span className="mars-pannel-item-label">调试页面:</span> <span className="mars-pannel-item-label">调试页面:</span>
<MarsButton href="editor-react.html?id=layer-tileset/manager/edit">模型参数调试</MarsButton> <MarsButton href="editor-react.html?id=layer-tileset/manager/edit" target="_blank">
模型参数调试
</MarsButton>
</MarsCollapsePanel> </MarsCollapsePanel>
</MarsCollapse> </MarsCollapse>
</MarsPannel> </MarsPannel>
......
...@@ -44,7 +44,7 @@ const selectWayOptions = [ ...@@ -44,7 +44,7 @@ const selectWayOptions = [
} }
] ]
function UIComponent(props) { function UIComponent() {
const [startNumber, setStartValue] = useState("") const [startNumber, setStartValue] = useState("")
const [countNumber, setEndtValue] = useState(0) const [countNumber, setEndtValue] = useState(0)
const [seltValue, setselctValue] = useState("1") // 出行方式 const [seltValue, setselctValue] = useState("1") // 出行方式
......
...@@ -3,8 +3,9 @@ import { createRoot } from "react-dom/client" ...@@ -3,8 +3,9 @@ import { createRoot } from "react-dom/client"
import { getQueryString } from "@mars/utils/mars-util" import { getQueryString } from "@mars/utils/mars-util"
import MarsUIInstall from "@mars/components/MarsUI" import MarsUIInstall from "@mars/components/MarsUI"
import MainOperation from "@mars/components/MarsWork/MainOperation" import MainOperation from "@mars/components/MarsWork/MainOperation"
import { generateWidgetView } from "@mars/widgets/common/store/widget"
import { Editor as MarsgisEditor } from "@marsgis/editor" import { Editor as MarsgisEditor } from "@marsgis/editor"
import widgetState from "@mars/widgets/widget-state"
import "@mars/assets/style/index.less" import "@mars/assets/style/index.less"
import "@marsgis/editor/dist/style.css" import "@marsgis/editor/dist/style.css"
...@@ -34,17 +35,21 @@ marsEditor.on("loaded", (exampleConfig) => { ...@@ -34,17 +35,21 @@ marsEditor.on("loaded", (exampleConfig) => {
inited = true inited = true
}) })
const WidgetView = generateWidgetView(widgetState)
function initUI(simple: boolean) { function initUI(simple: boolean) {
reactApp = createRoot(document.getElementById("mars-main-view")) reactApp = createRoot(document.getElementById("mars-main-view"))
if (simple) { if (simple) {
reactApp.render(<div></div>) reactApp.render(<div></div>)
} else { } else {
reactApp.render( reactApp.render(
<WidgetView>
<MainOperation <MainOperation
beforeMounted={() => { beforeMounted={() => {
marsEditor.useLifecycle() marsEditor.useLifecycle()
}} }}
></MainOperation> ></MainOperation>
</WidgetView>
) )
} }
} }
......
import {
MarsCollapse,
MarsCollapsePanel,
MarsInput,
MarsInputNumber,
MarsSwitch,
MarsSlider,
MarsColor,
MarsTextArea,
MarsSelect
} from "@mars/components/MarsUI"
import { isBoolean, isNumber } from "lodash"
import { useMemo } from "react"
const components = {
number: MarsInputNumber,
radio: MarsSwitch,
slider: MarsSlider,
color: MarsColor,
combobox: MarsSelect,
textarea: MarsTextArea,
label: "span",
text: MarsInput
}
function AttrItem({ type, ...props }) {
const Component = components[type]
return <Component {...props}></Component>
}
interface MarsAttrProps {
attrs: any
onChange?: (value?: any) => void
}
export default function MarsAttr({ attrs, onChange = () => {} }: MarsAttrProps) {
const attrComps = useMemo(() => {
const ac: any[] = Object.keys(attrs)
.filter((k) => !["id", "name", "remark"].includes(k))
.map((k) => {
let type = "text"
if (isBoolean(attrs[k])) {
type = "radio"
}
if (isNumber(attrs[k])) {
type = "number"
}
return { name: k, label: k, type }
})
console.log("ac", ac)
return [
{ name: "id", label: "主键", type: "label", defval: "" },
{ name: "name", label: "名称", type: "text", defval: "" },
{ name: "remark", label: "备注", type: "textarea", defval: "" }
].concat(ac)
}, [attrs])
return (
<MarsCollapse activeKey={["1"]}>
<MarsCollapsePanel key="1" showArrow={false} header="属性信息">
<table className="mars-primary-table">
<tbody>
{attrComps.map((item, i) => (
<tr key={i}>
<td>{item.label}</td>
<td>
{item.type === "lable" ? (
attrs[item.name]
) : (
<AttrItem
type={item.type}
value={attrs[item.name]}
onChange={(data) => {
onChange({
[item.name]: data.target ? data.target.value : data
})
}}
></AttrItem>
)}
</td>
</tr>
))}
</tbody>
</table>
</MarsCollapsePanel>
</MarsCollapse>
)
}
import { MarsCollapse, MarsCollapsePanel, MarsIcon, MarsInputNumber } from "@mars/components/MarsUI"
import { Space } from "antd"
import { Fragment, useCallback, useEffect, useRef } from "react"
import { cloneDeep } from "lodash"
interface MarsAttrProps {
positions: any
onChange?: (value?: any) => void
graphic: any
}
function PointPosition({ value = [], onChange }) {
const values = useRef(value)
useEffect(() => {
values.current = value
}, [value])
const itemChange = useCallback(
(v, i) => {
values.current[i] = v
onChange && onChange(values.current)
},
[values, onChange]
)
return (
<table className="mars-primary-table">
<tbody>
<tr>
<td width="80">经度</td>
<td>
<MarsInputNumber size="small" value={value[0]} step="0.000001" onChange={(value) => itemChange(value, 0)}></MarsInputNumber>
</td>
</tr>
<tr>
<td>纬度</td>
<td>
<MarsInputNumber size="small" value={value[1]} step="0.000001" onChange={(value) => itemChange(value, 1)}></MarsInputNumber>
</td>
</tr>
<tr>
<td>高程</td>
<td>
<MarsInputNumber size="small" value={value[2]} step="0.1" onChange={(value) => itemChange(value, 2)}></MarsInputNumber>
</td>
</tr>
</tbody>
</table>
)
}
export default function MarsPosition({ positions, graphic, onChange = () => {} }: MarsAttrProps) {
const minNum = getMinPointNum(graphic)
const maxNum = getMaxPointNum(graphic)
const pointChange = useCallback((value, i) => {
positions[i] = value
onChange(positions)
}, [])
return (
<MarsCollapse activeKey={["1", "2"]}>
<MarsCollapsePanel key="1" showArrow={false} header="属性信息">
<table className="mars-primary-table">
<tbody>
<tr>
<td width="100">在原值上增加</td>
<td>
<MarsInputNumber
size="small"
step="1"
onChange={(value) => {
onChange(
positions.map((p) => {
p[2] = p[2] + value
return p
})
)
}}
></MarsInputNumber>
</td>
</tr>
<tr>
<td>全部修改为</td>
<td>
<MarsInputNumber
size="small"
step="1"
onChange={(value) => {
onChange(
positions.map((p) => {
p[2] = value
return p
})
)
}}
></MarsInputNumber>
</td>
</tr>
</tbody>
</table>
</MarsCollapsePanel>
<MarsCollapsePanel key="2" showArrow={false} header="坐标列表">
{positions.map((item, i) => (
<Fragment key={i}>
<div className="position-title">
<span>{i + 1}</span>
<Space className="position-title__subfix">
{positions.length < maxNum && (
<MarsIcon
icon="add-one"
width="16"
onClick={() => {
const lonlats = cloneDeep(positions)
lonlats.splice(i, 0, cloneDeep(item))
onChange(lonlats)
}}
></MarsIcon>
)}
{positions.length > minNum && (
<MarsIcon
icon="delete"
width="16"
onClick={() => {
const lonlats = cloneDeep(positions)
lonlats.splice(i, 1)
onChange(lonlats)
}}
></MarsIcon>
)}
</Space>
</div>
<PointPosition value={item} onChange={(value) => pointChange(value, i)}></PointPosition>
</Fragment>
))}
</MarsCollapsePanel>
</MarsCollapse>
)
}
function getMaxPointNum(gp: any): number {
if (gp && gp._maxPointNum) {
return gp._maxPointNum
}
return 999
}
function getMinPointNum(gp: any): number {
if (gp && gp._minPointNum) {
return gp._minPointNum
}
return 3
}
import {
MarsCollapse,
MarsCollapsePanel,
MarsInput,
MarsInputNumber,
MarsSwitch,
MarsSlider,
MarsColor,
MarsTextArea,
MarsSelect,
$message
} from "@mars/components/MarsUI"
import styleConfig from "./attr.json"
import { useCallback, useEffect, useMemo, useState } from "react"
import { cloneDeep, uniq, isArray } from "lodash"
const components = {
number: MarsInputNumber,
radio: MarsSwitch,
slider: MarsSlider,
color: MarsColor,
combobox: MarsSelect,
textarea: MarsTextArea,
label: "span",
text: MarsInput
}
function StyleItem({ type, ...props }) {
const Component = components[type]
return <Component {...props}></Component>
}
interface MarsAttrProps {
style: any
graphic: any
onChange?: (value?: any) => void
}
export default function MarsStyle({ style, graphic, onChange = () => {} }: MarsAttrProps) {
const styleOptions = useMemo(() => {
const defaultOption = styleConfig[graphic.options.edittype || graphic.type] || {}
return defaultOption
}, [graphic])
const innerStyle = useMemo(() => {
const newStyle = cloneDeep(style)
styleOptions.style.forEach((item: any) => {
if (!newStyle[item.name] && newStyle[item.name] !== 0 && newStyle[item.name] !== false) {
newStyle[item.name] = item.defval
}
})
return newStyle
}, [style, styleOptions])
const showImpacts = useMemo(() => {
let allImpacts: any[] = []
if (styleOptions.style) {
styleOptions.style.forEach((item: any) => {
if (item.impact && innerStyle[item.name] === true) {
allImpacts = allImpacts.concat(item.impact)
}
if (item.data && isArray(item.data)) {
item.data.forEach((op: any) => {
if (op.impact && innerStyle[item.name] === op.value) {
allImpacts = allImpacts.concat(op.impact)
}
})
}
})
}
return allImpacts
}, [styleOptions, innerStyle])
const styleShowIt = useCallback(
(item: any) => {
if (item.type === "hidden") {
return false
}
if (item.isImpact && !showImpacts.includes(item.name)) {
return false
}
const attrName = item.name
// 三维立体对象
if (innerStyle.diffHeight > 0) {
if (attrName === "clampToGround" || attrName === "outlineWidth") {
return false
}
}
return true
},
[showImpacts, innerStyle]
)
const updateStyle = useCallback(
(item: any, value: any) => {
innerStyle[item.name] = value
onChange(innerStyle)
},
[innerStyle, onChange]
)
const unionChange = useCallback(
(item: any, value: any) => {
if (value === false && ((item.name === "fill" && innerStyle.outline === false) || (item.name === "outline" && innerStyle.fill === false))) {
$message("填充和边框不能同时为否")
return
}
updateStyle(item, value)
},
[innerStyle, updateStyle]
)
return (
<MarsCollapse activeKey={["1"]}>
<MarsCollapsePanel key="1" showArrow={false} header="属性信息">
<table className="mars-primary-table">
<tbody>
<tr>
<td width={80}>所在图层</td>
<td>{graphic._layer.name || "默认分组"}</td>
</tr>
<tr>
<td>标号类型</td>
<td>{graphic.name || styleOptions.name}</td>
</tr>
{styleOptions.style
.filter((item) => styleShowIt(item))
.map((item, i) => (
<tr key={i}>
<td>{item.label}</td>
<td>
{item.type === "lable"
? innerStyle[item.name]
: item.type !== "hidden" && (
<StyleItem
type={item.type}
value={innerStyle[item.name]}
min={item.min || item.min === 0 ? item.min : -Infinity}
max={item.max || item.max === 0 ? item.max : Infinity}
step={item.step || 0.1}
options={item.data || []}
onChange={(e) => {
unionChange(item, e.target ? e.target.value : e)
}}
></StyleItem>
)}
</td>
</tr>
))}
</tbody>
</table>
</MarsCollapsePanel>
</MarsCollapse>
)
}
.top-handle-bar {
border-bottom: 1px solid #cde1de;
padding: 5px 0 2px 0;
}
.attr-editor-main {
height: calc(100% - 40px);
overflow-y: auto;
* {
font-size: 12px;
}
.mars-input-number,
.mars-select {
width: 100%;
}
}
.position-title {
border-left: 2px solid #ffffff;
background-color: rgba(32, 42, 68, 0.5);
padding-left: 5px;
padding-right: 5px;
padding-top: 5px;
margin-top: 5px;
margin-bottom: 5px;
.position-title__subfix {
float: right;
.mars-icon {
cursor: pointer;
}
}
}
import { MarsDialog, MarsIcon, MarsTabs, MarsTabPane } from "@mars/components/MarsUI"
import { Space } from "antd"
import * as mars3d from "mars3d"
import { useCallback, useEffect, useState } from "react"
import MarsPosition from "./MarsPosition"
import MarsStyle from "./MarsStyle"
import MarsAttr from "./MarsAttr"
import _ from "lodash"
import "./index.less"
function GraphicEditor({ currentWidget, ...props }) {
const [graphic, setGraphic] = useState(null)
const [style, setStyle] = useState(null)
const [positions, setPositions] = useState(null)
const [attrs, setAttrs] = useState(null)
useEffect(() => {
console.log("编辑面板接收到了graphic对象更新:", currentWidget)
const gp = currentWidget.data.graphic
setGraphic(gp)
setStyle(_.cloneDeep(gp.style))
setPositions(_.cloneDeep(gp.coordinates))
setAttrs(_.cloneDeep(gp.attr))
}, [currentWidget])
const [acTab, setAcTab] = useState("style")
const tabChange = useCallback((key: string) => {
setAcTab(key)
}, [])
return (
<MarsDialog
title="属性编辑"
width="260"
top="60"
bottom="40"
left="10"
minWidth={200}
{...props}
footer={
<MarsTabs tabPosition="bottom" activeKey={acTab} type="card" onTabClick={tabChange}>
<MarsTabPane key="attr" tab="属性"></MarsTabPane>
<MarsTabPane key="coord" tab="坐标"></MarsTabPane>
<MarsTabPane key="style" tab="样式"></MarsTabPane>
</MarsTabs>
}
>
{graphic && (
<>
<div className="top-handle-bar">
<Space>
<MarsIcon icon="send" width="20" click="flyToGraphic" title="飞行定位" onClick={() => graphic.flyTo()}></MarsIcon>
<MarsIcon icon="delete" width="20" click="deleteEntity" title="删除" onClick={() => graphic.remove()}></MarsIcon>
<MarsIcon
icon="save"
width="20"
click="getGeoJson"
title="导出geojson"
onClick={() => {
// 文件处理
const geojson = graphic.toGeoJSON()
geojson.properties._layer = graphic._layer.name
mars3d.Util.downloadFile("标绘item.json", JSON.stringify(geojson))
}}
></MarsIcon>
</Space>
</div>
<div className="attr-editor-main">
{acTab === "attr" && (
<MarsAttr
attrs={attrs}
onChange={(data) => {
console.log("更新属性:", data)
graphic.attr = data
}}
></MarsAttr>
)}
{acTab === "coord" && (
<MarsPosition
positions={positions}
graphic={graphic}
onChange={(data) => {
console.log("更新positions:", data)
graphic.positions = data
setPositions(_.cloneDeep(data))
}}
></MarsPosition>
)}
{acTab === "style" && (
<MarsStyle
style={style}
graphic={graphic}
onChange={(data) => {
console.log("更新style:", data)
graphic.setStyle(data)
setStyle(_.cloneDeep(data))
}}
></MarsStyle>
)}
</div>
</>
)}
</MarsDialog>
)
}
export default GraphicEditor
declare module "@mars/widgets/common/store/widget" {
// 为 store state 声明类型
export interface DefaultOption {
autoDisable?: boolean
disableOther?: boolean | string[]
group?: string // group相同的widget一定是互斥的
meta?: any // 额外参数 不会在每次关闭后清除
}
export interface Widget {
name: string // 唯一标识
key?: string // 作为组件 diff 环节的key,用于控制组件重载
component?: any // widget关联的异步组件
autoDisable?: boolean // 是否能够被自动关闭
disableOther?: boolean | string[] // 是否自动关闭其他widget,或通过数组指定需要被关闭的widget
group?: string // group相同的widget一定是互斥的
visible?: boolean // 显示隐藏
data?: any // 额外传参 会在每次关闭后清除
meta?: any // 额外参数 不会在每次关闭后清除
}
export interface WidgetState {
widgets?: Widget[]
openAtStart?: string[]
defaultOption?: DefaultOption
}
export const connectWidget: (ele) => any
export const disable: (widget: string | string[]) => any
export const activate: (widget: Widget | string, reload?: boolean) => any
export const disableAll: (force?: boolean) => any
export const updateWidget: (widget: string, data: any) => void
export const isActive: (widget: string) => any
export const WidgetView: (state: WidgetState) => any
export const generateWidgetView: (options: WidgetState) => any
}
/**
* 该文件开源版本中 暂未开放源码,但可以免费无限制使用。
* 【仅此1个文件是未开源的,接口见 widget.d.ts 】
*
* 如果需要完整代码,可以访问了解更多:http://mars3d.cn/details.html?id=jcxm-react
*
* 编译日期:2022-5-22
* 版权所有:Copyright by 火星科技 http://mars3d.cn
*/
var __defProp=Object.defineProperty,__defProps=Object.defineProperties,__getOwnPropDescs=Object.getOwnPropertyDescriptors,__getOwnPropSymbols=Object.getOwnPropertySymbols,__hasOwnProp=Object.prototype.hasOwnProperty,__propIsEnum=Object.prototype.propertyIsEnumerable,__defNormalProp=(e,t,r)=>t in e?__defProp(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,__spreadValues=(e,t)=>{for(var r in t||(t={}))__hasOwnProp.call(t,r)&&__defNormalProp(e,r,t[r]);if(__getOwnPropSymbols)for(var r of __getOwnPropSymbols(t))__propIsEnum.call(t,r)&&__defNormalProp(e,r,t[r]);return e},__spreadProps=(e,t)=>__defProps(e,__getOwnPropDescs(t));!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react"),require("uuid"),require("redux"),require("react-redux")):"function"==typeof define&&define.amd?define(["exports","react","uuid","redux","react-redux"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).widget={},e.require$$0,e.uuid,e.redux,e.reactRedux)}(this,(function(e,t,r,a,s){"use strict";function i(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var o={exports:{}},d={},n=i(t).default,l=Symbol.for("react.element"),p=Symbol.for("react.fragment"),u=Object.prototype.hasOwnProperty,_=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,c={key:!0,ref:!0,__self:!0,__source:!0};function f(e,t,r){var a,s={},i=null,o=null;for(a in void 0!==r&&(i=""+r),void 0!==t.key&&(i=""+t.key),void 0!==t.ref&&(o=t.ref),t)u.call(t,a)&&!c.hasOwnProperty(a)&&(s[a]=t[a]);if(e&&e.defaultProps)for(a in t=e.defaultProps)void 0===s[a]&&(s[a]=t[a]);return{$$typeof:l,type:e,key:i,ref:o,props:s,_owner:_.current}}d.Fragment=p,d.jsx=f,d.jsxs=f,o.exports=d;const g=o.exports.jsx,b=o.exports.jsxs,w=o.exports.Fragment,m=e=>{let t={};return e.meta&&e.meta.props&&(t=__spreadValues(__spreadValues({},t),e.meta.props)),e.data&&e.data.props&&(t=__spreadValues(__spreadValues({},t),e.data.props)),t};let y=null;const v=e=>{y.dispatch({type:"disable",widget:e})},O=s.connect((e=>({widgets:e.widgets})))((e=>(console.log("数据更新"),g(w,{children:e.widgets.filter((e=>e.visible)).map((e=>{const r=e.component;return g(t.Suspense,{fallback:g("div",{}),children:g(r,__spreadProps(__spreadValues({},m(e)),{visible:e.visible,onClose:()=>v(e.name),currentWidget:e}))},e.key)}))}))));e.WidgetView=O,e.activate=(e,t=!0)=>{y.dispatch({type:"activate",widget:e,reload:t})},e.connectWidget=e=>s.connect((e=>({widgets:e.widgets})))(e),e.disable=v,e.disableAll=(e=!1)=>{y.dispatch({type:"disableAll",force:e})},e.generateWidgetView=e=>{if(!e)throw new Error("generateWidgetView参数不能为空");const t=__spreadValues({autoDisable:!0,disableOther:!1},e.defaultOption),i=e.openAtStart||[],o=e.widgets.map((e=>__spreadProps(__spreadValues(__spreadValues({visible:i.includes(e.name)},t),e),{meta:__spreadValues(__spreadValues({},t.meta),e.meta),key:r.v4()})));return y=a.createStore((function(e={widgets:o},t){switch(t.type){case"disable":{const r=e.widgets;let a=t.widget;return"string"==typeof a&&(a=[a]),{widgets:r.map((e=>(-1!==a.indexOf(e.name)&&(delete e.data,e.visible=!1),e)))}}case"activate":{const a=e.widgets,{widget:s,reload:i}=t,o="string"==typeof s?s:s.name,d=a.find((e=>e.name===o));return d?{widgets:a.map((e=>(e.name===o?(e.visible&&i&&(e.key=r.v4()),"object"==typeof s&&null!==s&&s.data&&(e.data=s.data),e.visible=!0):(d.group&&e.group===d.group&&(e.visible=!1),Array.isArray(d.disableOther)&&d.disableOther.includes(e.name)&&(e.visible=!1),!0===d.disableOther&&!0===e.autoDisable&&(e.visible=!1)),e)))}:(console.log("widget不存在",s),e)}case"disableAll":{const{force:r}=t;return{widgets:e.widgets.map((e=>(e.visible&&(r||e.autoDisable)&&(e.visible=!1),e)))}}case"update":{const{widget:r,data:a}=t;return{widgets:e.widgets.map((e=>-1!==r.indexOf(e.name)?__spreadProps(__spreadValues({},e),{data:a}):e))}}default:return e}})),({children:e})=>b(s.Provider,{store:y,children:[g(O,{}),e]})},e.isActive=e=>{const t=(y.getState().widgets||[]).find((t=>t.name===e));return t&&t.visible},e.updateWidget=(e,t)=>{y.dispatch({type:"update",widget:e,data:t})},Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
import { useEffect, useMemo } from "react"
export function useLifecycle(mapWork: any) {
const mapInstance = window._mapInstance
useMemo(() => {
if (mapWork.onMounted) {
mapWork.onMounted(mapInstance)
}
}, [])
useEffect(
() => () => {
if (mapWork.onUnmounted) {
mapWork.onUnmounted()
}
},
[]
)
}
import type { WidgetState } from "@mars/widgets/common/store/widget"
import { lazy } from "react"
const widgetState: WidgetState = {
widgets: [
{
component: lazy(() => import("@mars/widgets/basic/GraphicEditor")),
name: "GraphicEditor"
}
],
openAtStart: []
}
export default widgetState
...@@ -37,7 +37,7 @@ export default ({ mode }: ConfigEnv) => { ...@@ -37,7 +37,7 @@ export default ({ mode }: ConfigEnv) => {
extensions: [".js", ".ts", ".jsx", ".tsx", ".json"] extensions: [".js", ".ts", ".jsx", ".tsx", ".json"]
}, },
optimizeDeps: { optimizeDeps: {
include: ["mars3d"] include: ["mars3d", "@mars/widgets/common/store/widget"]
}, },
json: { json: {
// 支持从 .json 文件中进行按名导入 // 支持从 .json 文件中进行按名导入
...@@ -74,6 +74,11 @@ export default ({ mode }: ConfigEnv) => { ...@@ -74,6 +74,11 @@ export default ({ mode }: ConfigEnv) => {
input: { input: {
index: path.resolve(__dirname, "index.html"), index: path.resolve(__dirname, "index.html"),
editor: path.resolve(__dirname, "editor-react.html") editor: path.resolve(__dirname, "editor-react.html")
},
output: {
entryFileNames: `example/assets-react/[name].js`,
chunkFileNames: `example/assets-react/[name].js`,
assetFileNames: `example/assets-react/[name].[ext]`
} }
}, },
// 当设置为 true, 构建后将会生成 manifest.json 文件 // 当设置为 true, 构建后将会生成 manifest.json 文件
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论