feat: tui-image-editor 使用完成

master
LCJ-MinYa 7 months ago
parent c5cc48c240
commit 1f9c282ad7

@ -4,13 +4,33 @@
class="tui-image-editor-wrap" class="tui-image-editor-wrap"
v-loading="loading" v-loading="loading"
> >
<div id="tui-image-editor"></div> <div
ref="tuiImageEditorRef"
id="tui-image-editor"
></div>
<el-button <el-button
circle circle
:icon="Close" :icon="Close"
class="close-btn" class="close-btn"
@click="closeEditor" @click="closeEditor"
></el-button> ></el-button>
<el-button
:loading="sending"
type="primary"
class="save-btn"
@click="save"
>保存图片</el-button
>
<el-icon
class="left-btn"
@click="changeImage('prev')"
><ArrowLeftBold
/></el-icon>
<el-icon
class="right-btn"
@click="changeImage('next')"
><ArrowRightBold
/></el-icon>
</div> </div>
</Teleport> </Teleport>
</template> </template>
@ -18,15 +38,21 @@
<script setup> <script setup>
import '../css/tui-color-picker.css'; import '../css/tui-color-picker.css';
import '../css/tui-image-editor.css'; import '../css/tui-image-editor.css';
import { ref, onMounted, watch } from 'vue'; import { ref, onMounted, onUnmounted } from 'vue';
import { Close } from '@element-plus/icons-vue'; import { Close, ArrowLeftBold, ArrowRightBold } from '@element-plus/icons-vue';
const emits = defineEmits(['close']); const emits = defineEmits(['close']);
const props = defineProps(['imgList']); const props = defineProps(['imgList']);
const currentIndex = ref(0); const currentIndex = ref(0);
const imageEditor = ref(null); const imageEditor = ref(null);
const loading = ref(false); const loading = ref(false);
const sending = ref(false);
const scale = ref(1); const scale = ref(1);
const tuiImageEditorRef = ref(null);
const imgSize = {
width: 750,
height: 500,
};
function createScriptElement(src) { function createScriptElement(src) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -41,17 +67,22 @@ function createScriptElement(src) {
onMounted(async () => { onMounted(async () => {
loading.value = true; loading.value = true;
// js if (!window.hasOwnProperty('tui')) {
await createScriptElement('/src/views/demo/tuiImageEditor/js/fabric.js'); // js
await createScriptElement('/src/views/demo/tuiImageEditor/js/tui-code-snippet.js'); await createScriptElement('/src/views/demo/tuiImageEditor/js/fabric.js');
await createScriptElement('/src/views/demo/tuiImageEditor/js/tui-color-picker.js'); await createScriptElement('/src/views/demo/tuiImageEditor/js/tui-code-snippet.js');
await createScriptElement('/src/views/demo/tuiImageEditor/js/FileSaver.js'); await createScriptElement('/src/views/demo/tuiImageEditor/js/tui-color-picker.js');
await createScriptElement('/src/views/demo/tuiImageEditor/js/tui-image-editor.js'); await createScriptElement('/src/views/demo/tuiImageEditor/js/FileSaver.js');
await createScriptElement('/src/views/demo/tuiImageEditor/js/white-theme.js'); await createScriptElement('/src/views/demo/tuiImageEditor/js/tui-image-editor.js');
await createScriptElement('/src/views/demo/tuiImageEditor/js/black-theme.js'); await createScriptElement('/src/views/demo/tuiImageEditor/js/white-theme.js');
await createScriptElement('/src/views/demo/tuiImageEditor/js/black-theme.js');
}
initTuiImageEditor(); initTuiImageEditor();
addEventListenerFN();
}); });
onUnmounted(() => {});
const locale_zh = { const locale_zh = {
Resize: '调整宽高', Resize: '调整宽高',
Crop: '裁剪', Crop: '裁剪',
@ -152,53 +183,183 @@ const initTuiImageEditor = () => {
// Image editor // Image editor
imageEditor.value = new tui.ImageEditor('#tui-image-editor', { imageEditor.value = new tui.ImageEditor('#tui-image-editor', {
includeUI: { includeUI: {
loadImage: {}, loadImage: {
path: props.imgList[currentIndex.value].path,
name: props.imgList[currentIndex.value].name,
},
locale: locale_zh, locale: locale_zh,
theme: theme, theme: theme,
menu: ['resize', 'crop', 'rotate', 'draw', 'shape', 'icon', 'text'],
}, },
cssMaxWidth: 700, cssMaxWidth: imgSize.width,
cssMaxHeight: 500, cssMaxHeight: imgSize.height,
usageStatistics: false, usageStatistics: false,
}); });
imageEditor.value.loadImageFromURL(props.imgList[currentIndex.value].path, props.imgList[currentIndex.value].name).then((res) => { imageEditor.value.ui._actions.main.zoomIn = () => {
console.log(res); zoomSize('zoomIn');
};
imageEditor.value.ui._actions.main.zoomOut = () => {
zoomSize('zoomOut');
};
console.log(imageEditor.value); const defaultColor = '#ff4040';
imageEditor.value.ui._actions.main.zoomIn = () => {
console.log('zoomIn');
zoomSize('zoomIn');
};
imageEditor.value.ui._actions.main.zoomOut = () => { console.log(imageEditor.value);
console.log('zoomOut'); //
zoomSize('zoomOut'); imageEditor.value.ui.draw.color = defaultColor;
}; imageEditor.value.ui.draw._els.drawColorPicker.colorElement.style.backgroundColor = defaultColor;
});
window.onresize = function () { //
imageEditor.value.ui.resizeEditor(); imageEditor.value.ui.shape.options.stroke = defaultColor;
}; imageEditor.value.ui.shape._els.strokeColorpicker.colorElement.style.backgroundColor = defaultColor;
//
imageEditor.value.ui.icon._els.iconColorpicker._color = defaultColor;
imageEditor.value.ui.icon._els.iconColorpicker.colorElement.style.backgroundColor = defaultColor;
//
imageEditor.value.ui.text._els.textColorpicker.color = defaultColor;
imageEditor.value.ui.text._els.textColorpicker.colorElement.style.backgroundColor = defaultColor;
// tui-image-editor.js addText 50592
// window.onresize = function () {
// imageEditor.value.ui.resizeEditor();
// };
// bug
// imageEditor.value.on('addText', (pos) => {
// let obj = imageEditor.value._graphics._objects;
// let arr = Reflect.ownKeys(obj);
// arr.forEach((item) => {
// if (obj[item].text === '') {
// let defaultText = '';
// obj[item].text = defaultText;
// obj[item].textLines[0] = defaultColor;
// obj[item]._text = defaultColor.split(',');
// obj[item]._textBeforeEdit = defaultColor;
// }
// });
// console.log(imageEditor.value);
// });
loading.value = false; loading.value = false;
}; };
const addEventListenerFN = () => {
document.querySelector('.tui-image-editor-wrap').addEventListener('click', handleClickOutside);
window.addEventListener('wheel', handleWheelEvent);
};
const handleClickOutside = (event) => {
const getBtnDom = (claseeName) => {
return document.querySelector(claseeName);
};
if (
getBtnDom('.save-btn').contains(event.target) ||
getBtnDom('.left-btn').contains(event.target) ||
getBtnDom('.right-btn').contains(event.target)
) {
return;
}
if (tuiImageEditorRef.value && !(tuiImageEditorRef.value.contains(event.target) || tuiImageEditorRef.value === event.target)) {
closeEditor();
}
};
const handleWheelEvent = (event) => {
if (event.deltaY < 0) {
zoomSize('zoomIn');
} else {
zoomSize('zoomOut');
}
};
const zoomSize = (type) => { const zoomSize = (type) => {
console.log(type); if ((scale.value > 1.5 && type === 'zoomIn') || (scale.value < 0.8 && type === 'zoomOut')) {
return;
}
if (type === 'zoomIn') { if (type === 'zoomIn') {
scale.value = scale.value + 0.1; scale.value = scale.value + 0.1;
} else { } else {
scale.value = scale.value - 0.1; scale.value = scale.value - 0.1;
} }
imageEditor.value.resizeCanvasDimension({ imageEditor.value.resizeCanvasDimension({
width: 750 * scale.value, width: imgSize.width * scale.value,
height: 500 * scale.value, height: imgSize.height * scale.value,
});
};
const save = () => {
sending.value = true;
const base64String = imageEditor.value.toDataURL({ format: 'jpeg', quality: 0.8 });
//base64file
const data = window.atob(base64String.split(',')[1]);
const arr = new Uint8Array(data.length);
for (let i = 0; i < data.length; i++) {
arr[i] = data.charCodeAt(i);
}
const blob = new Blob([arr], { type: 'image/jpeg' }); //bolb
const file = new File([arr], new Date().getTime() + '.jpg', { type: blob.type }); //file
const objectURL = URL.createObjectURL(file); //fileurl
//
//
//
const a = document.createElement('a');
a.href = objectURL;
a.download = new Date().getTime() + '.jpg';
a.click();
URL.revokeObjectURL(objectURL);
sending.value = false;
};
const changeImage = (type) => {
loading.value = true;
let index;
switch (type) {
case 'prev':
index = currentIndex.value - 1;
if (index < 0) {
index = props.imgList.length - 1;
}
break;
case 'next':
index = currentIndex.value + 1;
if (index >= props.imgList.length) {
index = 0;
}
break;
default:
break;
}
imageEditor.value
.loadImageFromURL(props.imgList[index].path, props.imgList[index].name)
.then(() => {
currentIndex.value = index;
refreshImageShow();
})
.finally(() => {
loading.value = false;
});
};
const refreshImageShow = () => {
scale.value = 1;
imageEditor.value.resizeCanvasDimension({
width: imgSize.width,
height: imgSize.height,
}); });
}; };
const closeEditor = () => { const closeEditor = () => {
document.querySelector('.tui-image-editor-wrap').removeEventListener('click', handleClickOutside);
imageEditor.value.destroy(); imageEditor.value.destroy();
imageEditor.value = null; imageEditor.value = null;
window.fabric = null;
emits('close'); emits('close');
}; };
</script> </script>
@ -219,16 +380,41 @@ const closeEditor = () => {
margin: 0 auto; margin: 0 auto;
} }
.close-btn { .close-btn,
.save-btn {
position: absolute; position: absolute;
top: 10px; top: 10px;
right: calc(50% - 400px + 18px); right: calc(50% - 400px + 18px);
z-index: 9; z-index: 9;
} }
.save-btn {
top: unset;
bottom: 10px;
}
.left-btn,
.right-btn {
position: absolute;
left: calc(50% - 400px + 10px);
top: 50%;
margin-top: -12px;
font-size: 24px;
cursor: pointer;
color: #fff;
}
.right-btn {
left: unset;
right: calc(50% - 400px + 10px);
}
} }
</style> </style>
<style lang="scss"> <style lang="scss">
body > svg:last-of-type { body > svg:last-of-type {
display: none; display: none;
} }
//
.tui-image-editor-container div.tui-colorpicker-clearfix {
display: none !important;
}
</style> </style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

