app-announcement.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. <template>
  2. <view>
  3. <view class="app-announcement" :style="{backgroundColor:background}">
  4. <app-form-id>
  5. <view class="app-announcement-view cross-center" @click="show">
  6. <view class="dir-left-wrap">
  7. <image class="app-icon-left" :src="icon ? icon : '/static/image/icon/icon-notice.png'" ></image>
  8. <text class="app-text app-name" :style="{color: textColor}">{{name}}</text>
  9. </view>
  10. <view class="content">
  11. <view class="content-child" :animation="animationData">
  12. <text :style="{color: textColor,}">{{content}}</text>
  13. </view>
  14. </view>
  15. </view>
  16. </app-form-id>
  17. </view>
  18. <view class="app-spring-board" v-show="showHidden">
  19. <view class="app-transparent-frame">
  20. <view class="app-top-image" :style="{backgroundImage: `url(${headerUrl})`}" v-if="headerUrl"></view>
  21. <view class="app-top-image icon" v-else></view>
  22. <view class="app-bottom-content">
  23. <scroll-view scroll-y class="app-text-content">
  24. <view>
  25. {{content}}
  26. </view>
  27. </scroll-view>
  28. <view class="app-content-button" :style="{width: `${btnWidth}rpx`}">
  29. <app-form-id>
  30. <app-button @click="showHidden=false"
  31. :color="btnTextColor"
  32. :background="btnColor"
  33. fontSize="31"
  34. type="important"
  35. :roundSize="btnRadius">
  36. {{btnText}}
  37. </app-button>
  38. </app-form-id>
  39. </view>
  40. </view>
  41. </view>
  42. </view>
  43. </view>
  44. </template>
  45. <script>
  46. export default {
  47. name: 'app-announcement',
  48. props: {
  49. background: {
  50. type: String,
  51. default() {
  52. return '#f67f79';
  53. }
  54. },
  55. btnColor: {
  56. type: String,
  57. default() {
  58. return '#ff4544';
  59. }
  60. },
  61. btnHeight: {
  62. type: Number,
  63. default() {
  64. return 80;
  65. }
  66. },
  67. btnRadius: {
  68. type: String,
  69. default() {
  70. return '40rpx';
  71. }
  72. },
  73. btnText: {
  74. type: String,
  75. default() {
  76. return '我知道了';
  77. }
  78. },
  79. btnTextColor: {
  80. type: String,
  81. default() {
  82. return '#ffffff';
  83. }
  84. },
  85. btnWidth: {
  86. type: Number,
  87. default() {
  88. return 500;
  89. }
  90. },
  91. content: {
  92. type: String,
  93. default() {
  94. return '';
  95. }
  96. },
  97. headerUrl: {
  98. type: String,
  99. default() {
  100. return '';
  101. }
  102. },
  103. icon: {
  104. type: String,
  105. default() {
  106. return '';
  107. }
  108. },
  109. name: {
  110. type: String,
  111. default() {
  112. return '公告';
  113. }
  114. },
  115. textColor: {
  116. type: String,
  117. default() {
  118. return '#ffffff';
  119. }
  120. },
  121. },
  122. data() {
  123. return {
  124. showHidden: false,
  125. speed: 2000,
  126. animationData: null,
  127. animationTime: null,
  128. againTime: null,
  129. over: false,
  130. animation: {},
  131. duration: 0,
  132. }
  133. },
  134. methods: {
  135. show() {
  136. this.showHidden = true;
  137. },
  138. initAnimation() {
  139. let speed = this.content.length > 10 ? this.speed : 2000 + (10 - this.content.length) * 700;
  140. this.duration = this.content.length * 26 / 40 * speed;
  141. this.animation = uni.createAnimation({
  142. transformOrigin: "50% 50%",
  143. duration: this.duration,
  144. timingFunction: "linear",
  145. delay: 0,
  146. });
  147. },
  148. startAnimation() {
  149. // #ifdef MP-WEIXIN
  150. if (this.animation.option.transition.duration !== 0) {
  151. this.animation.option.transition.duration = 0;
  152. const resetAnimation = this.animation.translateX(this.content.length).step();
  153. this.animationData = resetAnimation.export();
  154. }
  155. this.animation.option.transition.duration = this.duration;
  156. // #endif
  157. // #ifdef MP-ALIPAY
  158. if (this.animation.config.duration !== 0) {
  159. this.animation.config.duration = 0;
  160. const resetAnimation = this.animation.translateX(this.content.length).step();
  161. this.animationData = resetAnimation.export();
  162. }
  163. this.animation.config.duration = this.duration;
  164. // #endif
  165. // #ifdef MP-TOUTIAO
  166. if (this.animation.option.duration !== 0) {
  167. this.animation.option.duration = 0;
  168. const resetAnimation = this.animation.translateX(this.content.length).step();
  169. this.animationData = resetAnimation.export();
  170. }
  171. this.animation.option.duration = this.duration;
  172. // #endif
  173. // #ifdef MP-BAIDU
  174. if (this.animation.duration !== 0) {
  175. this.animation.duration = 0;
  176. const resetAnimation = this.animation.translateX(this.content.length).step();
  177. this.animationData = resetAnimation.export();
  178. }
  179. this.animation.duration = this.duration;
  180. // #endif
  181. this.animation.translateX(-this.content.length * 26).step();
  182. setTimeout(() => {
  183. this.animationData = this.animation.export();
  184. }, 1000);
  185. let t = this.duration >= 52000 ? this.duration/2.5 : this.duration/1.5;
  186. this.againTime = setTimeout(() => {
  187. this.startAnimation();
  188. }, t);
  189. }
  190. },
  191. watch: {
  192. content: {
  193. handler: function(value) {
  194. if (value && !this.over) {
  195. this.initAnimation();
  196. this.startAnimation();
  197. this.over = true;
  198. }
  199. },
  200. immediate: true,
  201. deep: true,
  202. }
  203. },
  204. destroyed() {
  205. clearTimeout(this.animationTime);
  206. clearTimeout(this.againTime);
  207. }
  208. }
  209. </script>
  210. <style scoped lang="scss">
  211. .app-announcement {
  212. width: #{750rpx};
  213. height: #{72rpx};
  214. font-size: #{28rpx};
  215. }
  216. .content {
  217. position: relative;
  218. flex: 1;
  219. margin: #{0 30rpx};
  220. overflow: hidden;
  221. text-overflow: ellipsis;
  222. white-space: nowrap;
  223. height: #{72rpx};
  224. .content-child {
  225. height: #{72rpx};
  226. line-height: #{72rpx};
  227. position: absolute;
  228. >text {
  229. width: 100%;
  230. white-space: nowrap;
  231. }
  232. }
  233. }
  234. .app-announcement-view {
  235. width: #{750rpx};
  236. height: #{72rpx};
  237. position: relative;
  238. }
  239. .app-text-one {
  240. font-size:#{26rpx};
  241. white-space:nowrap;
  242. }
  243. .app-icon-left {
  244. width: #{36rpx};
  245. height: #{36rpx};
  246. margin-left: #{24rpx};
  247. margin-right: #{20rpx};
  248. }
  249. .app-icon-right {
  250. width: #{14rpx};
  251. height: #{24rpx};
  252. margin-right: #{4rpx};
  253. }
  254. .app-text {
  255. font-size:#{26rpx};
  256. overflow: hidden;
  257. word-break:keep-all;
  258. white-space:nowrap;
  259. }
  260. .app-name {
  261. max-width: #{180rpx};
  262. margin-right: #{10rpx};
  263. text-overflow: ellipsis;
  264. overflow: hidden;
  265. white-space: nowrap;
  266. display: inline-block;
  267. }
  268. .app-content-frame {
  269. overflow: hidden;
  270. width: #{560rpx};
  271. text-overflow: ellipsis;
  272. white-space: nowrap;
  273. position: relative;
  274. height: #{72rpx};
  275. }
  276. .app-animate {
  277. position: absolute;
  278. top: 50%;
  279. transform: translateY(-50%);
  280. }
  281. .app-content {
  282. /*width:100%;*/
  283. display: block;
  284. transform: translateX(-50%);
  285. animation: mymove 100.5s infinite;
  286. }
  287. @keyframes mymove
  288. {
  289. 0% {
  290. transform: translateX(0%);
  291. }
  292. 100% {
  293. transform: translateX(-100%);
  294. }
  295. }
  296. .app-spring-board {
  297. width: 100%;
  298. height: 100%;
  299. position: fixed;
  300. top: 0;
  301. z-index: 1600;
  302. background-color: rgba(153, 153,153,0.7);
  303. }
  304. .app-transparent-frame {
  305. height: #{540rpx};
  306. width: #{600rpx};
  307. position: absolute;
  308. top: 50%;
  309. left: 50%;
  310. transform: translate(-50%, -50%);
  311. }
  312. .app-top-image {
  313. height: #{150rpx};
  314. width: #{600rpx};
  315. background-repeat: no-repeat;
  316. background-size: cover;
  317. &.icon {
  318. background-image: url("../../../static/image/icon/announcement.png");
  319. }
  320. }
  321. .app-text-content {
  322. display: block;
  323. min-height: #{144rpx};
  324. max-height: #{285rpx};
  325. width: #{500rpx};
  326. margin-bottom: #{66rpx};
  327. word-break: break-all;
  328. line-height: #{48rpx};
  329. }
  330. .app-bottom-content {
  331. background-color: #ffffff;
  332. padding: #{50rpx};
  333. border-bottom-right-radius: #{11rpx};
  334. border-bottom-left-radius: #{11rpx};
  335. .app-content-button {
  336. margin: 0 auto;
  337. }
  338. }
  339. </style>