myIndex.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. <template>
  2. <div>
  3. <div>
  4. <!--button @click="increment">Count is: {{ count }}</button-->
  5. </div>
  6. <div id="vtkContainer" />
  7. <div class="tool">
  8. <div
  9. class="img"
  10. v-for="(item, index) in listArray"
  11. :key="index"
  12. @click="add(item.id)"
  13. >
  14. <el-image :src="item.img" fit="cover" /><span>{{ item.name }}</span>
  15. </div>
  16. <div class="left_container">
  17. <div class="leftdialong" v-show="dialogVisible">
  18. <div class="time">当前时间:{{ count }}</div>
  19. <div class="block">
  20. <el-form-item label="物理量">
  21. <el-cascader
  22. transfer="true"
  23. placeholder="灾情/物理量"
  24. clearable
  25. :popper-append-to-body="false"
  26. v-model="arrvalue"
  27. :options="options"
  28. @change="handleChange($event)"
  29. ></el-cascader>
  30. </el-form-item>
  31. </div>
  32. <!-- <el-form-item
  33. label="动画开始"
  34. >
  35. <el-input
  36. v-model="starttime"
  37. autocomplete="off"
  38. ></el-input>
  39. </el-form-item>
  40. <el-form-item
  41. label="动画结束"
  42. >
  43. <el-input
  44. v-model="endtime"
  45. autocomplete="off"
  46. ></el-input>
  47. </el-form-item> -->
  48. <div class="block">
  49. <span class="demonstration">动画开始</span>
  50. <el-slider
  51. :max="endtime"
  52. :min="starttime"
  53. v-model="count"
  54. @change="sliderchange"
  55. ></el-slider>
  56. <span class="demonstration">动画结束</span>
  57. </div>
  58. <div class="itemlist">
  59. <div class="item" @click="play(500)">播&nbsp;&nbsp;放</div>
  60. <div class="item" @click="suspend">暂&nbsp;&nbsp;停</div>
  61. <div class="item" @click="Prev">上一分钟</div>
  62. <div class="item" @click="increment">下一分钟</div>
  63. </div>
  64. <!-- <button @click="inOpacity">透明度: {{ opacity }}</button> -->
  65. <div class="dialog-footer">
  66. <span class="btn" @click="dialogVisible = false">关 闭</span>
  67. <!-- <el-button>关 闭</el-button> -->
  68. <!-- <el-button type="primary" @click="dialogVisible = false">确 定</el-button> -->
  69. </div>
  70. </div>
  71. </div>
  72. </div>
  73. <!-- 内容 -->
  74. <!-- 内容 -->
  75. <div>
  76. <evolutionView ref="evolution" :title1="title1" @getdata="getdata" />
  77. </div>
  78. </div>
  79. </template>
  80. <script setup>
  81. import p1 from "@/assets/img/u3479.png";
  82. import p2 from "@/assets/img/u10068.png";
  83. import p3 from "@/assets/img/12.png";
  84. import p4 from "@/assets/img/u3883.png";
  85. import p5 from "@/assets/img/u3405.png";
  86. import * as d3 from "d3-scale";
  87. import { formatDefaultLocale } from "d3-format";
  88. import { ref, onMounted, reactive } from "vue";
  89. import "@kitware/vtk.js/Rendering/Profiles/Geometry";
  90. import vtkRenderWindowWithControlBar from "@kitware/vtk.js/Rendering/Misc/RenderWindowWithControlBar";
  91. import vtkFullScreenRenderWindow from "@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow";
  92. import vtkActor from "@kitware/vtk.js/Rendering/Core/Actor";
  93. import vtkMapper from "@kitware/vtk.js/Rendering/Core/Mapper";
  94. import vtkUnstructuredDataReader from "../reader/UnstructuredDataReader.js";
  95. import vtkScalarBarActor from "@kitware/vtk.js/Rendering/Core/ScalarBarActor";
  96. import vtkLookupTable from "@kitware/vtk.js/Common/Core/LookupTable";
  97. import vtkDataArray from "@kitware/vtk.js/Common/Core/DataArray.js";
  98. import vtkColorTransferFunction from "@kitware/vtk.js/Rendering/Core/ColorTransferFunction";
  99. import { I } from "@kitware/vtk.js/macros2.js";
  100. import { Representation } from '@kitware/vtk.js/Rendering/Core/Property/Constants';
  101. import evolutionView from "./evolutionView.vue"
  102. // const props = {};
  103. let time = 3 * 60;
  104. let evolution=ref();
  105. let listArray = reactive([
  106. { id: 0, img: p1, name: "灾情演化" },
  107. { id: 1, img: p2, name: "演化过程" },
  108. { id: 2, img: p3, name: "灾情历史" },
  109. { id: 3, img: p4, name: "日志" },
  110. ]);
  111. let title1=ref("我是父组件")
  112. let dialogVisible = ref(false);
  113. let num = ref(4);
  114. let starttime = ref(1);
  115. let endtime = ref(60);
  116. let timenum = ref(2);
  117. let isstop = ref(false);
  118. let arrvalue = reactive();
  119. let options = reactive([
  120. {
  121. value: "fire",
  122. label: "火灾",
  123. children: [
  124. {
  125. value: "Temperature",
  126. label: "温度",
  127. },
  128. {
  129. value: "Pressure",
  130. label: "压强",
  131. },
  132. {
  133. value: "SO2",
  134. label: "SO2",
  135. },
  136. {
  137. value: "CO2",
  138. label: "CO2",
  139. },
  140. ],
  141. },
  142. {
  143. value: "Water",
  144. label: "水灾",
  145. children: [
  146. {
  147. value: "Height",
  148. label: "水位高度",
  149. },
  150. ],
  151. },
  152. ]);
  153. function add(id) {
  154. if (id == 2) {
  155. dialogVisible.value = true;
  156. evolution.value.isshow=false;
  157. }else if(id==0){
  158. evolution.value.isshow=true;
  159. evolution.value.getdata();
  160. dialogVisible.value = false;
  161. }
  162. }
  163. // 响应式状态
  164. const count = ref(0);
  165. const opacity = ref(0.1);
  166. const min = ref(0);
  167. const max = ref(1);
  168. const scalarFAll = ref([]); //火灾标量
  169. const scalarWAll = ref([]); //水灾标量
  170. /*
  171. Temperature:温度
  172. Pressure:压强
  173. SO2:SO2
  174. CO2:CO2
  175. Height:水位高度
  176. */
  177. // const scalarName = ref("CO2");
  178. // const filedir =ref("data/Fire/");
  179. //const scalarName = ref("Height");
  180. const filedir = ref("data/Water/");
  181. // const renderWindowWith = vtkRenderWindowWithControlBar.newInstance({
  182. // controlSize: 11,
  183. // });
  184. const renderWindowWith = vtkFullScreenRenderWindow.newInstance();
  185. const renderer = renderWindowWith.getRenderer();
  186. // renderer.setBackground([0.1,0.2,0]);
  187. const renderWindow = renderWindowWith.getRenderWindow();
  188. const resetCamera = renderer.resetCamera;
  189. const render = renderWindow.render;
  190. const mapper = vtkMapper.newInstance();
  191. //Sets scalarMode to USE_POINT_DATA
  192. // mapper.setScalarModeToUsePointData();
  193. const actor = vtkActor.newInstance();
  194. const reader = vtkUnstructuredDataReader.newInstance();
  195. const scalarBarActor = vtkScalarBarActor.newInstance();
  196. // actor.getProperty().setRepresentation(Representation.WIREFRAME);//线
  197. // actor.getProperty().setRepresentation(Representation.POINTS);//点
  198. actor.getProperty().setRepresentation(Representation.SURFACE);//面
  199. // 用来修改状态、触发更新的函数
  200. function inOpacity() {
  201. opacity.value = opacity.value + 0.1;
  202. actor.getProperty().setOpacity(opacity.value);
  203. renderWindow.render();
  204. }
  205. function getMinMax(scalars) {
  206. // console.log("getMinMax:",scalars);
  207. min.value = scalars[0];
  208. max.value = scalars[0];
  209. for (let index = 0; index <= scalars.length; index++) {
  210. let scalar = scalars[index];
  211. if (min.value > scalar) {
  212. min.value = scalar;
  213. }
  214. if (max.value < scalar) {
  215. max.value = scalar;
  216. }
  217. }
  218. // console.log("max,min:", max.value, min.value);
  219. }
  220. //时间
  221. function sleep(numberMillis) {
  222. var now = new Date();
  223. var exitTime = now.getTime() + numberMillis;
  224. console.log(exitTime);
  225. }
  226. function handleChange(val) {
  227. arrvalue = val;
  228. min.value = 0.0;
  229. max.value = 1.0;
  230. changeScalar();
  231. }
  232. //暂停
  233. function suspend() {
  234. isstop.value = false;
  235. console.log(isstop.value);
  236. }
  237. //滑块
  238. function sliderchange(val) {
  239. // console.log(val);
  240. changeScalar();
  241. }
  242. //播放
  243. function play(time) {
  244. isstop.value = true;
  245. const sleep = (timeout = time) =>
  246. new Promise((resolve, reject) => {
  247. setTimeout(resolve, timeout);
  248. });
  249. let timer = async (timeout) => {
  250. while (count.value < endtime.value && isstop.value) {
  251. // if (isstop.value == true) {
  252. await sleep(time);
  253. changeScalar();
  254. count.value++;
  255. // }
  256. }
  257. };
  258. timer(time);
  259. }
  260. //回到上一页
  261. function Prev() {
  262. isstop.value = false;
  263. count.value--;
  264. changeScalar();
  265. }
  266. // 用来修改状态、触发更新的函数
  267. function increment() {
  268. isstop.value = false;
  269. if (count.value == endtime.value) {
  270. return;
  271. }
  272. count.value++;
  273. changeScalar();
  274. }
  275. function changeScalar() {
  276. var scalars;
  277. if (arrvalue[0] == "fire") {
  278. scalars = scalarFAll.value[count.value];
  279. } else {
  280. scalars = scalarWAll.value[count.value];
  281. }
  282. const polydata = mapper.getInputData();
  283. const scalarArray = scalars.get(arrvalue[1]);
  284. // console.log("scalarArray:", scalarArray);
  285. const dataArray = vtkDataArray.newInstance({
  286. name: arrvalue[1],
  287. size: polydata.getNumberOfPoints(),
  288. });
  289. dataArray.setData(scalarArray);
  290. getMinMax(scalarArray);
  291. mapper.setScalarRange(min.value, max.value); //设置范围
  292. scalarBarActor.setAxisLabel(arrvalue[1]);
  293. polydata.getPointData().setScalars(dataArray);
  294. mapper.clearColorArrays(); //强制重建颜色
  295. actor.getProperty().setOpacity(count.value); //设置错误的透明度使得页面重新加载 不设置不刷新页面
  296. renderWindow.render();
  297. }
  298. //加载所有 标量数据
  299. function loadScalarAll() {
  300. //水灾
  301. for (let index = 0; index <= 60; index++) {
  302. const reader = vtkUnstructuredDataReader.newInstance();
  303. reader.setUrl("data/Water/" + "POST" + index + ".vtk").then(() => {
  304. const scalars = reader.getOutputData(1);
  305. scalarWAll.value[index] = scalars;
  306. });
  307. }
  308. //火灾
  309. for (let index = 0; index <= 60; index++) {
  310. const reader = vtkUnstructuredDataReader.newInstance();
  311. reader.setUrl("data/Fire/" + "POST" + index + ".vtk").then(() => {
  312. const scalars = reader.getOutputData(1);
  313. scalarFAll.value[index] = scalars;
  314. });
  315. }
  316. // console.log("scalarAll.value:",scalarAll.value);
  317. }
  318. //设置
  319. function generateTicks(numberOfTicks) {
  320. return (helper) => {
  321. const lastTickBounds = helper.getLastTickBounds();
  322. // compute tick marks for axes
  323. const scale = d3
  324. .scaleLinear()
  325. .domain([0.0, 1.0])
  326. .range([lastTickBounds[0], lastTickBounds[1]]);
  327. const samples = scale.ticks(numberOfTicks);
  328. const ticks = samples.map((tick) => scale(tick));
  329. // Replace minus "\u2212" with hyphen-minus "\u002D" so that parseFloat() works
  330. formatDefaultLocale({ minus: "\u002D" });
  331. const format = scale.tickFormat(ticks[0], ticks[ticks.length - 1], numberOfTicks);
  332. const tickStrings = ticks
  333. .map(format)
  334. .map((tick) => Number(parseFloat(tick).toPrecision(12)).toPrecision()); // d3 sometimes adds unwanted whitespace
  335. helper.setTicks(ticks);
  336. helper.setTickStrings(tickStrings);
  337. };
  338. }
  339. //安装时
  340. onMounted(() => {
  341. arrvalue = ["Water", "Height"];
  342. reader.setUrl(filedir.value + "POST1.vtk").then(() => {
  343. const polydata = reader.getOutputData(0);
  344. const scalars = reader.getOutputData(1);
  345. const scalarArray = scalars.get(arrvalue[1]);
  346. // console.log("scalarArray:", scalarArray);
  347. const dataArray = vtkDataArray.newInstance({
  348. name: arrvalue[1],
  349. size: polydata.getNumberOfPoints(),
  350. });
  351. dataArray.setData(scalarArray);
  352. polydata.getPointData().setScalars(dataArray);
  353. actor.setMapper(mapper);
  354. mapper.setInputData(polydata);
  355. getMinMax(scalarArray);
  356. mapper.setScalarRange(min.value, max.value); //设置范围
  357. renderer.addActor(actor);
  358. let lut = mapper.getLookupTable();
  359. renderer.addActor(scalarBarActor);
  360. scalarBarActor.setScalarsToColors(lut);
  361. // console.log("lut:", lut.getRange());
  362. // Change the number of ticks (TODO: add numberOfTicks to ScalarBarActor)
  363. scalarBarActor.setGenerateTicks(generateTicks(5));
  364. scalarBarActor.setAxisLabel(arrvalue[1]);
  365. scalarBarActor.setDrawAboveRangeSwatch(true);
  366. //修改设条颜色
  367. const ctf = vtkColorTransferFunction.newInstance();
  368. ctf.addRGBPoint(0.0, 0.0, 0.0, 1.0);
  369. ctf.addRGBPoint(1.0, 0.0, 1.0, 0.5);
  370. ctf.addRGBPoint(2.0, 0.0, 1.0, 0.0);
  371. ctf.addRGBPoint(3.0, 1.0, 0.5, 0.0);
  372. ctf.addRGBPoint(4.0, 1.0, 0.0, 0.0);
  373. mapper.setLookupTable(ctf);
  374. lut = mapper.getLookupTable();
  375. scalarBarActor.setScalarsToColors(lut);
  376. resetCamera();
  377. render();
  378. });
  379. loadScalarAll();
  380. });
  381. </script>
  382. <style>
  383. .controls {
  384. position: absolute;
  385. top: 25px;
  386. left: 25px;
  387. background: white;
  388. padding: 12px;
  389. }
  390. .haha {
  391. color: #fff;
  392. }
  393. .tool {
  394. position: fixed;
  395. top: 50px;
  396. left: 20px;
  397. z-index: 205;
  398. }
  399. .img {
  400. width: 48px;
  401. margin: -6px 0;
  402. padding: 8px 10px;
  403. background-color: rgba(255, 255, 255, 0.1);
  404. font-size: 12px;
  405. transform: scale(0.9);
  406. }
  407. .img span {
  408. color: #fff;
  409. display: inline-block;
  410. }
  411. .img .el-image {
  412. width: 34px;
  413. }
  414. .leftdialong {
  415. padding: 15px;
  416. width: 300px;
  417. position: relative;
  418. top: -248px;
  419. left: 69px;
  420. border-radius: 5px;
  421. box-shadow: 0px 3px 10px rgba(255, 255, 255, 0.1);
  422. }
  423. .leftdialong .el-form-item__label {
  424. font-size: 12px;
  425. color: #fff !important;
  426. padding-left: 6px;
  427. }
  428. .time {
  429. color: #fff;
  430. font-size: 12px;
  431. margin-bottom: 30px;
  432. }
  433. .itemlist {
  434. display: flex;
  435. }
  436. .item {
  437. background-color: rgba(255, 255, 255, 0.1);
  438. margin: 5px;
  439. padding: 5px 9px;
  440. border-radius: 5px;
  441. font-size: 14px;
  442. transform: scale(0.8);
  443. color: #fff;
  444. }
  445. .dialog-footer {
  446. margin-top: 30px;
  447. text-align: right;
  448. }
  449. .block {
  450. display: flex;
  451. }
  452. .demonstration {
  453. padding: 5px 5px 5px 0;
  454. font-size: 12px;
  455. color: #fff;
  456. display: inline-block;
  457. width: 100px;
  458. height: 24px;
  459. line-height: 24px;
  460. }
  461. .block .el-slider {
  462. padding: 0 5px;
  463. }
  464. .cascadeer .el-cascader {
  465. width: 100%;
  466. }
  467. .cascadeer .asterisk-left {
  468. width: 100% !important;
  469. font-size: 12px;
  470. }
  471. .btn {
  472. background-color: rgba(255, 255, 255, 0.1);
  473. margin: 5px;
  474. padding: 5px 9px;
  475. border-radius: 5px;
  476. font-size: 14px;
  477. transform: scale(0.8);
  478. color: #fff;
  479. }
  480. </style>