@ -29,11 +29,18 @@ const imgList = ref([
path: 'http://gips3.baidu.com/it/u=3886271102,3123389489&fm=3028&app=3028&f=JPEG&fmt=auto?w=1280&h=960', path: 'http://gips3.baidu.com/it/u=3886271102,3123389489&fm=3028&app=3028&f=JPEG&fmt=auto?w=1280&h=960',
name: '1', name: '1',
}, },
{ {
path: 'http://gips3.baidu.com/it/u=3886271102,3123389489&fm=3028&app=3028&f=JPEG&fmt=auto?w=1280&h=960', path: 'http://gips0.baidu.com/it/u=1690853528,2506870245&fm=3028&app=3028&f=JPEG&fmt=auto?w=1024&h=1024',
name: '2', name: '2',
}, },
{
path: 'http://gips2.baidu.com/it/u=207216414,2485641185&fm=3028&app=3028&f=JPEG&fmt=auto?w=1280&h=720',
name: '3',
},
{
path: '/src/views/demo/tuiImageEditor/img/test.jpg',
name: '3',
},
]); ]);
const openImageEditor = () => { const openImageEditor = () => {

@ -50589,7 +50589,7 @@ var ImageTracer = /*#__PURE__*/function () {
underline = _this12$ui$text.underline; underline = _this12$ui$text.underline;
var fontFamily = 'Noto Sans'; var fontFamily = 'Noto Sans';
_this12.addText('Double Click', { _this12.addText('请输入', {
position: pos.originPosition, position: pos.originPosition,
styles: { styles: {
fill: fill, fill: fill,

Loading…
Cancel
Save