Browse Source

点位根据高度确定颜色;添加高度筛选功能。

任一存 1 year ago
parent
commit
c36cdb4d6c
2 changed files with 121 additions and 55 deletions
  1. 4 21
      README.md
  2. 117 34
      src/App.vue

+ 4 - 21
README.md

@@ -1,24 +1,7 @@
-# app
+添加选项:选择高度范围。默认同时显示全部高度的。
 
-## Project setup
-```
-yarn install
-```
+已有的点:根据高度设置颜色,红至黑。(rgb)
 
-### Compiles and hot-reloads for development
-```
-yarn serve
-```
+画框补点。新补的点颜色半透明,高度:可以设置高度。如果没有设置高度,周围点又没有重叠的且高度差距不超过1m,则直接插值;如果周围点没有重叠的且高度差距超过1m,则插值并警告;如果周围点有重叠的则强制设置高度。
 
-### Compiles and minifies for production
-```
-yarn build
-```
-
-### Lints and fixes files
-```
-yarn lint
-```
-
-### Customize configuration
-See [Configuration Reference](https://cli.vuejs.org/config/).
+补点要有撤销、保存功能。

+ 117 - 34
src/App.vue

@@ -5,7 +5,10 @@
       label-position="left"
     >
       <el-form-item label="场景名或完整url">
-        <el-input v-model="sceneNameOrUrl" />
+        <el-input
+          v-model="sceneNameOrUrl"
+          autofocus
+        />
       </el-form-item>
       <el-button
         type="primary"
@@ -35,17 +38,17 @@
         显示路径
       </el-button>
       <el-button @click="onResetPath">
-        Reset
+        清空
       </el-button>
     </el-form>
     <el-form
       class="form3"
       label-position="top"
     >
-      <el-form-item label="起点坐标(以英文逗号分隔)(色小圆圈表示)">
+      <el-form-item label="起点坐标(以英文逗号分隔)(浅绿色小圆圈表示)">
         <el-input v-model="formData.startPoint" />
       </el-form-item>
-      <el-form-item label="终点坐标(以英文逗号分隔)(绿色小圆圈表示)">
+      <el-form-item label="终点坐标(以英文逗号分隔)(绿色小圆圈表示)">
         <el-input v-model="formData.endPoint" />
       </el-form-item>
       <el-button
@@ -55,7 +58,7 @@
         显示起点终点
       </el-button>
       <el-button @click="onResetStartEndPoint">
-        Reset
+        清空
       </el-button>
     </el-form>
   </div>
@@ -65,27 +68,63 @@
   </div>
   <div class="map">
     <div class="svgWrapper" />
-    <div class="button-group">
-      <el-button
-        class="btn"
-        type="primary"
-        @click="zoomInToStartPoint"
+    <div class="map-control-area">
+      <div class="zoom-control panel">
+        聚焦操作
+        <el-button
+          class="btn"
+          type="primary"
+          @click="zoomInToStartPoint"
+        >
+          聚焦到起点
+        </el-button>
+        <el-button
+          class="btn"
+          type="primary"
+          @click="zoomInToEndPoint"
+        >
+          聚焦到终点
+        </el-button>
+        <el-button
+          class="btn"
+          @click="resetZoom"
+        >
+          取消聚焦
+        </el-button>
+      </div>
+      <el-form
+        class="height-filter panel"
+        label-position="top"
       >
-        zoom in到起点
-      </el-button>
-      <el-button
-        class="btn"
-        type="primary"
-        @click="zoomInToEndPoint"
-      >
-        zoom in到终点
-      </el-button>
-      <el-button
-        clas="btn"
-        @click="resetZoom"
-      >
-        reset zoom
-      </el-button>
+        高度筛选
+        <el-form-item
+          :label="`高度上限`"
+        >
+          <el-input
+            v-model="formData.maxHeight"
+            type="number"
+          />
+        </el-form-item>
+        <el-form-item
+          :label="`高度下限`"
+        >
+          <el-input
+            v-model="formData.minHeight"
+            type="number"
+          />
+        </el-form-item>
+        <div class="btn-group">
+          <el-button
+            type="primary"
+            @click="onSetHeightFilter"
+          >
+            确定
+          </el-button>
+          <el-button @click="onResetHeightFilter">
+            清空
+          </el-button>
+        </div>
+      </el-form>
     </div>
   </div>
 </template>
@@ -100,7 +139,7 @@ const LENGTH_PER_POINT = 0.36
 // 视口尺寸
 let svgWidth = document.documentElement.clientWidth - 200
 let svgHeight = document.documentElement.clientHeight - 280
-let viewportRatio = svgWidth / svgHeight
+let svgRatio = svgWidth / svgHeight
 
 let pxPerUnitLength = 0 // 原始单位长度对应的像素数
 let rawWholeData = []
@@ -130,7 +169,7 @@ export default {
   name: 'App',
   data() {
     return {
-      sceneNameOrUrl: 'SS-t-XkquhxxurM',
+      sceneNameOrUrl: 'SS-t-NZUICC2fRLi',
       infoText: '',
       loadingHandler: null,
       formData: {
@@ -138,6 +177,8 @@ export default {
         path2: '',
         startPoint: '-38.5, 10.8',
         endPoint: '-28.4, 12.2',
+        maxHeight: '',
+        minHeight: '',
       }
     }
   },
@@ -252,11 +293,16 @@ export default {
         })
         let yLength = Math.max(...yArray) - Math.min(...yArray)
         yCenter = (Math.max(...yArray) + Math.min(...yArray)) / 2
+        let zArray = rawWholeData.map((eachPoint) => {
+          return eachPoint.z
+        })
+        let zLength = Math.max(...zArray) - Math.min(...zArray)
+        let zMin = Math.min(...zArray)
 
         let areaRatio = xLength / yLength
 
         // 各个点坐标映射到视口坐标
-        if (viewportRatio >= areaRatio) { // 分布范围应略小于svg尺寸
+        if (svgRatio >= areaRatio) { // 分布范围应略小于svg尺寸
           pxPerUnitLength = svgHeight / yLength * 0.9
         } else {
           pxPerUnitLength = svgWidth / xLength * 0.9
@@ -271,7 +317,7 @@ export default {
         // 组合成最终数据用来渲染
         for (let index = 0; index < rawWholeData.length; index++) {
           console.assert(rawWholeData[index].id === (index + 1), '数据点id和数据点在数组中的位置不相符!')
-          wholeDataForRender.push([wholeXArrayInPx[index], wholeYArrayInPx[index], JSON.stringify(rawWholeData[index]), rawWholeData[index].id])
+          wholeDataForRender.push([wholeXArrayInPx[index], wholeYArrayInPx[index], zArray[index], JSON.stringify(rawWholeData[index]), rawWholeData[index].id])
         }
 
         gNode.selectAll('rect').data(wholeDataForRender).enter().append('rect')
@@ -279,7 +325,9 @@ export default {
           .attr('y', (d) => d[1] - LENGTH_PER_POINT * pxPerUnitLength / 2)
           .attr('width', LENGTH_PER_POINT * pxPerUnitLength)
           .attr('height', LENGTH_PER_POINT * pxPerUnitLength)
-          .attr('fill', 'black')
+          .attr('fill', (d) => {
+            return `rgba(${Math.round((d[2] -zMin) / zLength * 255)}, 0, 0, 1)`
+          })
           .attr('render-data', (d) => {
             return d
           })
@@ -290,7 +338,9 @@ export default {
           let renderDataItemArray = renderDataItem.split(',')
           that.infoText = `数据点id: ${renderDataItemArray[renderDataItemArray.length - 1]}, \n具体值: ${renderDataItem.match(/^[^{]+(\{.+\})[^}]+$/)[1]}`
         }).on('mouseleave', function (e) {
-          d3.select(this).attr('fill', 'black')
+          d3.select(this).attr('fill', (d) => {
+            return `rgba(${Math.round((d[2] -zMin) / zLength * 255)}, 0, 0, 1)`
+          })
           that.infoText = ''
         })
 
@@ -446,7 +496,7 @@ export default {
           .attr('cx', (d) => d[0])
           .attr('cy', (d) => d[1])
           .attr('r', LENGTH_PER_POINT * pxPerUnitLength / 3.5)
-          .attr('fill', 'red')
+          .attr('fill', 'rgba(50, 255, 50, 1)')
           .attr('pointer-events', 'none')
       }
 
@@ -490,6 +540,24 @@ export default {
         zoomObj.transform,
         d3.zoomIdentity.scale(1)
       )
+    },
+    onSetHeightFilter() {
+      gNode.selectAll('rect').attr('visibility', (d) => {
+        if ((this.formData.maxHeight !== '') && (this.formData.maxHeight < d[2])) {
+          return 'hidden'
+        } else if ((this.formData.minHeight !== '') && (this.formData.minHeight > d[2])) {
+          return 'hidden'
+        } else {
+          return 'visible'
+        }
+      })
+    },
+    onResetHeightFilter() {
+      this.formData.maxHeight = ''
+      this.formData.minHeight = ''
+      gNode.selectAll('rect').attr('visibility', (d) => {
+        return 'visible'
+      })
     }
   },
 }
@@ -523,15 +591,30 @@ export default {
   display: flex;
   align-items: center;
 }
-.map .button-group {
+.map > .map-control-area {
+  margin-left: 20px;
+}
+.map > .map-control-area > .panel {
+  border: 1px solid black;
   display: flex;
   flex-direction: column;
   justify-content: center;
   align-items: center;
+  margin-bottom: 15px;
 }
-.map .button-group .btn {
+.map > .map-control-area > .panel > .btn {
   margin: 10px;
 }
+.map > .map-control-area > .panel.height-filter {
+  padding-left: 10px;
+  padding-right: 10px;
+}
+.map > .map-control-area > .panel.height-filter > .btn-group {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 10px;
+}
+
 .svgWrapper {
   display: inline-block;
   overflow: hidden;