EditPanel.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. <template>
  2. <transition
  3. appear
  4. name="custom-classes-transition"
  5. enter-active-class="animated slideInRight speed"
  6. leave-active-class="animated slideOutRight speed"
  7. >
  8. <div class="hots-panel" v-show="show">
  9. <div class="ui-between header">
  10. <span>{{ editTitle }}{{ $i18n.t('hotspot.hotspot_name') }}</span>
  11. <i class="iconfont icon_close" @click="cancel"></i>
  12. </div>
  13. <div class="content" ref="content">
  14. <div class="type-setting">
  15. <div class="remark">热点类型</div>
  16. <combox
  17. class="combox"
  18. :data="hotspotTypeList"
  19. :selected-id="hotspot.hotspotType"
  20. :bottomSpace="comboxBottomSpace"
  21. @change="onHotSpotTypeChange"
  22. />
  23. </div>
  24. <div class="icon-setting">
  25. <div class="remark">{{ $i18n.t('hotspot.select_icon') }}</div>
  26. <combox
  27. class="combox"
  28. :data="hotspotIconTypeList"
  29. :selected-id="hotspot.hotspotIconType"
  30. :bottomSpace="comboxBottomSpace"
  31. @change="onHotspotIconTypeChange"
  32. />
  33. <component
  34. class="icon-setting-component"
  35. :is="iconSettingComponent"
  36. ref="icon-setting-component"
  37. @addHotspot="addhotspot"
  38. />
  39. <div class="bars">
  40. <RangeItem :value="rang" @input="onRangeChange" />
  41. </div>
  42. </div>
  43. <div class="title-setting">
  44. <div class="remark-highlight">{{ $i18n.t('hotspot.hotspot_title') }}</div>
  45. <div class="title-input-wrapper">
  46. <input
  47. v-model.trim="hotspot.hotspotTitle"
  48. type="text" maxlength="15"
  49. :placeholder="$i18n.t('hotspot.title_placeholder')"
  50. />
  51. <span class="count">{{ hotspot.hotspotTitle.length }}/15</span>
  52. </div>
  53. <div class="remark">{{ $i18n.t('hotspot.title_show_mode') }}</div>
  54. <TabbarSwitcher
  55. class="display-mode-selector"
  56. :tabList="[
  57. $i18n.t('hotspot.show_on_hover'),
  58. $i18n.t('hotspot.always_show'),
  59. $i18n.t('hotspot.never_show'),
  60. ]"
  61. :activeIdx="currentTitleDispayModeIdx"
  62. @select="onSelectTitleDisplayMode"
  63. />
  64. <div class="remark">{{ $i18n.t('hotspot.title_position') }}</div>
  65. <TabbarSwitcherIcon
  66. class="display-mode-selector"
  67. :tabList="[
  68. {
  69. icon: 'icon-up',
  70. tip: $i18n.t('hotspot.title_top'),
  71. },
  72. {
  73. icon: 'icon-down',
  74. tip: $i18n.t('hotspot.title_bottom'),
  75. },
  76. {
  77. icon: 'icon-left',
  78. tip: $i18n.t('hotspot.title_left'),
  79. },
  80. {
  81. icon: 'icon-right',
  82. tip: $i18n.t('hotspot.title_right'),
  83. },
  84. {
  85. icon: 'icon-mobile',
  86. tip: $i18n.t('hotspot.title_custom'),
  87. },
  88. ]"
  89. :activeIdx="currentTitlePositionIdx"
  90. @select="onSelectTitlePosition"
  91. />
  92. </div>
  93. <div class="effect-setting">
  94. <component
  95. class="effect-setting-component"
  96. @sceneSelect="handleSceneSelect"
  97. :scene="hotspot.secne"
  98. @imageChange="data => { hotspot.image = data }"
  99. :image="hotspot.image"
  100. @linkChange="data => { hotspot.hyperlink = data }"
  101. :link="hotspot.hyperlink"
  102. @linkOpenType="data => { hotspot.linkOpenType = data }"
  103. :linkOpenType="hotspot.linkOpenType"
  104. @textChange="data => { hotspot.textarea = data }"
  105. :textarea="hotspot.textarea"
  106. @audioChange="data => { hotspot.audio = data }"
  107. :audio="hotspot.audio"
  108. @videoChange="data => { hotspot.video = data }"
  109. :video="hotspot.video"
  110. :is="effectSettingComponent"
  111. />
  112. </div>
  113. </div>
  114. <div class="ui-between footer" app-border dir-top>
  115. <button
  116. class="ui-button deepcancel"
  117. :class="{ disable: false }"
  118. @click="cancel"
  119. >
  120. {{$i18n.t('hotspot.cancel')}}
  121. </button>
  122. <button
  123. class="ui-button submit"
  124. :class="{ disable: !canSubmit }"
  125. @click="save"
  126. >
  127. {{$i18n.t('hotspot.finish')}}
  128. </button>
  129. </div>
  130. </div>
  131. </transition>
  132. </template>
  133. <script>
  134. import RangeItem from "@/components/rangeItem/index.vue";
  135. import Combox from "@/components/shared/Combox";
  136. import { mapGetters } from "vuex";
  137. import Switcher from "@/components/shared/Switcher.vue";
  138. import TabbarSwitcher from "@/components/shared/TabbarSwitcher.vue";
  139. import TabbarSwitcherIcon from "@/components/shared/TabbarSwitcherIcon.vue";
  140. import hotspotTypeList from "./hotspotTypeList.js";
  141. export default {
  142. props: ['show', 'data', 'editTitle'],
  143. components: {
  144. RangeItem,
  145. Combox,
  146. Switcher,
  147. TabbarSwitcher,
  148. TabbarSwitcherIcon,
  149. },
  150. data() {
  151. return {
  152. hotspotTypeList,
  153. hotspotIconTypeList: [
  154. {
  155. name: '系统图标',
  156. id: 'system',
  157. },
  158. {
  159. name: '自定义图标',
  160. id: 'custom',
  161. },
  162. {
  163. name: '个性标签',
  164. id: 'personalized',
  165. },
  166. ],
  167. rang: {
  168. label: this.$i18n.t('hotspot.icon_size'),
  169. unit: this.$i18n.t('hotspot.unit'),
  170. gradient: 0.1,
  171. value: 1,
  172. min: 0.5,
  173. max: 2,
  174. },
  175. isAdd: true,
  176. comboxBottomSpace: 0,
  177. }
  178. },
  179. watch: {
  180. 'hotspot.hotspotTitle': function () {
  181. this.$getKrpano().set('layer[tooltip_' + this.hotspot.name + '].html', this.hotspot.hotspotTitle)
  182. },
  183. // 'hotspot.visible': function () {
  184. // this.$getKrpano().set('layer[tooltip_' + this.hotspot.name + '].visible', this.hotspot.visible)
  185. // },
  186. 'hotspot.size': {
  187. immediate: true,
  188. handler: function (newVal) {
  189. let h = 52
  190. let scaleH = h * newVal
  191. let offset = '-130%'
  192. this.rang = { ...this.rang, value: newVal }
  193. this.$getKrpano().set(`hotspot[${this.hotspot.name}].height`, scaleH)
  194. if (newVal < 1) {
  195. offset = '-200%'
  196. }
  197. if (newVal > 1) {
  198. offset = '-100%'
  199. }
  200. this.$getKrpano().set('layer[tooltip_' + this.hotspot.name + '].y', `${offset}`)
  201. }
  202. },
  203. 'hotspot.fontSize': {
  204. handler: function (newVal) {
  205. this.$getKrpano().set('layer[tooltip_' + this.hotspot.name + '].css', `text-align:center; color:#FFFFFF;
  206. font-family:STXihei;font-size:${newVal}px;`)
  207. }
  208. },
  209. },
  210. beforeDestroy() {
  211. this.$bus.removeListener('resethotspotTitle', this.listerFnReset)
  212. },
  213. computed: {
  214. ...mapGetters({
  215. hotspot: 'hotspot',
  216. backupHotSpot: 'backupHotSpot',
  217. }),
  218. iconSettingComponent() {
  219. let tmp = this.hotspot.hotspotIconType
  220. return () => import(`./hotspotIconType/${tmp}.vue`);
  221. },
  222. currentTitleDispayModeIdx() {
  223. switch (this.hotspot.titleDisplayMode) {
  224. case 'hover':
  225. return 0
  226. case 'always':
  227. return 1
  228. case 'never':
  229. return 2
  230. default:
  231. return 0
  232. }
  233. },
  234. currentTitlePositionIdx() {
  235. switch (this.hotspot.titlePosition) {
  236. case 'top':
  237. return 0
  238. case 'bottom':
  239. return 1
  240. case 'left':
  241. return 2
  242. case 'right':
  243. return 3
  244. case 'custom':
  245. return 4
  246. default:
  247. return 0
  248. }
  249. },
  250. effectSettingComponent() {
  251. let tmp = this.hotspot.hotspotType
  252. return () => import(`./hotspotType/${tmp}.vue`);
  253. },
  254. canSubmit() {
  255. let { img, hotspotTitle } = this.hotspot
  256. if (!img) {
  257. return false
  258. }
  259. if (!hotspotTitle.trim()) {
  260. return false
  261. }
  262. if (this.hotspot.hotspotType == 'image' && this.hotspot.image.length <= 0) {
  263. return false
  264. }
  265. return true
  266. }
  267. },
  268. mounted() {
  269. this.$bus.on('resethotspotTitle', this.listerFnReset)
  270. this.$bus.on('delhotspot', () => {
  271. this.cancel()
  272. })
  273. setTimeout(() => {
  274. if (this.editTitle != '编辑' && this.editTitle != this.$i18n.t('hotspot.edit')) {
  275. this.addhotspot(this.$refs['icon-setting-component'].hotspotIconList[0])
  276. this.rang.value = window.g_hotspotCurrentScale
  277. this.onRangeChange({ value: window.g_hotspotCurrentScale })
  278. }
  279. this.comboxBottomSpace = this.$refs.content.getBoundingClientRect().bottom
  280. }, 300)
  281. },
  282. methods: {
  283. handleSceneSelect(data) {
  284. this.hotspot.secne = {
  285. ...data,
  286. someData: {}
  287. }
  288. },
  289. onHotSpotTypeChange(data) {
  290. this.hotspot.hotspotType = data.id
  291. },
  292. onHotspotIconTypeChange(data) {
  293. this.hotspot.hotspotIconType = data.id
  294. },
  295. onRangeChange(data) {
  296. console.log(data);
  297. this.rang = { ...this.rang, value: data.value }
  298. this.hotspot.size = data.value
  299. switch (data.value) {
  300. case 0.5:
  301. case 0.6:
  302. case 0.7:
  303. this.hotspot.fontSize = 12
  304. break;
  305. case 0.8:
  306. case 0.9:
  307. case 1.0:
  308. case 1.1:
  309. case 1.2:
  310. this.hotspot.fontSize = 14
  311. break;
  312. case 1.3:
  313. case 1.4:
  314. case 1.5:
  315. case 1.6:
  316. case 1.7:
  317. this.hotspot.fontSize = 17
  318. break;
  319. case 1.8:
  320. case 1.9:
  321. case 2:
  322. this.hotspot.fontSize = 20
  323. break;
  324. default:
  325. break;
  326. }
  327. },
  328. onSelectTitleDisplayMode(idx) {
  329. switch (idx) {
  330. case 0:
  331. this.hotspot.titleDisplayMode = 'hover'
  332. break;
  333. case 1:
  334. this.hotspot.titleDisplayMode = 'always'
  335. break;
  336. case 2:
  337. this.hotspot.titleDisplayMode = 'never'
  338. break;
  339. default:
  340. break;
  341. }
  342. },
  343. onSelectTitlePosition(idx) {
  344. switch (idx) {
  345. case 0:
  346. this.hotspot.titlePosition = 'top'
  347. break;
  348. case 1:
  349. this.hotspot.titlePosition = 'bottom'
  350. break;
  351. case 2:
  352. this.hotspot.titlePosition = 'left'
  353. break;
  354. case 3:
  355. this.hotspot.titlePosition = 'right'
  356. break;
  357. case 4:
  358. this.hotspot.titlePosition = 'custom'
  359. break;
  360. default:
  361. break;
  362. }
  363. },
  364. listerFnReset() {
  365. if (this.hotspot.hotspotTitle == '单击确定热点位置'||this.hotspot.hotspotTitle == this.$i18n.t('hotspot.click_to_comfirm')) {
  366. this.hotspot.hotspotTitle = ''
  367. }
  368. },
  369. cancel() {
  370. this.$store.commit("SetHotspot", this.backupHotSpot);
  371. this.$emit("close", {
  372. type: this.editTitle == this.$i18n.t('hotspot.edit') ? 'edit' : 'add',
  373. data: this.backupHotSpot
  374. });
  375. },
  376. reset(data) {
  377. this.$bus.emit('edithotspotTitle', data)
  378. this.$bus.emit('edithotspotTitleisShow', data)
  379. this.$getKrpano().set(`hotspot[${data.name}].url`, data.img)
  380. },
  381. save() {
  382. this.$store.commit("SetHotspot", this.hotspot);
  383. this.$emit("close");
  384. this.$emit("save", this.hotspot);
  385. },
  386. addhotspot(data) {
  387. if (this.isAdd && (this.editTitle != '编辑' && this.editTitle != this.$i18n.t('hotspot.edit'))) {
  388. this.isAdd = false
  389. this.hotspot.img = data.img
  390. this.$bus.emit('addhotspot', this.hotspot)
  391. this.$getKrpano().set('layer[tooltip_' + this.hotspot.name + '].css', `text-align:center; color:#FFFFFF;
  392. font-family:STXihei;font-size:${this.hotspot.fontSize}px;`)
  393. } else {
  394. this.hotspot.img = data.img
  395. this.$getKrpano().set(`hotspot[${this.hotspot.name}].url`, data.img)
  396. this.$getKrpano().set(`hotspot[${this.hotspot.name}].hotspottitle`, this.hotspot.hotspotTitle)
  397. }
  398. }
  399. }
  400. };
  401. </script>
  402. <style lang="less" scoped>
  403. .hots-panel {
  404. background: #252526;
  405. z-index: 10;
  406. display: flex;
  407. flex-direction: column;
  408. .header {
  409. padding: 20px;
  410. display: flex;
  411. font-size: 18px;
  412. color: #fff;
  413. flex: 0 0 auto;
  414. .icon_close {
  415. color: rgba(255, 255, 255, 0.6);
  416. cursor: pointer;
  417. }
  418. }
  419. .content {
  420. padding: 0 20px 14px 20px;
  421. flex: 1 0 1px;
  422. overflow: auto;
  423. .type-setting {
  424. .remark {
  425. font-size: 14px;
  426. color: #ababab;
  427. }
  428. .combox {
  429. margin-top: 16px;
  430. }
  431. }
  432. .icon-setting {
  433. .icon-setting-title {
  434. font-size: 18px;
  435. color: #FFFFFF;
  436. }
  437. .remark {
  438. margin-top: 16px;
  439. font-size: 14px;
  440. color: #ababab;
  441. }
  442. .combox {
  443. margin-top: 16px;
  444. }
  445. .icon-setting-component {
  446. margin-top: 16px;
  447. }
  448. .bars {
  449. margin-top: 16px;
  450. }
  451. }
  452. .title-setting {
  453. .remark-highlight {
  454. margin-top: 16px;
  455. font-size: 18px;
  456. color: #FFFFFF;
  457. }
  458. >.title-input-wrapper {
  459. position: relative;
  460. border: 1px solid rgba(151, 151, 151, 0.2);
  461. padding: 0 16px;
  462. background: #1A1B1D;
  463. border-radius: 2px;
  464. height: 36px;
  465. width: 100%;
  466. margin-top: 18px;
  467. &:focus-within {
  468. border-color: #0076F6;
  469. }
  470. >input {
  471. border: none;
  472. background: transparent;
  473. outline: none;
  474. height: 100%;
  475. width: calc(100% - 50px);
  476. padding: 0;
  477. color: #fff;
  478. letter-spacing: 1px;
  479. font-size: 14px;
  480. }
  481. >.count {
  482. position: absolute;
  483. top: 50%;
  484. transform: translateY(-50%);
  485. right: 16px;
  486. font-size: 14px;
  487. color: rgba(255, 255, 255, 0.2);
  488. }
  489. }
  490. .remark {
  491. margin-top: 18px;
  492. color: rgba(255, 255, 255, 0.6);
  493. font-size: 14px;
  494. }
  495. .display-mode-selector {
  496. margin-top: 18px;
  497. }
  498. }
  499. .effect-setting {
  500. margin-top: 16px;
  501. .effect-setting-title {
  502. font-size: 18px;
  503. color: #FFFFFF;
  504. }
  505. .combox {
  506. margin-top: 16px;
  507. }
  508. .effect-setting-component {
  509. margin-top: 16px;
  510. }
  511. }
  512. }
  513. .footer {
  514. flex: 0 0 auto;
  515. padding: 15px;
  516. background: #252526;
  517. .deepcancel {
  518. margin-right: 10px;
  519. }
  520. .ui-button {
  521. width: 112px;
  522. }
  523. }
  524. }
  525. </style>