VideoFusion.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. <template>
  2. <div class="side-frame" @contextmenu.prevent="">
  3. <a-card size="small" :bordered="false" class="card-custom-style">
  4. <a-tabs v-model="tab" size="small" :animated="false" centered>
  5. <a-tab-pane :key="1" :tab="$t('model.VideoFusion-Setting')" class="roam-list scroll-box">
  6. <a-form
  7. ref="formRef"
  8. :model="form"
  9. v-bind="formItemLayout"
  10. @finishFailed="onFinishFailed"
  11. :label-col="{ span: 12 }" :wrapper-col="{ span: 10 }"
  12. >
  13. <a-form-item :label="$t('model.VideoFusion-Position')">
  14. <a-button ghost @click="AddPoint" class="submit-btn"
  15. >{{$t('model.VideoFusion-ClickPosition')}}</a-button
  16. >
  17. </a-form-item>
  18. <div>
  19. <a-list
  20. size="small"
  21. :data-source="track"
  22. bordered
  23. class="viewpoint-list scroll-box"
  24. :locale="{
  25. emptyText: $t('model.VideoFusion-Position-EmptyText'),
  26. }"
  27. >
  28. <a-list-item :key="index" v-for="(item, index) in track">
  29. {{ $t('model.Position') + (index + 1) }}
  30. <template #actions>
  31. <a-tooltip :title="$t('model.Delete')">
  32. <a-icon type="delete" @click="DelPoint(index)" :style="{ fontSize: '16px', color: '#05a081' }"></a-icon>
  33. </a-tooltip>
  34. </template>
  35. </a-list-item>
  36. </a-list>
  37. </div>
  38. <a-form-item :label="$t('model.VideoFusion-rotate')" name="rotate">
  39. <a-slider
  40. v-model="form.rotate"
  41. @blur="rotateChange"
  42. :min="0"
  43. :max="360"
  44. :step="1"
  45. />
  46. </a-form-item>
  47. <a-form-item :label="$t('model.VideoFusion-alpha')" name="alpha">
  48. <a-slider
  49. v-model="form.alpha"
  50. @blur="alphaChange"
  51. :min="0"
  52. :max="1"
  53. :step="0.01"
  54. />
  55. </a-form-item>
  56. <a-form-item :label="$t('model.VideoFusion-mixDepth')" name="mixDepth">
  57. <a-slider
  58. v-model="form.mixDepth"
  59. @blur="mixDepthChange"
  60. :min="0"
  61. :max="1"
  62. :step="0.01"
  63. />
  64. </a-form-item>
  65. <a-form-item :label="$t('model.VideoFusion-isFlipX')" name="isFlipX">
  66. <a-switch
  67. v-model="form.isFlipX"
  68. @change="isFlipXChange"
  69. />
  70. </a-form-item>
  71. <a-form-item :label="$t('model.VideoFusion-isFlipY')" name="isFlipY">
  72. <a-switch
  73. v-model="form.isFlipY"
  74. @change="isFlipYChange"
  75. />
  76. </a-form-item>
  77. <a-form-item :label="$t('model.VideoFusion-offextX')" name="offextX">
  78. <a-input-number
  79. v-model="form.offextX"
  80. @change="offextXChange"
  81. />
  82. </a-form-item>
  83. <a-form-item :label="$t('model.VideoFusion-offextY')" name="offextY">
  84. <a-input-number
  85. v-model="form.offextY"
  86. @change="offextYChange"
  87. />
  88. </a-form-item>
  89. <a-form-item :label="$t('model.VideoFusion-offextZ')" name="offextZ">
  90. <a-input-number
  91. v-model="form.offextZ"
  92. @change="offextZChange"
  93. />
  94. </a-form-item>
  95. <a-form-item :wrapper-col="{ span: 24 }">
  96. <a-space class="options-btn">
  97. <a-button ghost @click="StartVideoFusion2D">{{$t('model.VideoFusion-Save')}}</a-button>
  98. <a-button ghost @click="StopVideoFusion2D">{{$t('model.VideoFusion-Delete')}}</a-button>
  99. </a-space>
  100. </a-form-item>
  101. </a-form>
  102. </a-tab-pane>
  103. <a-tab-pane :key="2" :tab="$t('model.HistoryData')">
  104. <a-list
  105. size="small"
  106. :data-source="historysList"
  107. :locale="{ emptyText: $t('model.EmptyData') }"
  108. class="roam-list scroll-box"
  109. >
  110. <a-list-item :key="index" v-for="(item, index) in historysList">
  111. {{ $t('model.VideoFusion') + (index + 1) }}
  112. <template #actions>
  113. <a-tooltip :title="$t('model.Delete')">
  114. <a-icon type="delete" @click="delList(index, index)" :style="{ fontSize: '16px', color: '#05a081' }"></a-icon>
  115. </a-tooltip>
  116. </template>
  117. </a-list-item>
  118. </a-list>
  119. </a-tab-pane>
  120. </a-tabs>
  121. </a-card>
  122. </div>
  123. </template>
  124. <script>
  125. import { message } from "ant-design-vue";
  126. import { buildShortID } from "@/utils/util";
  127. export default {
  128. name: "VideoFusion",
  129. props:{
  130. store: {
  131. type: Object,
  132. default: {},
  133. },
  134. $t: {
  135. type: Function,
  136. },
  137. $i18n: {
  138. type: Object,
  139. },
  140. },
  141. data() {
  142. return {
  143. tab: 1,
  144. formRef: null,
  145. form: {
  146. title: "",
  147. rotate: 90,
  148. alpha: 1,
  149. mixDepth: 0.25,
  150. isFlipX: false,
  151. isFlipY: false,
  152. offextX: 0,
  153. offextY: 0,
  154. offextZ: 0,
  155. url: "/static/img/DisplayVideo.mp4",
  156. },
  157. track: [],
  158. formItemLayout: {
  159. labelCol: {
  160. span: 9,
  161. },
  162. wrapperCol: {
  163. span: 15,
  164. },
  165. },
  166. historysList: [], //历史列表,如需要可自行存储
  167. currentId: null,
  168. videoPlugin: null,
  169. };
  170. },
  171. mounted() {
  172. this.videoPlugin = window.api.Plugin.initVideo();
  173. window.api.Public.setSceneRenderState(false);
  174. },
  175. beforeDestroy() {
  176. window.api.Public.setSceneRenderState(true);
  177. this.historysList.forEach((item) => {
  178. this.videoPlugin.delete(item.ID);
  179. });
  180. },
  181. methods: {
  182. StartVideoFusion2D(values) {
  183. //开始漫游
  184. if (this.currentId) {
  185. message.warning(this.$t('model.VideoFusion-Exist'));
  186. return;
  187. }
  188. if (this.track.length != 4) {
  189. message.warning(this.$t('model.VideoFusion-Waring'));
  190. return;
  191. }
  192. var position = [];
  193. for (let i = 0; i < this.track.length; i++) {
  194. position = position.concat(this.track[i]);
  195. }
  196. const params = {
  197. ID: "video" + buildShortID(6), //唯一标识id
  198. videoElement: this.form.url, // 视频地址
  199. positions: position, // 承載視頻的多邊形頂點坐標
  200. positionOffset: {
  201. //偏移
  202. x: values.offextX,
  203. y: values.offextY,
  204. z: values.offextZ,
  205. },
  206. isFlipX: values.isFlipX, // 水平方向翻转材质法向
  207. isFlipY: values.isFlipY, // 水平方向翻转材质法向
  208. rotate: values.rotate, // 视频旋转角度, 纹理旋转角度
  209. alpha: values.alpha, // [0.0,1.0] 全局透明度
  210. mixDepth: values.mixDepth, // 融合深度 0:不融合 [0,1]
  211. videoAutoPlay: true, // 是否自动播放视频
  212. videoLoop: true, // 是否循环播放视频
  213. };
  214. console.log("视频融合参数", params);
  215. this.currentId = params.ID;
  216. this.videoPlugin.addByPlane(params.ID, params);
  217. window.api.Public.removePoint(0);
  218. this.historysList.push(params);
  219. },
  220. onFinishFailed(errorInfo) {
  221. message.error(this.$t('model.Input-tip'));
  222. },
  223. StopVideoFusion2D() {
  224. this.formRef ? this.formRef.resetFields() : null; //清空表单
  225. window.api.Public.removePoint(0); //清除点
  226. message.success(this.$t('model.End'));
  227. this.videoPlugin.delete(this.currentId);
  228. let index = this.historysList.findIndex(
  229. (item) => item.ID == this.currentId
  230. );
  231. index != -1 ? this.historysList.splice(index, 1) : null;
  232. this.currentId = "";
  233. this.track = [];
  234. },
  235. delList(data, index) {
  236. this.historysList.splice(index, 1);
  237. this.videoPlugin.delete(data.ID); //删除视频融合
  238. if (data.ID == this.currentId) {
  239. this.currentId = "";
  240. this.track = [];
  241. this.formRef ? this.formRef.resetFields() : null; //清空表单
  242. }
  243. message.success(this.$t('model.Delete-Success'));
  244. },
  245. AddPoint() {
  246. let that = this
  247. if (this.track.length == 4) {
  248. this.formRef ? this.formRef.resetFields() : null; //清空表单
  249. this.track = [];
  250. this.currentId = "";
  251. }
  252. message.info(this.$t('model.VideoFusion-Position-Tip'));
  253. window.api.Public.event("LEFT_CLICK", function (click) {
  254. window.api.Public.pickupCoordinate(click.position, function (data) {
  255. that.track.push(data);
  256. window.api.Public.drawPoint(data, {
  257. axisType: 1,
  258. });
  259. });
  260. });
  261. },
  262. DelPoint(index) {
  263. this.track.splice(index, 1);
  264. },
  265. rotateChange() {
  266. if (
  267. this.currentId == this.historysList[this.historysList.length - 1].ID
  268. ) {
  269. var defaultConfigSimgle2D = {
  270. url: this.form.url,
  271. rotate: this.form.rotate, // 视频旋转角度, 纹理旋转角度
  272. };
  273. this.videoPlugin.updateByPlane(this.currentId, defaultConfigSimgle2D);
  274. }
  275. },
  276. alphaChange() {
  277. if (
  278. this.currentId == this.historysList[this.historysList.length - 1].ID
  279. ) {
  280. var defaultConfigSimgle2D = {
  281. url: this.form.url,
  282. alpha: this.form.alpha, // 视频旋转角度, 纹理旋转角度
  283. };
  284. this.videoPlugin.updateByPlane(this.currentId, defaultConfigSimgle2D);
  285. }
  286. },
  287. mixDepthChange() {
  288. if (
  289. this.currentId == this.historysList[this.historysList.length - 1].ID
  290. ) {
  291. var defaultConfigSimgle2D = {
  292. url: this.form.url,
  293. mixDepth: this.form.mixDepth, // 视频旋转角度, 纹理旋转角度
  294. };
  295. this.videoPlugin.updateByPlane(this.currentId, defaultConfigSimgle2D);
  296. }
  297. },
  298. isFlipXChange() {
  299. if (
  300. this.currentId == this.historysList[this.historysList.length - 1].ID
  301. ) {
  302. var defaultConfigSimgle2D = {
  303. url: this.form.url,
  304. isFlipX: this.form.isFlipX, // 视频旋转角度, 纹理旋转角度
  305. };
  306. this.videoPlugin.updateByPlane(this.currentId, defaultConfigSimgle2D);
  307. }
  308. },
  309. isFlipYChange() {
  310. if (
  311. this.currentId == this.historysList[this.historysList.length - 1].ID
  312. ) {
  313. var defaultConfigSimgle2D = {
  314. url: this.form.url,
  315. isFlipY: this.form.isFlipY, // 视频旋转角度, 纹理旋转角度
  316. };
  317. this.videoPlugin.updateByPlane(this.currentId, defaultConfigSimgle2D);
  318. }
  319. },
  320. offextXChange() {
  321. if (
  322. this.currentId == this.historysList[this.historysList.length - 1].ID
  323. ) {
  324. var defaultConfigSimgle2D = {
  325. url: this.form.url,
  326. positionOffset: {
  327. x: this.form.offextX, // 向y轴负方向偏移1m
  328. },
  329. };
  330. this.videoPlugin.updateByPlane(this.currentId, defaultConfigSimgle2D);
  331. }
  332. },
  333. offextYChange() {
  334. if (
  335. this.currentId == this.historysList[this.historysList.length - 1].ID
  336. ) {
  337. var defaultConfigSimgle2D = {
  338. url: this.form.url,
  339. positionOffset: {
  340. y: this.form.offextY, // 向y轴负方向偏移1m
  341. },
  342. };
  343. this.videoPlugin.updateByPlane(this.currentId, defaultConfigSimgle2D);
  344. }
  345. },
  346. offextZChange() {
  347. if (
  348. this.currentId == this.historysList[this.historysList.length - 1].ID
  349. ) {
  350. var defaultConfigSimgle2D = {
  351. url: this.form.url,
  352. positionOffset: {
  353. z: this.form.offextZ, // 向y轴负方向偏移1m
  354. },
  355. };
  356. this.videoPlugin.updateByPlane(this.currentId, defaultConfigSimgle2D);
  357. }
  358. },
  359. },
  360. };
  361. </script>
  362. <style lang="less" scoped>
  363. .viewpoint-list {
  364. height: 12vh;
  365. overflow-y: auto;
  366. margin: 8px 10px 15px;
  367. /deep/.ant-list-item {
  368. padding: 5px 10px;
  369. margin: 0 10px;
  370. }
  371. }
  372. .ant-slider {
  373. width: 100%;
  374. }
  375. .roam-list {
  376. max-height: 55vh;
  377. overflow-x: hidden;
  378. }
  379. </style>