| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- import '@/scss/iconfont/iconfont.css'
- import domToImage from 'dom-to-image'
- import {
- getProgram,
- updateProgram
- } from '@/api/program'
- import {
- getAssetUrl,
- getThumbnailUrl
- } from '@/api/asset'
- import {
- create,
- fix,
- getDuration,
- toJSON
- } from './utils'
- export default {
- provide () {
- return {
- control: this
- }
- },
- data () {
- return {
- program: null,
- snapping: false,
- loading: true,
- scale: 100,
- minScale: 100,
- maxScale: 100,
- padding: 0,
- selectedWidgetIndex: -1,
- node: null,
- bgm: '',
- muted: true
- }
- },
- computed: {
- transformStyles () {
- return {
- transform: `scale(${this.scale / 100})`,
- 'transform-origin': '0 0'
- }
- },
- styles () {
- if (this.node) {
- const { width, height, backgroundColor, backgroundImage } = this.node
- return {
- width: `${width}px`,
- height: `${height}px`,
- color: backgroundColor,
- 'background-image': backgroundImage[0] ? `url("${getThumbnailUrl(backgroundImage[0].keyName)}")` : 'none'
- }
- }
- return {}
- },
- widgets () {
- return this.node?.widgets || []
- },
- widget () {
- return this.widgets[this.selectedWidgetIndex] || this.node
- },
- hasAudio () {
- if (this.node) {
- if (this.node.bgm.length) {
- return true
- }
- return this.node.widgets.some(widget => widget.mute === 0 && (widget.sources?.length || widget.url))
- }
- return false
- },
- bgmUrl () {
- return this.bgm ? getAssetUrl(this.bgm) : ''
- },
- hasNext () {
- return !this.muted && this.node?.bgm.length > 1
- }
- },
- created () {
- this.fetch()
- },
- beforeRouteUpdate () {
- window.close()
- },
- beforeRouteLeave () {
- window.close()
- },
- watch: {
- 'node.bgm' () {
- this.setBgm()
- }
- },
- methods: {
- toggleMute () {
- this.muted = !this.muted
- },
- setBgm () {
- this.$bgmIndex = 0
- this.chooseBgm()
- },
- chooseBgm () {
- const { bgm, toggleType } = this.node
- const length = bgm.length
- if (length === 0) {
- this.bgm = ''
- return
- }
- if (length === 1) {
- this.bgm = bgm[0].keyName
- return
- }
- let index
- switch (toggleType) {
- case 'cycle':
- index = this.$bgmIndex
- this.$bgmIndex = (index + 1) % length
- break
- case 'random':
- index = Math.random() * length | 0
- if (bgm[index]?.keyName === this.bgm) {
- if (index === 0) {
- index += 1
- } else {
- index -= 1
- }
- }
- break
- default:
- return
- }
- this.bgm = bgm[index].keyName
- },
- onAudioEnded () {
- if (this.node.bgm.length > 1) {
- this.chooseBgm()
- }
- this.$refs.audio.play()
- },
- onAudioError (e) {
- console.warn('audio error', e)
- if (this.node?.bgm.length > 1) {
- this.chooseBgm()
- }
- },
- checkRatio () {
- const wrapper = this.$refs.wrapper
- if (wrapper && this.node) {
- const width = wrapper.offsetWidth - this.padding * 2
- const height = wrapper.offsetHeight - this.padding * 2
- const { width: cWidth, height: cHeight } = this.node
- const wScale = width / cWidth
- const hScale = height / cHeight
- if (cWidth > width || cHeight > height) {
- this.scale = Math.min(wScale, hScale) * 100 | 0
- this.maxScale = Math.max(1, wScale, hScale) * 100 | 0
- } else {
- this.scale = 100
- this.maxScale = Math.max(2, wScale, hScale) * 100 | 0
- }
- this.minScale = this.scale
- console.log('width: layout -> window', cWidth, '->', width, wScale)
- console.log('height: layout -> window', cHeight, '->', height, hScale)
- console.log(this.scale, this.maxScale)
- }
- },
- showMessage (type, message) {
- let count = 3
- const loading = this.$loading({
- lock: true,
- text: `${message},${count}秒后自动关闭`,
- spinner: `el-icon-${type}`,
- background: 'rgba(0, 0, 0, .8)',
- customClass: `c-lock ${type}`
- })
- const timer = setInterval(() => {
- count -= 1
- if (count === 0) {
- clearInterval(timer)
- window.close()
- } else {
- loading.text = `${message},${count}秒后自动关闭`
- }
- }, 1000)
- },
- initCanvas (canvas) {
- this.node = create(canvas)
- console.log(this.node)
- },
- checkStatus (status) {
- return true
- },
- onLoaded () { },
- fetch () {
- this.loading = true
- getProgram(this.$route.params.id).then(({ data }) => {
- try {
- if (!this.checkStatus(data.status)) {
- this.showMessage('warning', '布局已锁定')
- return
- }
- this.program = data
- const { resolutionRatio, itemJsonStr } = data
- const [width, height] = resolutionRatio.split('x')
- if (!width || !height) {
- this.showMessage('warning', '布局分辨率异常')
- return
- }
- this.initCanvas({
- width: Number(width),
- height: Number(height),
- ...JSON.parse(itemJsonStr)
- })
- this.checkRatio()
- window.addEventListener('resize', this.checkRatio)
- this.onLoaded()
- } catch (e) {
- this.showMessage('error', '布局解析失败')
- }
- }, err => {
- this.showMessage('error', err.errMessage || '获取布局失败')
- }).finally(() => {
- this.loading = false
- })
- },
- check () {
- const warning = fix(this.node)
- if (warning) {
- return this.$confirm(
- `${warning},确定保存?`,
- '提示',
- {
- type: 'warning',
- confirmButtonText: '确定',
- cancelButtonText: '取消'
- }
- )
- }
- return Promise.resolve()
- },
- async _save () {
- try {
- const base64 = await this.snap()
- const result = await updateProgram({
- id: this.program.id,
- duration: getDuration(this.node),
- itemJsonStr: JSON.stringify(toJSON(this.node)),
- base64
- })
- if (result) {
- window.opener?.postMessage({
- id: this.program.id,
- base64
- })
- this.$message({
- type: 'success',
- message: '保存成功'
- })
- } else {
- this.$message({
- type: 'warning',
- message: '保存失败'
- })
- }
- } catch (e) {
- console.warn(e)
- this.$message({
- type: 'warning',
- message: '保存失败'
- })
- }
- },
- save () {
- this.check().then(() => {
- this.selectedWidgetIndex = -1
- this.loading = true
- this.$nextTick(() => {
- this._save().finally(() => {
- this.loading = false
- })
- })
- })
- },
- snap () {
- this.snapping = true
- return domToImage.toJpeg(this.$refs.canvas, {
- filter (node) {
- const { tagName } = node
- if (tagName === 'CANVAS') {
- return /^data:.+;base64,.+/.test(node.toDataURL())
- }
- return tagName !== 'VIDEO' && tagName !== 'IFRAME'
- },
- width: this.node.width * this.scale / 100 | 0,
- height: this.node.height * this.scale / 100 | 0,
- quality: 0.1
- }).finally(() => {
- this.snapping = false
- })
- }
- }
- }
|