From e4f79a7e36214e5836cb0e667b3ffbd3db45456d Mon Sep 17 00:00:00 2001 From: Ben Lin <maobin001@msn.com> Date: 星期二, 22 十月 2024 23:54:26 +0800 Subject: [PATCH] 工单变量删除优化,预览优化 --- src/components/Cropper/src/Cropper.vue | 242 ++++++++++++++++++++++++------------------------ 1 files changed, 120 insertions(+), 122 deletions(-) diff --git a/src/components/Cropper/src/Cropper.vue b/src/components/Cropper/src/Cropper.vue index 4523ad4..0aaade4 100644 --- a/src/components/Cropper/src/Cropper.vue +++ b/src/components/Cropper/src/Cropper.vue @@ -10,13 +10,14 @@ /> </div> </template> -<script lang="ts"> +<script lang="ts" setup> import type { CSSProperties } from 'vue'; - import { defineComponent, onMounted, ref, unref, computed, onUnmounted } from 'vue'; + import { onMounted, ref, unref, computed, onUnmounted } from 'vue'; import Cropper from 'cropperjs'; import 'cropperjs/dist/cropper.css'; - import { useDesign } from '/@/hooks/web/useDesign'; - import { useDebounceFn } from '@vueuse/shared'; + import { useDesign } from '@/hooks/web/useDesign'; + import { useDebounceFn } from '@vueuse/core'; + import { useAttrs } from '@vben/hooks'; type Options = Cropper.Options; @@ -43,7 +44,9 @@ rotatable: true, }; - const props = { + defineOptions({ name: 'CropperImage' }); + + const props = defineProps({ src: { type: String, required: true }, alt: { type: String }, circled: { type: Boolean, default: false }, @@ -55,124 +58,119 @@ }, imageStyle: { type: Object as PropType<CSSProperties>, default: () => ({}) }, options: { type: Object as PropType<Options>, default: () => ({}) }, - }; - - export default defineComponent({ - name: 'CropperImage', - props, - emits: ['cropend', 'ready', 'cropendError'], - setup(props, { attrs, emit }) { - const imgElRef = ref<ElRef<HTMLImageElement>>(); - const cropper = ref<Nullable<Cropper>>(); - const isReady = ref(false); - - const { prefixCls } = useDesign('cropper-image'); - const debounceRealTimeCroppered = useDebounceFn(realTimeCroppered, 80); - - const getImageStyle = computed((): CSSProperties => { - return { - height: props.height, - maxWidth: '100%', - ...props.imageStyle, - }; - }); - - const getClass = computed(() => { - return [ - prefixCls, - attrs.class, - { - [`${prefixCls}--circled`]: props.circled, - }, - ]; - }); - - const getWrapperStyle = computed((): CSSProperties => { - return { height: `${props.height}`.replace(/px/, '') + 'px' }; - }); - - onMounted(init); - - onUnmounted(() => { - cropper.value?.destroy(); - }); - - async function init() { - const imgEl = unref(imgElRef); - if (!imgEl) { - return; - } - cropper.value = new Cropper(imgEl, { - ...defaultOptions, - ready: () => { - isReady.value = true; - realTimeCroppered(); - emit('ready', cropper.value); - }, - crop() { - debounceRealTimeCroppered(); - }, - zoom() { - debounceRealTimeCroppered(); - }, - cropmove() { - debounceRealTimeCroppered(); - }, - ...props.options, - }); - } - - // Real-time display preview - function realTimeCroppered() { - props.realTimePreview && croppered(); - } - - // event: return base64 and width and height information after cropping - function croppered() { - if (!cropper.value) { - return; - } - let imgInfo = cropper.value.getData(); - const canvas = props.circled ? getRoundedCanvas() : cropper.value.getCroppedCanvas(); - canvas.toBlob((blob) => { - if (!blob) { - return; - } - let fileReader: FileReader = new FileReader(); - fileReader.readAsDataURL(blob); - fileReader.onloadend = (e) => { - emit('cropend', { - imgBase64: e.target?.result ?? '', - imgInfo, - }); - }; - fileReader.onerror = () => { - emit('cropendError'); - }; - }, 'image/png'); - } - - // Get a circular picture canvas - function getRoundedCanvas() { - const sourceCanvas = cropper.value!.getCroppedCanvas(); - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d')!; - const width = sourceCanvas.width; - const height = sourceCanvas.height; - canvas.width = width; - canvas.height = height; - context.imageSmoothingEnabled = true; - context.drawImage(sourceCanvas, 0, 0, width, height); - context.globalCompositeOperation = 'destination-in'; - context.beginPath(); - context.arc(width / 2, height / 2, Math.min(width, height) / 2, 0, 2 * Math.PI, true); - context.fill(); - return canvas; - } - - return { getClass, imgElRef, getWrapperStyle, getImageStyle, isReady, croppered }; - }, }); + + const emit = defineEmits(['cropend', 'ready', 'cropendError']); + + const attrs = useAttrs(); + + const imgElRef = ref<ElRef<HTMLImageElement>>(); + const cropper = ref<Nullable<Cropper>>(); + const isReady = ref(false); + + const { prefixCls } = useDesign('cropper-image'); + const debounceRealTimeCroppered = useDebounceFn(realTimeCroppered, 80); + + const getImageStyle = computed((): CSSProperties => { + return { + height: props.height, + maxWidth: '100%', + ...props.imageStyle, + }; + }); + + const getClass = computed(() => { + return [ + prefixCls, + attrs.class, + { + [`${prefixCls}--circled`]: props.circled, + }, + ]; + }); + + const getWrapperStyle = computed((): CSSProperties => { + return { height: `${props.height}`.replace(/px/, '') + 'px' }; + }); + + onMounted(init); + + onUnmounted(() => { + cropper.value?.destroy(); + }); + + async function init() { + const imgEl = unref(imgElRef); + if (!imgEl) { + return; + } + cropper.value = new Cropper(imgEl, { + ...defaultOptions, + ready: () => { + isReady.value = true; + realTimeCroppered(); + emit('ready', cropper.value); + }, + crop() { + debounceRealTimeCroppered(); + }, + zoom() { + debounceRealTimeCroppered(); + }, + cropmove() { + debounceRealTimeCroppered(); + }, + ...props.options, + }); + } + + // Real-time display preview + function realTimeCroppered() { + props.realTimePreview && croppered(); + } + + // event: return base64 and width and height information after cropping + function croppered() { + if (!cropper.value) { + return; + } + let imgInfo = cropper.value.getData(); + const canvas = props.circled ? getRoundedCanvas() : cropper.value.getCroppedCanvas(); + canvas.toBlob((blob) => { + if (!blob) { + return; + } + let fileReader: FileReader = new FileReader(); + fileReader.readAsDataURL(blob); + fileReader.onloadend = (e) => { + emit('cropend', { + imgBase64: e.target?.result ?? '', + imgInfo, + }); + }; + fileReader.onerror = () => { + emit('cropendError'); + }; + }, 'image/png'); + } + + // Get a circular picture canvas + function getRoundedCanvas() { + const sourceCanvas = cropper.value!.getCroppedCanvas(); + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d')!; + const width = sourceCanvas.width; + const height = sourceCanvas.height; + canvas.width = width; + canvas.height = height; + context.imageSmoothingEnabled = true; + context.drawImage(sourceCanvas, 0, 0, width, height); + context.globalCompositeOperation = 'destination-in'; + context.beginPath(); + context.arc(width / 2, height / 2, Math.min(width, height) / 2, 0, 2 * Math.PI, true); + context.fill(); + return canvas; + } </script> <style lang="less"> @prefix-cls: ~'@{namespace}-cropper-image'; -- Gitblit v1.9.3