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 @@
:disabled="!legalUrl"
:content="url"
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"
@change="onChange" @drop.native="drop" @dragover.native="dragOver">
<el-button slot="append" icon="el-icon-aim" @click="locateAsset"></el-button>
......@@ -21,10 +26,11 @@
import CmdInputWrapper from "./CmdInputWrapper";
import {assetScheme, getInputDefaultValue} from "../../utils";
import events from "@/global-events.js"
import SvgaPreviewView from "../SvgaPreviewView";
export default {
name: "SourceInput",
components: {LinkableInputWrapper, CmdInputWrapper},
components: {SvgaPreviewView, LinkableInputWrapper, CmdInputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable'],
data(){
return {
......@@ -40,7 +46,7 @@
},
url: function () {
if (this.value) {
if (this.value.indexOf(assetScheme) > -1) {
if (this.value.startsWith(assetScheme)) {
let uuid = this.value.replace(assetScheme, '');
let _ass = this.assets.find(a => a.uuid === uuid);
return _ass ? _ass.url : '';
......@@ -54,7 +60,7 @@
legalUrl: function () {
return this.value && this.value.startsWith(assetScheme);
},
...mapGetters(['assets']),
...mapGetters(['assets', 'assetSize']),
},
methods: {
getEditValue() {
......@@ -68,7 +74,8 @@
drop(e) {
if (this.$store.state.project.dragUUID) {
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) {
......
......@@ -4,9 +4,12 @@
* 环境
*/
import Vue from "vue";
import {envApi} from "../../api";
import {Parser} from "svgaplayerweb";
const storeKey = 'code-sync-serve-config';
const svgaParser = new Parser();
export const editorStore = {
state: {
......@@ -21,7 +24,10 @@ export const editorStore = {
autoLaunch: false,
ip: 'localhost',
port: 7788,
}
},
svgaCache: {},
svgaLoadingQueue: {},
assetSizeCache: {},
},
mutations: {
updateEnv(state, env) {
......@@ -40,6 +46,13 @@ export const editorStore = {
},
},
getters: {
assetSize: state => url => {
let size = state.assetSizeCache[url];
if(size){
return `${size.width}x${size.height}`
}
return '0x0';
}
},
actions: {
async updateEnv({state, commit}) {
......@@ -48,5 +61,67 @@ export const editorStore = {
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;
}
}
.source-input-popover{
.wrapper{
display: flex;
flex-direction: column;
align-items: center;
}
}
.enum-input-comment{
float: right;
color: $--color-text-secondary;
......
......@@ -13,6 +13,10 @@
</div>
<div class="item">
<p>
<span>size</span>:
<span>{{assetSize(currentItem.url)}}</span>
</p>
<p v-for="(field, index) in showFields" :key="index">
<span>{{field}}</span>:
<span>{{currentItem[field]}}</span>
......@@ -57,13 +61,13 @@
}
},
computed: {
...mapGetters(['assets']),
...mapGetters(['assets', 'assetSize']),
},
mounted() {
this.currentItem = null;
events.$on('select-asset-item', this.selectAssetItem);
},
destroyed(){
destroyed() {
events.$off('select-asset-item', this.selectAssetItem);
},
methods: {
......@@ -93,7 +97,7 @@
this.$refs.assetsShow.show(asset);
},
onItemClick(asset) {
this.currentItem = asset;
this.selectAssetItem(asset);
},
deleteAll() {
this.$confirm(this.$t('Are you sure to delete all assets'), this.$t('Alert'), {
......@@ -105,7 +109,8 @@
}).catch((e) => {
});
},
selectAssetItem(asset){
selectAssetItem(asset) {
this.updateAssetSize(asset.url);
this.currentItem = asset;
this.$refs.assetList.selectItem(asset);
},
......@@ -114,6 +119,7 @@
]),
...mapActions([
'uploadFiles',
'updateAssetSize',
]),
}
}
......
<template>
<div class="file-item" @click="$emit('click', $event)">
<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>
<img @dragstart="assetDragStart(data)" v-if="showThumbnail" draggable="true"
class="thumbnail alpha-image-background" :src="thumbnailUrl"
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">
<!--<el-button class="micro" circle plain size="mini" type="success" icon="icon-upload" @dblclick.native.stop
@click="onClickReplace"/>-->
......@@ -46,9 +50,11 @@
import {mapMutations, mapActions} from "vuex";
import {fileTypeIcon} from "../../../config";
import {selectFile, strEllipsis} from "../../../utils";
import SvgaPreviewView from "../../../components/SvgaPreviewView";
export default {
name: "FileItem",
components: {SvgaPreviewView},
props: {
data: {type: Object},
editable: {type: Boolean, default: false},
......@@ -68,6 +74,12 @@
showThumbnail() {
return fileTypeIcon[this.data.ext] === 't';
},
showSvga() {
return this.data.ext === '.svga';
},
showIcon() {
return !this.showThumbnail && !this.showSvga;
},
thumbnailUrl() {
return this.data.url;
},
......
......@@ -10,7 +10,7 @@
<div class="mapping-list">
<div class="list" v-if="customMeta">
<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="side left">
<span class="extname">
......@@ -18,6 +18,10 @@
</span>
<div class="thumbnail">
<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>
<el-input size="mini" v-model="item.url" readonly/>
</div>
......@@ -28,7 +32,11 @@
</span>-->
<div class="thumbnail">
<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>
<el-input size="mini" v-model="item.replace" clearable>
<el-button slot="append" icon="el-icon-brush" @click="onClickReplace(item)"/>
......@@ -51,16 +59,17 @@
</template>
<script>
import {mapMutations, mapState, mapGetters} from 'vuex';
import {mapMutations, mapState, mapGetters, mapActions} from 'vuex';
import {fileTypeIcon} from "../../../../config";
import SelectAssetDialog from "../SelectAssetDialog";
import {clonePureObj} from "../../../../utils";
import SvgaPreviewView from "../../../../components/SvgaPreviewView";
const linkScheme = 'link://';
export default {
name: "AssetMappingEditorDialog",
components: {SelectAssetDialog},
components: {SvgaPreviewView, SelectAssetDialog},
data() {
return {
visible: false,
......@@ -75,13 +84,14 @@
...mapGetters([
'assets',
'customPackages',
'assetSize',
])
},
methods: {
showThumbnail(ext) {
return fileTypeIcon[ext] === 't';
},
resolveImg(item) {
resolveSrc(item) {
let url;
const replace = item.replace;
if (replace.startsWith(linkScheme)) {
......@@ -107,6 +117,9 @@
show(data) {
this.mid = data.id;
this.customMeta = clonePureObj(this.customPackages[this.mid]);
for(let asset of this.customMeta.assets){
this.updateAssetSize(asset.url);
}
for (let uuid in data.assetMapping) {
let asset = this.customMeta.assets.find(item => item.uuid === uuid);
......@@ -135,6 +148,7 @@
},
...mapMutations([]),
...mapActions(['updateAssetSize']),
}
}
</script>
......@@ -153,11 +167,11 @@
flex-direction: column;
align-items: stretch;
.name{
.name {
text-align: center;
}
.diff{
.diff {
position: relative;
border: 1px solid lightgray;
border-radius: 5px;
......
......@@ -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"
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:
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"
......
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