Commit 9355f0ca authored by rockyl's avatar rockyl

转换jpg功能

parent a067b144
......@@ -250,6 +250,7 @@
"Previous Conflict": "上一个冲突",
"Next Conflict": "下一个冲突",
"To Verify": "去验证",
"Transform options": "转换参数",
"eventGroup": {
"in": "接收",
"out": "派发"
......@@ -394,7 +395,8 @@
"assetItemMenu": {
"rename": "重命名",
"replace": "替换",
"combine": "合并"
"combine": "合并",
"to-jpg": "转换为JPG"
},
"customCmds": {
"z-for": "循环",
......
......@@ -5,8 +5,10 @@
*/
import Vue from "vue";
import {envApi} from "../../api";
import {editorApi, envApi} from "../../api";
import {Parser} from "svgaplayerweb";
import db from "../../utils/db-storage";
import events from "@/global-events"
const storeKey = 'code-sync-serve-config';
const svgaParser = new Parser();
......@@ -125,3 +127,24 @@ export const editorStore = {
},
}
};
export async function uploadFiles(files) {
const failedList = [];
let ps = [];
for (let file of files) {
events.$emit('upload-indicator', true);
ps.push(
editorApi.uploadFile(file).catch(e => {
failedList.push(file);
}).finally(() => {
events.$emit('upload-indicator', false);
})
);
}
const result = await Promise.all(ps);
return {
failedList,
result,
}
}
......@@ -17,7 +17,6 @@ import {
traverseViewNode
} from "../../utils"
import {template} from "../../template"
import events from "@/global-events"
import {packAssetsGroups} from "../../utils/assets-pack"
import {addBehavior, deleteProcessMeta,} from "./behavior"
......@@ -26,6 +25,7 @@ import {preprocess} from "../../views/Preview/preview-preprocess"
import {packageStore} from "./package"
import {toZeroing} from "psd-parse-web"
import {arrayFind} from "element-ui/src/utils/util";
import {uploadFiles} from "./editor";
const storeName = 'project';
const psStoreName = 'pack-history';
......@@ -619,7 +619,7 @@ export const projectStore = {
},
assetDepFlag: state => uuid => {
return state.data.views.filter(view =>
view.explicitDepAssets.includes(uuid) || view.implicitDepAssets.includes(uuid)
view.explicitDepAssets && view.explicitDepAssets.includes(uuid) || view.implicitDepAssets && view.implicitDepAssets.includes(uuid)
).length > 0 ? 0 : -1;
},
customs(state) {
......@@ -907,6 +907,7 @@ export const projectStore = {
return failedList;
},
async replaceAsset({commit}, {uuid, file}) {
console.log(file);
const {failedList, result} = await uploadFiles([file]);
commit('replaceAsset', {uuid, url: result[0].url,});
return failedList;
......@@ -971,34 +972,6 @@ export const projectStore = {
},
};
async function uploadFiles(files) {
const failedList = [];
let ps = [];
for (let file of files) {
events.$emit('upload-indicator', true);
ps.push(
editorApi.uploadFile(file).catch(e => {
failedList.push(file);
}).finally(() => {
events.$emit('upload-indicator', false);
})
);
}
const result = await Promise.all(ps);
return {
failedList,
result,
}
}
export async function updateMock(mocks) {
await db.clear('mock');
for (let mock of mocks) {
db.set('mock', mock);
}
}
function getDefaultOptions() {
return clonePureObj(defaultOptions)
......@@ -1040,3 +1013,10 @@ function copyBaseRoot(node) {
}
return data
}
export async function updateMock(mocks) {
await db.clear('mock');
for (let mock of mocks) {
db.set('mock', mock);
}
}
......@@ -426,6 +426,61 @@ export function deleteAssetsDepConfig(data) {
}
}
export function formatJson(source){
export function formatJson(source) {
return source ? JSON.stringify(JSON.parse(source), null, '\t') : '';
}
let transCanvas = document.createElement('canvas');
export async function transPngToJpg(img, type = 'blob', option) {
const quality = option ? option.quality : 70;
const bgColor = option ? option.bgColor : '#FFFFFF';
if (!img) {
return;
}
let imgOrigin;
if (typeof img === 'string') {
imgOrigin = new Image();
imgOrigin.crossOrigin = 'anonymous';
imgOrigin.src = img;
await new Promise((resolve, reject) => {
imgOrigin.onload = resolve;
imgOrigin.onerror = reject;
})
} else {
imgOrigin = img;
}
const {width, height} = imgOrigin;
transCanvas.width = width;
transCanvas.height = height;
let ctx = transCanvas.getContext('2d');
ctx.fillStyle = bgColor;
ctx.fillRect(0, 0, width, height);
ctx.drawImage(imgOrigin, 0, 0);
let dataUrl = transCanvas.toDataURL('image/jpeg', quality / 100);
let result;
switch (type) {
case 'img':
let imgR = new Image();
imgR.src = dataUrl;
result = imgR;
break;
case 'blob':
result = dataURLtoBlob(dataUrl);
break;
}
return result;
}
export function dataURLtoBlob(dataUrl) {
var arr = dataUrl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type: mime});
}
......@@ -131,6 +131,26 @@ export default {
type: 'color',
default: '#000'
},
shadowBlur: {
alias: '阴影模糊度',
type: 'string',
default: 0
},
shadowColor: {
alias: '阴影颜色',
type: 'color',
default: '#000'
},
shadowOffsetX: {
alias: '阴影偏移X',
type: 'number',
default: 0
},
shadowOffsetY: {
alias: '阴影偏移Y',
type: 'number',
default: 0
},
stroke: {
alias: '描边宽度',
type: 'number',
......
......@@ -7,17 +7,21 @@
@click="onClickItem(asset, $event)"
@delete="onDeleteItem(asset)"
@combine="onCombineAssets"
@to-jpg="onToJpg"
/>
<trans-to-jpg-option-dialog ref="transToJpgOptionDialog" @confirm="onConfirmToTransJpg"/>
</div>
</template>
<script>
import {mapGetters, mapMutations} from 'vuex';
import {mapGetters, mapMutations, mapActions} from 'vuex';
import FileItem from "./FileItem";
import {transPngToJpg} from "../../../utils";
import TransToJpgOptionDialog from "./TransToJpgOptionDialog";
export default {
name: "AssetList",
components: {FileItem},
components: {TransToJpgOptionDialog, FileItem},
props: {
editable: {
type: Boolean,
......@@ -105,6 +109,18 @@
}).catch((e) => {
});
},
async onToJpg(asset) {
this.lastAsset = asset;
this.$refs.transToJpgOptionDialog.show();
},
async onConfirmToTransJpg(option){
let asset = this.lastAsset;
let blob = await transPngToJpg(asset.url, 'blob', option);
this.replaceAsset({
uuid: asset.uuid,
file: new File([blob], asset.name + '.jpg'),
});
},
selectItem(asset, unselectAll = true) {
if (unselectAll) {
this.selectedIndices.splice(0);
......@@ -140,6 +156,7 @@
return flag;
},
...mapMutations(['combineAssets']),
...mapActions(['replaceAsset']),
}
}
</script>
......
......@@ -22,7 +22,9 @@
:command="key"
:key="key"
:disabled="key === 'combine' && !combinable"
>{{item}}</el-dropdown-item>
v-if="showMenuItem(key)"
>{{item}}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
......@@ -68,9 +70,7 @@
assetItemMenu: this.$t('assetItemMenu'),
}
},
watch: {
},
watch: {},
computed: {
fileIcon() {
let icon = fileTypeIcon[this.data.ext];
......@@ -91,9 +91,9 @@
ellipsisName() {
return strEllipsis(this.data.name, 14, 5);
},
depFlag(){
depFlag() {
return this.$parent.getDepFlag(this.data.uuid);
}
},
},
methods: {
onDbclick() {
......@@ -126,6 +126,9 @@
case 'combine':
this.$emit('combine', this.data);
break;
case 'to-jpg':
this.$emit('to-jpg', this.data);
break;
}
},
editName() {
......@@ -151,6 +154,14 @@
});
})
},
showMenuItem(key) {
const {ext} = this.data;
if (key === 'to-jpg') {
return ext === '.png';
} else {
return true;
}
},
...mapMutations([
'deleteAsset',
'modifyAsset',
......
<template>
<el-dialog :title="$t('Transform options')" width="70%" :visible.sync="visible" @opened="onOpen"
:append-to-body="true"
custom-class="flex-dialog details-dialog"
>
<el-form v-model="option" label-position="right" label-width="100px" size="mini" style="padding: 20px">
<el-form-item label="品质">
<el-input-number v-model="option.quality" :max="100" :min="10" controls-position="right"/>
</el-form-item>
<el-form-item label="底色">
<el-color-picker v-model="option.bgColor"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<div></div>
<div>
<el-button size="mini" @click="onClose">{{$t('Close')}}</el-button>
<el-button size="mini" @click="onConfirm" type="primary">{{$t('Confirm')}}</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
import {mapMutations} from 'vuex';
import ElFormItem from "../../../components/inputs/form-item";
export default {
name: "TransToJpgOptionDialog",
components: {ElFormItem},
data() {
return {
visible: false,
option: {
quality: 70,
bgColor: '#ffffff',
}
}
},
methods: {
show() {
this.option.quality = 70;
this.option.bgColor = '#ffffff';
this.visible = true;
},
onConfirm() {
this.$emit('confirm', this.option);
this.visible = false;
},
onClose() {
this.visible = false;
},
onOpen() {
},
...mapMutations([
'modifyProjectDetails',
]),
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
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