feat: add cropper components

This commit is contained in:
xiaoxian521 2021-04-11 14:53:15 +08:00
parent ba6e3447a7
commit 90b2ac8599
8 changed files with 209 additions and 2 deletions

5
package-lock.json generated
View File

@ -562,6 +562,11 @@
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.10.0.tgz",
"integrity": "sha512-CC582enhrFZStO4F8lGI7QL3SYx7/AIRc+IdSi3btrQGrVsTawo5K/crmKbRrQ+MOMhNX4v+PATn0k2NN6wI7A=="
},
"cropperjs": {
"version": "1.5.11",
"resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.5.11.tgz",
"integrity": "sha512-SJUeBBhtNBnnn+UrLKluhFRIXLJn7XFPv8QN1j49X5t+BIMwkgvDev541f96bmu8Xe0TgCx3gON22KmY/VddaA=="
},
"cssesc": {
"version": "3.0.0",
"resolved": "http://192.168.250.101:4873/cssesc/-/cssesc-3.0.0.tgz",

View File

@ -11,6 +11,7 @@
"@vueuse/core": "^4.8.1",
"await-to-js": "^2.1.1",
"axios": "^0.21.1",
"cropperjs": "^1.5.11",
"dayjs": "^1.10.4",
"dotenv": "^8.2.0",
"echarts": "^5.0.2",

View File

@ -0,0 +1,128 @@
<template>
<div :class="$attrs.class" :style="getWrapperStyle">
<img
v-show="isReady"
ref="imgElRef"
:src="src"
:alt="alt"
:crossorigin="crossorigin"
:style="getImageStyle"
/>
</div>
</template>
<script lang="ts">
import type { CSSProperties } from 'vue';
import { defineComponent, onMounted, ref, unref, computed, PropType } from 'vue';
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.css';
type Options = Cropper.Options;
const defaultOptions: Cropper.Options = {
aspectRatio: 16 / 9,
zoomable: true,
zoomOnTouch: true,
zoomOnWheel: true,
cropBoxMovable: true,
cropBoxResizable: true,
toggleDragModeOnDblclick: true,
autoCrop: true,
background: true,
highlight: true,
center: true,
responsive: true,
restore: true,
checkCrossOrigin: true,
checkOrientation: true,
scalable: true,
modal: true,
guides: true,
movable: true,
rotatable: true,
};
export default defineComponent({
props: {
src: {
type: String,
required: true,
},
alt: {
type: String,
},
height: {
type: [String, Number],
default: '360px',
},
crossorigin: {
type: String,
default: undefined,
},
imageStyle: {
type: Object as PropType<CSSProperties>,
default: {},
},
options: {
type: Object as PropType<Options>,
default: {},
},
},
setup(props, ctx) {
const imgElRef = ref<ElRef<HTMLImageElement>>(null);
const cropper: any = ref<Nullable<Cropper>>(null);
const isReady = ref(false);
const getImageStyle = computed(
(): CSSProperties => {
return {
height: props.height,
maxWidth: '100%',
...props.imageStyle,
};
}
);
const getWrapperStyle = computed(
(): CSSProperties => {
const { height } = props;
return { height: `${height}`.replace(/px/, '') + 'px' };
}
);
async function init() {
const imgEl = unref(imgElRef);
if (!imgEl) {
return;
}
cropper.value = new Cropper(imgEl, {
...defaultOptions,
ready: () => {
isReady.value = true;
},
...props.options,
});
}
// event: return base64 and width and height information after cropping
const croppered = (): void => {
let imgInfo = cropper.value.getData();
cropper.value.getCroppedCanvas().toBlob(blob => {
let fileReader: FileReader = new FileReader()
fileReader.onloadend = (e: any) => {
ctx.emit("cropperedInfo", {
imgBase64: e.target.result,
imgInfo
})
}
fileReader.readAsDataURL(blob)
}, 'image/jpeg')
}
onMounted(init);
return { imgElRef, getWrapperStyle, getImageStyle, isReady, croppered };
},
});
</script>

View File

@ -14,5 +14,6 @@
"map": "地图组件",
"draggable": "拖拽组件",
"split-pane": "切割面板",
"button": "按钮组件"
"button": "按钮组件",
"cropping": "图片裁剪"
}

View File

@ -14,5 +14,6 @@
"map": "Map Components",
"draggable": "Draggable Components",
"split-pane": "Split Pane",
"button": "Button Components"
"button": "Button Components",
"cropping": "Picture Cropping"
}

View File

@ -76,6 +76,15 @@ const routes: Array<RouteRecordRaw> = [
showLink: false,
savedPosition: true
}
},
{
path: '/components/cropping',
component: () => import(/* webpackChunkName: "components" */ '../views/components/cropping/index.vue'),
meta: {
title: 'cropping',
showLink: false,
savedPosition: true
}
}
],
meta: {

View File

@ -0,0 +1,62 @@
<template>
<div style="margin: 10px">
<div class="cropper-container">
<cropperImage ref="refCropper" :src="img" @cropperedInfo="cropperedInfo" style="width:45%" />
<img :src="cropperImg" class="croppered" v-if="cropperImg" />
</div>
<el-button type="primary" @click="onCropper">裁剪</el-button>
<p v-if="cropperImg">裁剪后图片信息{{ info }}</p>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, onBeforeMount, getCurrentInstance } from "vue";
import cropperImage from "../../../components/cropper/index.vue";
import img from "./picture.jpeg";
export default defineComponent({
components: {
cropperImage
},
setup() {
let vm: any;
let info = ref("");
let cropperImg = ref("");
const onCropper = (): void => {
vm.refs.refCropper.croppered();
};
onBeforeMount(() => {
vm = getCurrentInstance();
});
function cropperedInfo({ imgBase64, imgInfo }) {
info.value = imgInfo;
cropperImg.value = imgBase64;
}
return {
img,
info,
cropperImg,
onCropper,
cropperedInfo
};
}
});
</script>
<style scoped>
.cropper-container {
display: flex;
justify-content: space-between;
align-items: center;
}
.el-button {
margin-top: 10px;
}
.croppered {
display: block;
width: 45%;
height: 360px;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB