Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vue版本的upload组件没有裁剪功能 #1393

Closed
1 task done
CrazyBoyM opened this issue Jul 6, 2022 · 3 comments
Closed
1 task done

vue版本的upload组件没有裁剪功能 #1393

CrazyBoyM opened this issue Jul 6, 2022 · 3 comments

Comments

@CrazyBoyM
Copy link

CrazyBoyM commented Jul 6, 2022

Basic Info

Steps to reproduce

如题,vue版本的upload组件没有裁剪功能,但react版本有,请求增加。

@liziwork
Copy link

@SleepDevil
Copy link
Contributor

react版本只是添加了通过react-easy-cropper实现的简单图片裁剪上传功能的实例,你可以自己去通过开源的图片裁剪库去封装,例如cropperjs,或者可以去我们的物料平台寻找是否有现有物料。

@SleepDevil SleepDevil closed this as not planned Won't fix, can't repro, duplicate, stale Jul 13, 2022
@zgia
Copy link

zgia commented Jan 5, 2025

https://github.com/chengpeiquan/vue-picture-cropper-demo/blob/main/src/views/composition.vue 用这个自己封装个组件

一个比较简陋的实现,参考react版本的实现方式,在onBeforeUpload时处理

子组件:comp-upload.vue

<template>
  <div class="container">
    <a-upload
      action="/"
      accept="image/*"
      list-type="picture"
      :file-list="uploadValue"
      :custom-request="customRequest"
      @before-upload="onBeforeUpload"
      @before-remove="beforeRemove"
    />

    <PictureCropperModal
      v-if="props.showPictureCopper && showCropperModal"
      ref="cropperModalRef"
      @update="updateCropper"
      @cancel="cancelCropper"
    />
  </div>
</template>

<script lang="ts" setup>
  // @ts-nocheck
  import PictureCropperModal from './crop-picture.vue';

  const props = defineProps({
    modelValue: {
      type: Array,
      default: () => [],
    },
    showPictureCopper: {
      type: Boolean,
      default: false,
    },
  });

  const emit = defineEmits(['update:modelValue', 'beforeRemove', 'change']);

  // Vue Picture Cropper
  const showCropperModal = ref(false);
  const cropperModalRef = ref();
  const handleCrop = (file: any, resolve) => {
    showCropperModal.value = true;
    nextTick(() => {
      cropperModalRef.value.showModal(file, resolve);
    });
  };
  const updateCropper = (file: any, resolve) => {
    resolve(file);
    showCropperModal.value = false;
  };
  const cancelCropper = (resolve) => {
    resolve(false);
    showCropperModal.value = false;
  };

  // 父组件传来的值
  const fileList = ref([] as any);
  const uploadValue = computed({
    get() {
      const value = [...props.modelValue];
      fileList.value = value;

      return value;
    },
    set(value: any) {
      // emit...value
    },
  });

  const onBeforeUpload = (file: any) => {
    return new Promise((resolve, reject) => {
      if (props.showPictureCopper) {
        handleCrop(file, resolve);
      } else {
        resolve(true);
      }
    });
  };

  // 自定义上传处理:onCustomRequest,需要实现
  const customRequest = async (option: any) => {
    const res = await onCustomRequest(option);
    if (res) {
      // emit...fileList
    } else {
      // emit...fileList
    }
  };

  const beforeRemove = (file: any) => {
    // emit...fileList
  };
</script>

<style lang="less" scoped></style>

crop-picture.vue:

<template>
  <a-modal
    title="剪裁图片"
    :visible="visible"
    @before-ok="onBeforeOk"
    @cancel="onCancel"
  >
    <VuePictureCropper
      :key="Date.now()"
      :box-style="{
        width: '100%',
        height: '100%',
        backgroundColor: '#f8f8f8',
        margin: 'auto',
      }"
      :img="state.image"
      :options="{
        viewMode: 1,
        dragMode: 'crop',
        aspectRatio: 1,
      }"
      :preset-mode="{
        mode: 'fixedSize',
      }"
    />
  </a-modal>
</template>

<script lang="ts" setup>
  // https://cropper.chengpeiquan.com/zh/preset-mode.html
  import VuePictureCropper, { cropper } from 'vue-picture-cropper';

  const emit = defineEmits(['update', 'cancel']);

  const visible = ref(false);
  const state = reactive({}) as any;

  const getResult = async (): Promise<void> => {
    if (!cropper) return;
    state.blob = (await cropper?.getBlob()) as Blob;
  };

  const showModal = (file: any, resolve) => {
    // 转换为base64传给裁切组件
    const reader: FileReader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => {
      state.image = String(reader.result);
    };

    state.file = file;
    state.resolve = resolve;

    visible.value = true;
  };

  const onBeforeOk = async () => {
    await getResult();

    const file: File = new File([state.blob], state.file.name, {
      type: state.blob.type,
    });

    visible.value = false;
    emit('update', file, state.resolve);
  };

  const onCancel = () => {
    visible.value = false;
    emit('cancel', state.resolve);
  };

  defineExpose({ showModal });
</script>

<style scoped lang="less"></style>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants