PointMaterial.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. <template>
  2. <el-card style="margin-top: 10px; overflow: auto">
  3. <el-input
  4. v-model="pointModel.modelUrl"
  5. placeholder="请输入相应模型/图片地址"
  6. >
  7. <template #prepend>
  8. <el-select v-model="pointModel.modelName" style="width: 80px">
  9. <el-option label="模型" value="model" />
  10. <el-option label="图片" value="image" />
  11. </el-select>
  12. </template>
  13. </el-input>
  14. <el-button
  15. type="primary"
  16. style="margin-top: 5px; margin-left: 80%"
  17. @click="modelClick"
  18. >确定</el-button
  19. >
  20. </el-card>
  21. <el-card style="margin-top: 10px; overflow: auto; max-height: 500px">
  22. <template #header>
  23. <div class="card-header">
  24. <span>粒子系统</span>
  25. </div>
  26. </template>
  27. <el-select
  28. v-model="pointParticle.particleType"
  29. placeholder="Select"
  30. style="width: 100%"
  31. @change="particleChange"
  32. >
  33. <el-option label="盒发射器" value="BoxEmitter" />
  34. <el-option label="圆形发射器" value="CircleEmitter" />
  35. <el-option label="圆锥发射器" value="ConeEmitter" />
  36. <el-option label="球发射器" value="SphereEmitter" />
  37. </el-select>
  38. <el-input
  39. style="margin-top: 10px"
  40. v-for="(item, index) in pointParticle.particleInput"
  41. :key="index"
  42. v-model="item.value"
  43. :placeholder="item.title"
  44. :oninput="item.oninput"
  45. >
  46. <template #prepend>
  47. {{ item.name }}
  48. </template>
  49. </el-input>
  50. <el-button
  51. type="primary"
  52. @click="particleClick"
  53. style="margin-top: 5px; margin-left: 80%"
  54. >确定</el-button
  55. >
  56. </el-card>
  57. </template>
  58. <script lang="ts" setup>
  59. import {
  60. Billboard,
  61. BoxEmitter,
  62. Cartesian2,
  63. Cartesian3,
  64. CircleEmitter,
  65. Color,
  66. ConeEmitter,
  67. HeadingPitchRoll,
  68. Matrix4,
  69. Model,
  70. ParticleSystem,
  71. SphereEmitter,
  72. Transforms,
  73. Math as cesiumMath,
  74. } from "cesium";
  75. import { reactive } from "vue";
  76. import PlotDraw from "../plot";
  77. import type { Marker } from "../plot/graphicsDraw/pointDraw";
  78. const props = defineProps({
  79. draw: {
  80. type: PlotDraw,
  81. required: true,
  82. },
  83. });
  84. let point = props.draw.nowObj as Marker;
  85. let pointModel = reactive({
  86. modelUrl: "",
  87. modelName: "image",
  88. });
  89. function modelClick() {
  90. if (pointModel.modelName == "image") {
  91. if (point.pointPrimitive instanceof Billboard) {
  92. point.pointPrimitive.image = pointModel.modelUrl;
  93. } else {
  94. const position = Matrix4.getTranslation(
  95. point.pointPrimitive.modelMatrix,
  96. new Cartesian3()
  97. );
  98. window.Viewer.scene.primitives.remove(point.pointPrimitive);
  99. point.pointPrimitive = point.showPrimitiveOnMap(position);
  100. }
  101. } else {
  102. if (
  103. point.pointPrimitive instanceof Model ||
  104. point.pointPrimitive instanceof ParticleSystem
  105. ) {
  106. window.Viewer.scene.primitives.remove(point.pointPrimitive);
  107. point.pointPrimitive = point.showPrimitiveModelOnMap(
  108. pointModel.modelUrl,
  109. point.pointPrimitive.modelMatrix
  110. );
  111. } else {
  112. const position = point.pointPrimitive.position;
  113. const modelMatrix = Transforms.headingPitchRollToFixedFrame(
  114. position,
  115. new HeadingPitchRoll(0, 0, 0)
  116. );
  117. window.Viewer.billboards.remove(point.pointPrimitive);
  118. point.pointPrimitive = point.showPrimitiveModelOnMap(
  119. pointModel.modelUrl,
  120. modelMatrix
  121. );
  122. }
  123. }
  124. }
  125. let pointParticle = reactive({
  126. particleType: "BoxEmitter",
  127. particleInput: [
  128. {
  129. value: 1.0,
  130. name: "初始比例",
  131. realName: "startScale",
  132. title: "请输入粒子初始时比例",
  133. oninput: "value=value.replace(/[^0-9.]/g,'')",
  134. },
  135. {
  136. value: 5.0,
  137. name: "消失比例",
  138. realName: "endScale",
  139. title: "请输入粒子消失时比例",
  140. oninput: "value=value.replace(/[^0-9.]/g,'')",
  141. },
  142. {
  143. value: "#ffff00",
  144. name: "粒子颜色",
  145. realName: "startColor",
  146. title: "请输入粒子初始时颜色",
  147. oninput: "value=value.replace(/^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/g,'')",
  148. },
  149. {
  150. value: "/src/assets/icon/smoke.png",
  151. name: "图片地址",
  152. realName: "image",
  153. title: "请输入粒子对应图片地址",
  154. oninput: "value=value.replace(/*/g,'')",
  155. },
  156. {
  157. value: 3.0,
  158. name: "图片尺寸",
  159. realName: "image",
  160. title: "请输入粒子对应图片尺寸",
  161. oninput: "value=value.replace(/[^0-9.]/g,'')",
  162. },
  163. {
  164. value: 1.0,
  165. name: "最小速度",
  166. realName: "minimumSpeed",
  167. title: "请输入粒子最小速度",
  168. oninput: "value=value.replace(/[^0-9.]/g,'')",
  169. },
  170. {
  171. value: 3.0,
  172. name: "最大速度",
  173. realName: "maximumSpeed",
  174. title: "请输入粒子最大速度",
  175. oninput: "value=value.replace(/[^0-9.]/g,'')",
  176. },
  177. {
  178. value: 10.0,
  179. name: "每秒粒子数",
  180. realName: "emissionRate",
  181. title: "请输入每秒发射的粒子数",
  182. oninput: "value=value.replace(/[^0-9.]/g,'')",
  183. },
  184. {
  185. value: 1.0,
  186. name: "最小存活时间",
  187. realName: "minimumParticleLife",
  188. title: "请输入粒子最小存活时间",
  189. oninput: "value=value.replace(/[^0-9.]/g,'')",
  190. },
  191. {
  192. value: 5.0,
  193. name: "最大存活时间",
  194. realName: "maximumParticleLife",
  195. title: "请输入粒子最大存活时间",
  196. oninput: "value=value.replace(/[^0-9.]/g,'')",
  197. },
  198. ],
  199. });
  200. function particleClick() {
  201. let emitterParticle;
  202. switch (pointParticle.particleType) {
  203. case "BoxEmitter":
  204. emitterParticle = new BoxEmitter(new Cartesian3(10.0, 10.0, 10.0));
  205. break;
  206. case "CircleEmitter":
  207. emitterParticle = new CircleEmitter(2.0);
  208. break;
  209. case "ConeEmitter":
  210. emitterParticle = new ConeEmitter(cesiumMath.toRadians(45.0));
  211. break;
  212. case "SphereEmitter":
  213. emitterParticle = new SphereEmitter(2.5);
  214. break;
  215. default:
  216. emitterParticle = new CircleEmitter(2.0);
  217. break;
  218. }
  219. let modelMatrix;
  220. if (point.pointPrimitive instanceof Billboard) {
  221. modelMatrix = Transforms.headingPitchRollToFixedFrame(
  222. point.pointPrimitive.position,
  223. new HeadingPitchRoll(0, 0, 0)
  224. );
  225. window.Viewer.billboards.remove(point.pointPrimitive);
  226. } else if (point.pointPrimitive instanceof Model) {
  227. modelMatrix = point.pointPrimitive.modelMatrix;
  228. window.Viewer.scene.primitives.remove(point.pointPrimitive);
  229. } else {
  230. modelMatrix = point.pointPrimitive.modelMatrix;
  231. }
  232. const gravityScratch = new Cartesian3();
  233. if (!(point.pointPrimitive instanceof ParticleSystem)) {
  234. point.pointPrimitive = window.Viewer.scene.primitives.add(
  235. new ParticleSystem({
  236. lifetime: 16.0,
  237. updateCallback: function (p) {
  238. const position = p.position;
  239. Cartesian3.normalize(position, gravityScratch);
  240. Cartesian3.multiplyByScalar(gravityScratch, 0, gravityScratch);
  241. p.velocity = Cartesian3.add(p.velocity, gravityScratch, p.velocity);
  242. },
  243. emitterModelMatrix: modelMatrix,
  244. })
  245. );
  246. }
  247. point.pointPrimitive.emitter = emitterParticle;
  248. point.pointPrimitive.image = pointParticle.particleInput[3].value;
  249. point.pointPrimitive.startColor = Color.fromCssColorString(
  250. pointParticle.particleInput[2].value as string
  251. ).withAlpha(0.7);
  252. point.pointPrimitive.endColor = Color.WHITE.withAlpha(0.0);
  253. point.pointPrimitive.startScale = eval(
  254. pointParticle.particleInput[0].value as string
  255. ) as number;
  256. point.pointPrimitive.endScale = eval(
  257. pointParticle.particleInput[1].value as string
  258. ) as number;
  259. point.pointPrimitive.minimumParticleLife = eval(
  260. pointParticle.particleInput[8].value as string
  261. ) as number;
  262. point.pointPrimitive.maximumParticleLife = eval(
  263. pointParticle.particleInput[9].value as string
  264. ) as number;
  265. point.pointPrimitive.minimumSpeed = eval(
  266. pointParticle.particleInput[5].value as string
  267. ) as number;
  268. point.pointPrimitive.maximumSpeed = eval(
  269. pointParticle.particleInput[6].value as string
  270. ) as number;
  271. point.pointPrimitive.imageSize = new Cartesian2(
  272. eval(pointParticle.particleInput[4].value as string) as number,
  273. eval(pointParticle.particleInput[4].value as string) as number
  274. );
  275. point.pointPrimitive.emissionRate = eval(
  276. pointParticle.particleInput[7].value as string
  277. ) as number;
  278. }
  279. function particleChange(val: string) {
  280. console.log(val);
  281. if (point.pointPrimitive instanceof ParticleSystem) {
  282. switch (val) {
  283. case "BoxEmitter":
  284. point.pointPrimitive.emitter = new BoxEmitter(
  285. new Cartesian3(10.0, 10.0, 10.0)
  286. );
  287. break;
  288. case "CircleEmitter":
  289. point.pointPrimitive.emitter = new CircleEmitter(2.0);
  290. break;
  291. case "ConeEmitter":
  292. point.pointPrimitive.emitter = new ConeEmitter(
  293. cesiumMath.toRadians(45.0)
  294. );
  295. break;
  296. case "SphereEmitter":
  297. point.pointPrimitive.emitter = new SphereEmitter(2.5);
  298. break;
  299. default:
  300. point.pointPrimitive.emitter = new CircleEmitter(2.0);
  301. break;
  302. }
  303. }
  304. }
  305. </script>
  306. <style lang="scss" scoped></style>