Commit 7d685686 authored by rockyl's avatar rockyl

svga预览

素材尺寸统一管理
parent e8227960
<template>
<div :draggable="draggable" @dragstart="onDragstart" ref="playerContainer" :style="style">
</div>
</template>
<script>
import {mapActions} from 'vuex';
import {Player} from 'svgaplayerweb';
export default {
name: "SvgaPreviewView",
props: {
maxWidth: {
type: Number
},
maxHeight: {
type: Number
},
src: {
type: String
},
draggable: {
type: Boolean,
default: false,
},
},
data() {
return {
videoSize: {
width: 0,
height: 0,
}
}
},
computed: {
style() {
const {width, height} = this.videoSize;
return {
width: (this.maxWidth || width) + 'px',
height: (this.maxHeight || height) + 'px',
}
},
size() {
const {width, height} = this.videoSize;
return `${width}x${height}`;
},
},
watch: {
src(v, oldv) {
if(v !== oldv){
this.update();
}
}
},
mounted() {
let container = this.$refs.playerContainer;
this.player = new Player(container);
this.update();
},
methods: {
onDragstart(e){
this.$emit('dragstart', e);
},
async update() {
const player = this.player;
player.clear();
if(this.src){
let videoItem = await this.loadSvga(this.src);
this.videoSize.width = videoItem.videoSize.width;
this.videoSize.height = videoItem.videoSize.height;
this.$nextTick(() => {
player.setVideoItem(videoItem);
player.startAnimation();
});
}
},
...mapActions([
'loadSvga'
]),
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
...@@ -6,8 +6,13 @@ ...@@ -6,8 +6,13 @@
:disabled="!legalUrl" :disabled="!legalUrl"
:content="url" :content="url"
class="source-input" class="source-input"
popper-class="source-input-popover"
> >
<img style="max-width: 200px;" v-if="url" :src="url" alt=""/> <div class="wrapper">
<img style="max-width: 200px;" class="thumbnail alpha-image-background" v-if="!url.endsWith('.svga')" :src="url" alt=""/>
<svga-preview-view :max-width="200" class="thumbnail alpha-image-background" :max-height="200" v-if="url.endsWith('.svga')" :src="url" alt=""/>
<span>{{assetSize(url)}}</span>
</div>
<el-input slot="reference" :disabled="!editable" v-model="editValue" controls-position="right" :placeholder="defaultValue" <el-input slot="reference" :disabled="!editable" v-model="editValue" controls-position="right" :placeholder="defaultValue"
@change="onChange" @drop.native="drop" @dragover.native="dragOver"> @change="onChange" @drop.native="drop" @dragover.native="dragOver">
<el-button slot="append" icon="el-icon-aim" @click="locateAsset"></el-button> <el-button slot="append" icon="el-icon-aim" @click="locateAsset"></el-button>
...@@ -21,10 +26,11 @@ ...@@ -21,10 +26,11 @@
import CmdInputWrapper from "./CmdInputWrapper"; import CmdInputWrapper from "./CmdInputWrapper";
import {assetScheme, getInputDefaultValue} from "../../utils"; import {assetScheme, getInputDefaultValue} from "../../utils";
import events from "@/global-events.js" import events from "@/global-events.js"
import SvgaPreviewView from "../SvgaPreviewView";
export default { export default {
name: "SourceInput", name: "SourceInput",
components: {LinkableInputWrapper, CmdInputWrapper}, components: {SvgaPreviewView, LinkableInputWrapper, CmdInputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable'], props: ['value', 'container', 'property', 'propertyName', 'editable'],
data(){ data(){
return { return {
...@@ -40,7 +46,7 @@ ...@@ -40,7 +46,7 @@
}, },
url: function () { url: function () {
if (this.value) { if (this.value) {
if (this.value.indexOf(assetScheme) > -1) { if (this.value.startsWith(assetScheme)) {
let uuid = this.value.replace(assetScheme, ''); let uuid = this.value.replace(assetScheme, '');
let _ass = this.assets.find(a => a.uuid === uuid); let _ass = this.assets.find(a => a.uuid === uuid);
return _ass ? _ass.url : ''; return _ass ? _ass.url : '';
...@@ -54,7 +60,7 @@ ...@@ -54,7 +60,7 @@
legalUrl: function () { legalUrl: function () {
return this.value && this.value.startsWith(assetScheme); return this.value && this.value.startsWith(assetScheme);
}, },
...mapGetters(['assets']), ...mapGetters(['assets', 'assetSize']),
}, },
methods: { methods: {
getEditValue() { getEditValue() {
...@@ -68,7 +74,8 @@ ...@@ -68,7 +74,8 @@
drop(e) { drop(e) {
if (this.$store.state.project.dragUUID) { if (this.$store.state.project.dragUUID) {
console.log('native drop', this.$store.state); console.log('native drop', this.$store.state);
this.onChange(assetScheme + this.$store.state.project.dragUUID) this.editValue = assetScheme + this.$store.state.project.dragUUID;
this.onChange(this.editValue)
} }
}, },
dragOver(e) { dragOver(e) {
......
...@@ -4,9 +4,12 @@ ...@@ -4,9 +4,12 @@
* 环境 * 环境
*/ */
import Vue from "vue";
import {envApi} from "../../api"; import {envApi} from "../../api";
import {Parser} from "svgaplayerweb";
const storeKey = 'code-sync-serve-config'; const storeKey = 'code-sync-serve-config';
const svgaParser = new Parser();
export const editorStore = { export const editorStore = {
state: { state: {
...@@ -21,7 +24,10 @@ export const editorStore = { ...@@ -21,7 +24,10 @@ export const editorStore = {
autoLaunch: false, autoLaunch: false,
ip: 'localhost', ip: 'localhost',
port: 7788, port: 7788,
} },
svgaCache: {},
svgaLoadingQueue: {},
assetSizeCache: {},
}, },
mutations: { mutations: {
updateEnv(state, env) { updateEnv(state, env) {
...@@ -40,6 +46,13 @@ export const editorStore = { ...@@ -40,6 +46,13 @@ export const editorStore = {
}, },
}, },
getters: { getters: {
assetSize: state => url => {
let size = state.assetSizeCache[url];
if(size){
return `${size.width}x${size.height}`
}
return '0x0';
}
}, },
actions: { actions: {
async updateEnv({state, commit}) { async updateEnv({state, commit}) {
...@@ -48,5 +61,67 @@ export const editorStore = { ...@@ -48,5 +61,67 @@ export const editorStore = {
commit('updateEnv', env); commit('updateEnv', env);
} }
}, },
loadSvga({state, commit}, url) {
const {svgaCache, svgaLoadingQueue} = state;
return new Promise((resolve, reject) => {
let videoItem = svgaCache[url];
if (videoItem) {
resolve(videoItem);
} else if (svgaLoadingQueue[url]) {
svgaLoadingQueue[url].push({resolve, reject});
} else {
svgaLoadingQueue[url] = [{resolve, reject}];
svgaParser.load(url, (videoItem) => {
let queue = svgaLoadingQueue[url];
svgaCache[url] = videoItem;
while (queue.length > 0) {
let item = queue.shift();
item.resolve(videoItem);
}
delete svgaLoadingQueue[url];
}, (e) => {
let queue = svgaLoadingQueue[url];
while (queue.length > 0) {
let item = queue.shift();
item.reject(e);
}
delete svgaLoadingQueue[url];
}
)
}
})
},
async updateAssetSize({state, commit, dispatch}, url) {
let size = state.assetSizeCache[url];
if (!size) {
let extname = url.substr(url.lastIndexOf('.'));
switch (extname) {
case '.svga':
let data = await dispatch('loadSvga', url);
Vue.set(state.assetSizeCache, url, data.videoSize);
break;
case '.jpg':
case '.png':
case '.gif':
case '.svg':
await new Promise((resolve, reject) => {
let img = new Image();
img.onload = function () {
let size = {
width: img.width,
height: img.height,
};
Vue.set(state.assetSizeCache, url, size);
resolve(size);
};
img.onerror = function (e) {
reject(e);
};
img.src = url;
});
break;
}
}
},
} }
}; };
...@@ -482,6 +482,14 @@ $dock-pin-width: 9px; ...@@ -482,6 +482,14 @@ $dock-pin-width: 9px;
} }
} }
.source-input-popover{
.wrapper{
display: flex;
flex-direction: column;
align-items: center;
}
}
.enum-input-comment{ .enum-input-comment{
float: right; float: right;
color: $--color-text-secondary; color: $--color-text-secondary;
......
...@@ -13,6 +13,10 @@ ...@@ -13,6 +13,10 @@
</div> </div>
<div class="item"> <div class="item">
<p>
<span>size</span>:
<span>{{assetSize(currentItem.url)}}</span>
</p>
<p v-for="(field, index) in showFields" :key="index"> <p v-for="(field, index) in showFields" :key="index">
<span>{{field}}</span>: <span>{{field}}</span>:
<span>{{currentItem[field]}}</span> <span>{{currentItem[field]}}</span>
...@@ -57,13 +61,13 @@ ...@@ -57,13 +61,13 @@
} }
}, },
computed: { computed: {
...mapGetters(['assets']), ...mapGetters(['assets', 'assetSize']),
}, },
mounted() { mounted() {
this.currentItem = null; this.currentItem = null;
events.$on('select-asset-item', this.selectAssetItem); events.$on('select-asset-item', this.selectAssetItem);
}, },
destroyed(){ destroyed() {
events.$off('select-asset-item', this.selectAssetItem); events.$off('select-asset-item', this.selectAssetItem);
}, },
methods: { methods: {
...@@ -93,7 +97,7 @@ ...@@ -93,7 +97,7 @@
this.$refs.assetsShow.show(asset); this.$refs.assetsShow.show(asset);
}, },
onItemClick(asset) { onItemClick(asset) {
this.currentItem = asset; this.selectAssetItem(asset);
}, },
deleteAll() { deleteAll() {
this.$confirm(this.$t('Are you sure to delete all assets'), this.$t('Alert'), { this.$confirm(this.$t('Are you sure to delete all assets'), this.$t('Alert'), {
...@@ -105,7 +109,8 @@ ...@@ -105,7 +109,8 @@
}).catch((e) => { }).catch((e) => {
}); });
}, },
selectAssetItem(asset){ selectAssetItem(asset) {
this.updateAssetSize(asset.url);
this.currentItem = asset; this.currentItem = asset;
this.$refs.assetList.selectItem(asset); this.$refs.assetList.selectItem(asset);
}, },
...@@ -114,6 +119,7 @@ ...@@ -114,6 +119,7 @@
]), ]),
...mapActions([ ...mapActions([
'uploadFiles', 'uploadFiles',
'updateAssetSize',
]), ]),
} }
} }
......
<template> <template>
<div class="file-item" @click="$emit('click', $event)"> <div class="file-item" @click="$emit('click', $event)">
<div class="icon"> <div class="icon">
<i @dragstart="assetDragStart(data)" v-if="!showThumbnail" draggable="true" class="file-icon" <i @dragstart="assetDragStart(data)" v-if="showIcon" draggable="true" class="file-icon"
:class="fileIcon"></i> :class="fileIcon"></i>
<img @dragstart="assetDragStart(data)" v-if="showThumbnail" draggable="true" <img @dragstart="assetDragStart(data)" v-if="showThumbnail" draggable="true"
class="thumbnail alpha-image-background" :src="thumbnailUrl" class="thumbnail alpha-image-background" :src="thumbnailUrl"
alt="thumb" @dblclick="onDbclick()"> alt="thumb" @dblclick="onDbclick()">
<svga-preview-view @dragstart="assetDragStart(data)" draggable class="alpha-image-background" v-if="showSvga"
:max-width="60"
:max-height="60"
:src="thumbnailUrl"></svga-preview-view>
<div v-if="editable" class="operate-bar"> <div v-if="editable" class="operate-bar">
<!--<el-button class="micro" circle plain size="mini" type="success" icon="icon-upload" @dblclick.native.stop <!--<el-button class="micro" circle plain size="mini" type="success" icon="icon-upload" @dblclick.native.stop
@click="onClickReplace"/>--> @click="onClickReplace"/>-->
...@@ -46,9 +50,11 @@ ...@@ -46,9 +50,11 @@
import {mapMutations, mapActions} from "vuex"; import {mapMutations, mapActions} from "vuex";
import {fileTypeIcon} from "../../../config"; import {fileTypeIcon} from "../../../config";
import {selectFile, strEllipsis} from "../../../utils"; import {selectFile, strEllipsis} from "../../../utils";
import SvgaPreviewView from "../../../components/SvgaPreviewView";
export default { export default {
name: "FileItem", name: "FileItem",
components: {SvgaPreviewView},
props: { props: {
data: {type: Object}, data: {type: Object},
editable: {type: Boolean, default: false}, editable: {type: Boolean, default: false},
...@@ -68,6 +74,12 @@ ...@@ -68,6 +74,12 @@
showThumbnail() { showThumbnail() {
return fileTypeIcon[this.data.ext] === 't'; return fileTypeIcon[this.data.ext] === 't';
}, },
showSvga() {
return this.data.ext === '.svga';
},
showIcon() {
return !this.showThumbnail && !this.showSvga;
},
thumbnailUrl() { thumbnailUrl() {
return this.data.url; return this.data.url;
}, },
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
<div class="mapping-list"> <div class="mapping-list">
<div class="list" v-if="customMeta"> <div class="list" v-if="customMeta">
<div class="item" v-for="(item, index) in customMeta.assets" :key="index"> <div class="item" v-for="(item, index) in customMeta.assets" :key="index">
<span class="name">{{item.name}}</span> <span class="name">{{item.name}}({{assetSize(item.url)}})</span>
<div class="diff"> <div class="diff">
<div class="side left"> <div class="side left">
<span class="extname"> <span class="extname">
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
</span> </span>
<div class="thumbnail"> <div class="thumbnail">
<img class="alpha-image-background" v-if="showThumbnail(item.ext)" :src="item.url"> <img class="alpha-image-background" v-if="showThumbnail(item.ext)" :src="item.url">
<svga-preview-view class="alpha-image-background" v-if="item.ext === '.svga'"
:max-width="100"
:max-height="100"
:src="item.url"></svga-preview-view>
</div> </div>
<el-input size="mini" v-model="item.url" readonly/> <el-input size="mini" v-model="item.url" readonly/>
</div> </div>
...@@ -28,7 +32,11 @@ ...@@ -28,7 +32,11 @@
</span>--> </span>-->
<div class="thumbnail"> <div class="thumbnail">
<img class="alpha-image-background" v-if="item.replace && showThumbnail(item.ext)" <img class="alpha-image-background" v-if="item.replace && showThumbnail(item.ext)"
:src="resolveImg(item)"> :src="resolveSrc(item)">
<svga-preview-view class="alpha-image-background" v-if="item.replace && item.ext === '.svga'"
:max-width="100"
:max-height="100"
:src="resolveSrc(item)"></svga-preview-view>
</div> </div>
<el-input size="mini" v-model="item.replace" clearable> <el-input size="mini" v-model="item.replace" clearable>
<el-button slot="append" icon="el-icon-brush" @click="onClickReplace(item)"/> <el-button slot="append" icon="el-icon-brush" @click="onClickReplace(item)"/>
...@@ -51,16 +59,17 @@ ...@@ -51,16 +59,17 @@
</template> </template>
<script> <script>
import {mapMutations, mapState, mapGetters} from 'vuex'; import {mapMutations, mapState, mapGetters, mapActions} from 'vuex';
import {fileTypeIcon} from "../../../../config"; import {fileTypeIcon} from "../../../../config";
import SelectAssetDialog from "../SelectAssetDialog"; import SelectAssetDialog from "../SelectAssetDialog";
import {clonePureObj} from "../../../../utils"; import {clonePureObj} from "../../../../utils";
import SvgaPreviewView from "../../../../components/SvgaPreviewView";
const linkScheme = 'link://'; const linkScheme = 'link://';
export default { export default {
name: "AssetMappingEditorDialog", name: "AssetMappingEditorDialog",
components: {SelectAssetDialog}, components: {SvgaPreviewView, SelectAssetDialog},
data() { data() {
return { return {
visible: false, visible: false,
...@@ -75,13 +84,14 @@ ...@@ -75,13 +84,14 @@
...mapGetters([ ...mapGetters([
'assets', 'assets',
'customPackages', 'customPackages',
'assetSize',
]) ])
}, },
methods: { methods: {
showThumbnail(ext) { showThumbnail(ext) {
return fileTypeIcon[ext] === 't'; return fileTypeIcon[ext] === 't';
}, },
resolveImg(item) { resolveSrc(item) {
let url; let url;
const replace = item.replace; const replace = item.replace;
if (replace.startsWith(linkScheme)) { if (replace.startsWith(linkScheme)) {
...@@ -107,6 +117,9 @@ ...@@ -107,6 +117,9 @@
show(data) { show(data) {
this.mid = data.id; this.mid = data.id;
this.customMeta = clonePureObj(this.customPackages[this.mid]); this.customMeta = clonePureObj(this.customPackages[this.mid]);
for(let asset of this.customMeta.assets){
this.updateAssetSize(asset.url);
}
for (let uuid in data.assetMapping) { for (let uuid in data.assetMapping) {
let asset = this.customMeta.assets.find(item => item.uuid === uuid); let asset = this.customMeta.assets.find(item => item.uuid === uuid);
...@@ -135,6 +148,7 @@ ...@@ -135,6 +148,7 @@
}, },
...mapMutations([]), ...mapMutations([]),
...mapActions(['updateAssetSize']),
} }
} }
</script> </script>
...@@ -153,11 +167,11 @@ ...@@ -153,11 +167,11 @@
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
.name{ .name {
text-align: center; text-align: center;
} }
.diff{ .diff {
position: relative; position: relative;
border: 1px solid lightgray; border: 1px solid lightgray;
border-radius: 5px; border-radius: 5px;
......
...@@ -8102,6 +8102,11 @@ svg-tags@^1.0.0: ...@@ -8102,6 +8102,11 @@ svg-tags@^1.0.0:
resolved "https://registry.npm.taobao.org/svg-tags/download/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" resolved "https://registry.npm.taobao.org/svg-tags/download/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=
svgaplayerweb@^2.3.0:
version "2.3.0"
resolved "https://registry.npmjs.org/svgaplayerweb/-/svgaplayerweb-2.3.0.tgz#417e2620e68f9ba616037a0feeb93354cb63d545"
integrity sha512-o4hcgA3mW0rmt8n9/z8NXrPGhPnmLndKOLoGAVL+nd6S+aOIojDpnZ4nK3PAw9F4xrOA06FqI3VkEsVHVLNYVA==
svgo@^1.0.0: svgo@^1.0.0:
version "1.3.2" version "1.3.2"
resolved "https://registry.npm.taobao.org/svgo/download/svgo-1.3.2.tgz?cache=0&sync_timestamp=1572433263159&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsvgo%2Fdownload%2Fsvgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" resolved "https://registry.npm.taobao.org/svgo/download/svgo-1.3.2.tgz?cache=0&sync_timestamp=1572433263159&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsvgo%2Fdownload%2Fsvgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment