ButtonElement.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. <template>
  2. <div class='wrap' @mouseover="mouseover" @mouseleave="mouseleave" @dragstart="dragstart" @mousedown="mousedown"
  3. @mouseup="mouseup">
  4. <template v-if="!element.eleCanvas">
  5. <img :style="{'z-index':1,width:'100%',height:'100%','border-radius': element.circular+'%'}"
  6. :src="element.backgroundUnselectedImg">
  7. <img
  8. src="https://dm.static.elab-plus.com/launchTemplate/0a3b783c-c54a-4e13-ba50-8f0ac6bb35f4-%E6%92%AD%E6%94%BE.png"
  9. v-show="element.videoEditable"
  10. style="z-index:1;top:50%;left:50%;transform:translate(-50%,-50%);display: block" />
  11. <section class="content">
  12. <!-- 默认属性动画 -->
  13. <div :class="'animated ' + this.element['animatedName']" :style="styleAnime" v-if="element['animatedFont']">
  14. <myfont :duration="element.duration" :delay="element.delay" :loop="element.loop"
  15. :fonts="element.text.replace(/\n/g,'^').split('')" :class="element['animatedFont']"
  16. :fontstyle="element['animatedFont']" :highLightDelimitId="isOverView?'':element.nodeId"
  17. :elabEditable="element['elabEditable']||true" :style="styleBasic">{{ element.text }}</myfont>
  18. </div>
  19. <div :class="'animated ' + this.element['animatedName']" :style="styleAnime"
  20. v-else-if="this.element['animatedType']==0">
  21. <div :highLightDelimitId="isOverView?'':element.nodeId" :elabEditable="element['elabEditable']||true"
  22. :style="styleBasic" :class="this.element['animatedFont'] ">{{ element.text }}</div>
  23. </div>
  24. <div :class="'animated ' + this.element['animatedName']" :style="styleAnime" v-else>
  25. <div :highLightDelimitId="isOverView?'':element.nodeId" :elabEditable="element['elabEditable']||true"
  26. :style="styleBasic" :class="this.element['animatedFont'] ">{{ element.text }}</div>
  27. </div>
  28. </section>
  29. </template>
  30. <elab-background-canvas v-else-if="element.eleCanvas=='WaterRipple'" :width="element.width" :height="element.height"
  31. :cstyle="`position:absolute;z-index: 1;border-radius:${element.circular+'%'}`" :type="element.eleCanvas"
  32. :picSrc="element.backgroundUnselectedImg">
  33. </elab-background-canvas>
  34. <Operate v-show="showOperate || show|| $store.state.editor.complexEditorElement.indexOf(element)>-1"
  35. @mousedown.native.stop="scaleMousedown" @mouseup.native.stop="scaleMouseup"
  36. @mousemove.native.stop="scaleMousemove" />
  37. </div>
  38. </template>
  39. <script>
  40. import Operate from '../Operate'
  41. import appConst from '../../util/appConst'
  42. import myfont from '../font/font'
  43. import elabBackgroundCanvas from '../../util/canvas/elabBackgroundCanvas'
  44. var body = document.body;
  45. export default {
  46. props: {
  47. element: {
  48. type: Object,
  49. require: true
  50. },
  51. showOperate: {
  52. type: Boolean
  53. },
  54. stopEvent: {
  55. type: Boolean
  56. },
  57. type: '',
  58. isOverView:Boolean
  59. },
  60. data() {
  61. return {
  62. left: 0,
  63. top: 0,
  64. width: 0,
  65. height: 0,
  66. currentX: 0,
  67. currentY: 0,
  68. flag: false,
  69. scaleFlag: false,
  70. direction: '',
  71. http: appConst.BACKEND_DOMAIN,
  72. show: false
  73. }
  74. },
  75. mounted() {
  76. window.addEventListener("mouseup", () => {
  77. this.$store.state.user.operationFlag = true;
  78. this.flag = false
  79. this.scaleFlag = false
  80. })
  81. },
  82. methods: {
  83. // 处理元素拖动
  84. move() {
  85. var body = document.body;
  86. // var editor = document.querySelector('.editor')
  87. document.querySelector('body').onmousemove = (event) => {
  88. var e = event || window.event
  89. if (this.flag && !this.scaleFlag) {
  90. let nowX = e.clientX
  91. let nowY = e.clientY
  92. let disX = nowX - this.currentX
  93. let disY = nowY - this.currentY
  94. if (this.$store.state.editor.complexEditorElement.indexOf(this.element) > -1 && this.$store.state.editor.complexEditorElement.length > 1) {
  95. this.$store.state.editor.complexEditorElement.forEach((ele, index) => {
  96. ele['top'] = disY + this.startTopArr[index]
  97. ele['left'] = ele.type == 'frame' ? 0 : disX + this.startLeftArr[index]
  98. });
  99. return;
  100. }
  101. this.element.top = parseInt(this.top) + disY
  102. this.element.left = parseInt(this.left) + disX
  103. }
  104. }
  105. },
  106. // 处理元素伸缩
  107. scaleMousemove() {
  108. document.querySelector('.editor').onmouseup = (event) => {
  109. this.scaleFlag = false
  110. }
  111. document.querySelector('.editor').onmousemove = (event) => {
  112. var e = event || window.event
  113. if (this.scaleFlag) {
  114. let nowX = e.clientX
  115. let nowY = e.clientY
  116. let disX = nowX - this.currentX
  117. let disY = nowY - this.currentY
  118. let ratio = this.width / this.height
  119. switch (this.direction) {
  120. // 左边
  121. case 'w':
  122. this.element.width = parseInt(this.width) - disX
  123. // this.element.height = parseInt(((this.width) - disX)/ratio)
  124. this.element.left = parseInt(this.left) + disX
  125. break
  126. // 右边
  127. case 'e':
  128. this.element.width = parseInt(this.width) + disX
  129. // this.element.height = parseInt(((this.width) + disX)/ratio)
  130. break
  131. // 上边
  132. case 'n':
  133. this.element.height = parseInt(this.height) - disY
  134. // this.element.width = parseInt(((this.height) - disY)*ratio)
  135. this.element.top = parseInt(this.top) + disY
  136. break
  137. // 下边
  138. case 's':
  139. this.element.height = parseInt(this.height) + disY
  140. // this.element.width = parseInt(((this.height) + disY)*ratio)
  141. break
  142. // 左上
  143. case 'nw':
  144. // this.element.width = parseInt(this.width) - disX
  145. this.element.width = parseInt(((this.height) - disY) * ratio)
  146. // this.element.left = parseInt(this.left) + disX
  147. this.element.left = parseInt(this.left + disY * ratio)
  148. this.element.height = parseInt(this.height) - disY
  149. this.element.top = parseInt(this.top) + disY
  150. break
  151. // 左下
  152. case 'sw':
  153. // this.element.width = parseInt(this.width) - disX
  154. this.element.width = parseInt(((this.height) + disY) * ratio)
  155. // this.element.left = parseInt(this.left) + disX
  156. this.element.left = parseInt(this.left - disY * ratio)
  157. this.element.height = parseInt(this.height) + disY
  158. break
  159. // 右上
  160. case 'ne':
  161. this.element.height = parseInt(this.height) - disY
  162. this.element.top = parseInt(this.top) + disY
  163. // this.element.width = parseInt(this.width) + disX
  164. this.element.width = parseInt(((this.height) - disY) * ratio)
  165. break
  166. // 右下
  167. case 'se':
  168. this.element.height = parseInt(this.height) + disY
  169. // this.element.width = parseInt(this.width) + disX
  170. this.element.width = parseInt(((this.height) + disY) * ratio)
  171. break
  172. }
  173. }
  174. }
  175. },
  176. mousedown(e) {
  177. this.$store.state.user.operationFlag = false;
  178. if (this.element.locked) {
  179. return false;
  180. }
  181. if (this.stopEvent) {
  182. return false
  183. }
  184. this.flag = true
  185. this.currentX = e.clientX
  186. this.currentY = e.clientY
  187. if (this.$store.state.editor.complexEditorElement.indexOf(this.element) > -1 && this.$store.state.editor.complexEditorElement.length > 1) {
  188. this.startTopArr = this.$store.state.editor.complexEditorElement.map(v => v.top)
  189. this.startLeftArr = this.$store.state.editor.complexEditorElement.map(v => v.left)
  190. }
  191. this.top = this.element.top
  192. this.left = this.element.left
  193. this.move()
  194. },
  195. mouseup(e) {
  196. this.$store.state.user.operationFlag = true;
  197. this.flag = false
  198. this.scaleFlag = false
  199. },
  200. mouseover(e) {
  201. if (this.$store.state.editor.editorPage.elements.indexOf(this.element) == -1) {
  202. return
  203. }
  204. this.show = true
  205. },
  206. mouseleave(e) {
  207. this.show = false
  208. },
  209. scaleMousedown(e) {
  210. this.$store.state.user.operationFlag = false;
  211. this.scaleFlag = true
  212. this.flag = true
  213. this.currentX = e.clientX
  214. this.currentY = e.clientY
  215. this.top = this.element.top
  216. this.left = this.element.left
  217. this.width = this.element.width
  218. this.height = this.element.height
  219. this.direction = e.target.getAttribute('data-direction')
  220. this.scaleMousemove()
  221. },
  222. scaleMouseup(e) {
  223. this.$store.state.user.operationFlag = true;
  224. this.scaleFlag = false
  225. this.flag = false
  226. },
  227. dragstart(event) {
  228. event.preventDefault()
  229. }
  230. },
  231. components: {
  232. Operate,
  233. myfont,
  234. elabBackgroundCanvas
  235. },
  236. computed: {
  237. editingElement () {
  238. return this.$store.getters['editingElement']
  239. },
  240. styleAnime () {
  241. var playing = this.element['playing']
  242. //粒子滚动效果
  243. if (this.element['animatedType'] == 1) {
  244. ////粒子滚动效果,如果设置了延迟播放大小,则进行判断,默认是不延迟,默认的虚线宽度是70
  245. if (this.element['delay'] ==0) {
  246. if (playing) {
  247. return {
  248. animationName: this.element['animatedName'],
  249. animationDuration: this.element['duration']+'s',
  250. animationTimingFunction: 'linear',
  251. animationIterationCount: (this.element['loop'] ? 'infinite' : 'initial'),
  252. }
  253. }
  254. //stroke动画不动的情况,stroke填充线条
  255. return {
  256. // animationName: this.element['animatedName'],
  257. strokeDasharray: '300 400',
  258. animationDuration: this.element['duration']+'s',
  259. animationTimingFunction: 'linear',
  260. animationIterationCount: (this.element['loop'] ? 'infinite' : 'initial'),
  261. }
  262. }
  263. return {
  264. animationName: this.element['animatedName'],
  265. animationDuration: this.element['duration']+'s',
  266. animationTimingFunction: 'linear',
  267. animationDelay: this.element['delay'] + 's',
  268. animationIterationCount: (this.element['loop'] ? 'infinite' : 'initial'),
  269. }
  270. } else if (this.element['animatedType'] == 2) { //类似抖音抖动动画
  271. var sharksScroll = {
  272. animationDirection: 'reverse',
  273. animationFillMode: 'none',
  274. animationPlayState: 'running',
  275. animationTimingFunction: 'cubic-bezier(0.68, -0.55, 0.27, 1.55)',
  276. animationDelay: this.element['delay'] + 's',
  277. animationIterationCount: (this.element['loop'] ? 'infinite' : 'initial'),
  278. animationDuration: this.element['duration']+'s',
  279. animationDelay: this.element['delay'] + 's',
  280. };
  281. if (playing) {
  282. sharksScroll = {
  283. animationDirection: 'reverse',
  284. animationFillMode: 'none',
  285. animationPlayState: 'running',
  286. animationName: this.element['animatedName'],
  287. animationTimingFunction: 'cubic-bezier(0.68, -0.55, 0.27, 1.55)',
  288. animationDelay: this.element['delay'] + 's',
  289. animationIterationCount: (this.element['loop'] ? 'infinite' : 'initial'),
  290. animationDuration: this.element['duration']+'s',
  291. animationDelay: this.element['delay'] + 's',
  292. }
  293. }
  294. return sharksScroll;
  295. }
  296. return {
  297. animationIterationCount: this.element['loop'] ? 'infinite' : 'initial',
  298. animationDuration: this.element['duration'] + 's',
  299. animationDelay: this.element['delay'] + 's'
  300. }
  301. },
  302. styleBasic () {
  303. return {
  304. width: this.element['width'] + 'px',
  305. height: this.element['height'] + 'px',
  306. lineHeight: this.element['lineHeight'],
  307. color: this.element['color'],
  308. backgroundColor: this.element['allTransparent'] || this.element['backgroundColor'],
  309. textAlign: this.element['textAlign'],
  310. fontSize: this.element['fontSize'] + 'px',
  311. fontWeight: this.element['fontWeight'],
  312. 'font-family': this.element['fontFamily'],
  313. opacity: this.element['opacity'] / 100,
  314. transform: 'rotate(' + this.element['transform'] + 'deg' + ')',
  315. 'vertical-align': this.element['verticalAlign'],
  316. display: this.element['display'],
  317. 'text-indent': this.element['textIndent'] + 'em',
  318. 'letter-spacing': this.element['letterSpacing'] + 'em',
  319. 'writing-mode' : this.element['verticalFont'],
  320. 'white-space' : this.element['verticalFont'] ? 'pre' : 'pre-wrap'
  321. }
  322. }
  323. },
  324. }
  325. </script>
  326. <style lang='less' scoped>
  327. .content {
  328. /*white-space: pre-wrap;*/
  329. word-wrap: break-word;
  330. position: absolute;
  331. top: 0;
  332. z-index: 3;
  333. }
  334. .wrap {
  335. position: absolute;
  336. cursor: move;
  337. }
  338. .wrap img {
  339. position: absolute;
  340. user-select: none;
  341. /*-webkit-user-drag: none;*/
  342. }
  343. </style>