| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- <script lang="ts" setup>
- import 'vue-cropper/dist/index.css'
- import { VueCropper } from 'vue-cropper'
- import {ref,defineEmits} from "vue"
- import api from '@/api'
- import {ElMessage} from "element-plus";
- interface Props{
- imgUrl: string;
- imgName:string;
- }
- const props = withDefaults(defineProps<Props>(),{
- imgUrl:'',
- imgName:''
- })
- const emit = defineEmits(['uploadImg']);
- const cropper = ref<InstanceType<typeof VueCropper>>()
- const inputRef = ref<HTMLInputElement>()
- const loading = ref<boolean>(false)
- const isReady = ref<boolean>(false)
- // vue-cropper的基本配置
- // console.log(props.imgUrl,666)
- const option = ref({
- img: props.imgUrl, //裁剪图片的地址
- outputSize: 1, //裁剪生成图片的质量(可选0.1 - 1)
- outputType: 'jpeg', //裁剪生成图片的格式(jpeg || png || webp)
- info: true, //图片大小信息
- canScale: true, //图片是否允许滚轮缩放
- autoCrop: true, //是否默认生成截图框
- autoCropWidth: 150, //默认生成截图框宽度
- autoCropHeight: 150, //默认生成截图框高度
- fixed: true, //是否开启截图框宽高固定比例
- fixedNumber: [1, 1], //截图框的宽高比例
- full: false, //false按原比例裁切图片,不失真
- fixedBox: false, //固定截图框大小,不允许改变
- canMove: false, //上传图片是否可以移动
- canMoveBox: true, //截图框能否拖动
- original: false, //上传图片按照原始比例渲染
- centerBox: false, //截图框是否被限制在图片里面
- height: true, //是否按照设备的dpr 输出等比例图片
- infoTrue: false, //true为展示真实输出图片宽高,false展示看到的截图框宽高
- maxImgSize: 3000, //限制图片最大宽度和高度
- enlarge: 1, //图片根据截图框输出比例倍数
- mode: '300px 300px' //图片默认渲染方式
- })
- const previewURL = ref<string>('')
- // 实时的刷新
- const realTime = () => {
- if (loading.value) return
- loading.value = true
- // 节流
- setTimeout(() => {
- cropper.value.getCropBlob((data: Blob) => {
- previewURL.value = URL.createObjectURL(data)
- console.log(previewURL.value)
- loading.value = false
- })
- }, 500)
- }
- // 初始化
- const imgLoad = (msg: string) => {
- if (msg === 'success') {
- isReady.value = true
- }
- }
- //选择图片
- const img=ref()
- const selectImg = (e: Event) => {
- const eTarget = e.target as HTMLInputElement
- if (!eTarget.files) return
- const file = eTarget.files[0]
- if (!/\.(jpg|jpeg|png|JPG|PNG)$/.test(eTarget.value)) {
- alert('图片格式错误')
- return false
- }
- img.value=file
- // console.log(file)
- const reader = new FileReader()
- reader.readAsDataURL(file) //将文件转化为base64
- reader.onload = e => {
- let data
- if (!e.target) return
- if (typeof e.target.result === 'object') {
- data = URL.createObjectURL(new Blob([e.target.result ?? '']))
- } else {
- data = e.target.result
- }
- option.value.img = data
- }
- }
- //图片缩放
- const changeScale = (num: number) => {
- num = num || 1
- cropper.value.changeScale(num)
- }
- //向左旋转
- const rotateLeft = () => {
- cropper.value.rotateLeft()
- }
- //向右旋转
- const rotateRight = () => {
- cropper.value.rotateRight()
- }
- //上传图片
- const imgUpload = () => {
- //获取截图的blob数据
- // console.log(cropper.value)
- // console.log(cropper.value.scaleImg)
- cropper.value.getCropBlob(async (data: File) => {
- let formData = new FormData();
- const files = new File([data],img.value?.name || props.imgName,{
- type:data.type
- }); // 声明formData数据类型
- formData.append('file',files)
- // console.log(img.value.size)
- // console.log(data)
- // params.append("file", );
- api.areaApi.fileUpload(formData).then((res: any) => {
- if (res.code === 200) {
- // console.log(res)
- ElMessage({
- message: '上传成功',
- type: 'success'
- })
- emit("uploadImg", res.data);
- } else {
- ElMessage({
- message: res.msg,
- type: 'warning'
- })
- }
- });
- // 上传到服务器
- })
- }
- //选择图片
- const selectClick = () => {
- inputRef.value?.click()
- }
- </script>
- <template>
- <div class="h-[40vh] w-[100vw] ">
- <div class="w-[800px] h-[300px]">
- <div class="w-[800px] h-[300px] flex items-center justify-between">
- <!-- 给组件固定宽高 -->
- <div class="h-[300px] w-[510px]" style="width: 500px">
- <VueCropper
- ref="cropper"
- :img="option.img"
- :outputSize="option.outputSize"
- :outputType="option.outputType"
- :info="option.info"
- :canScale="option.canScale"
- :autoCrop="option.autoCrop"
- :autoCropWidth="option.autoCropWidth"
- :autoCropHeight="option.autoCropHeight"
- :fixed="option.fixed"
- :fixedNumber="option.fixedNumber"
- :full="option.full"
- :fixedBox="option.fixedBox"
- :canMove="option.canMove"
- :canMoveBox="option.canMoveBox"
- :original="option.original"
- :centerBox="option.centerBox"
- :height="option.height"
- :infoTrue="option.infoTrue"
- :maxImgSize="option.maxImgSize"
- :enlarge="option.enlarge"
- :mode="option.mode"
- @realTime="realTime"
- @imgLoad="imgLoad"
- ></VueCropper>
- </div>
- <!-- <div class="ml-[60px]">
- <div class="text-center text-[#409EFF] mb-[20px] text-[20px] font-medium">预览</div>
- <div class="flex items-center">
- <div v-if="isReady">
- <el-image class="rounded-[50%] w-[150px] h-[150px]" :src="previewURL" />
- </div>
- </div>
- </div> -->
- </div>
- <div class="flex items-center mt-[30px]">
- <div class="relative">
- <div
- class="mr-[15px] cursor-pointer text-[20px] text-[#409EFF] font-semibold"
- @click="selectClick"
- >
- 选择图片
- </div>
- <input
- ref="inputRef"
- type="file"
- style="position: absolute; clip: rect(0 0 0 0)"
- accept="image/png, image/jpeg, image/gif, image/jpg"
- @change="selectImg"
- />
- </div>
- <el-button style="width: 96px" type="primary" @click="changeScale(1)">放大</el-button>
- <el-button style="width: 96px" type="primary" @click="changeScale(-1)">缩小</el-button>
- <el-button style="width: 96px" type="primary" @click="rotateLeft">↺ 左旋转</el-button>
- <el-button style="width: 96px" type="primary" @click="rotateRight">↻ 右旋转</el-button>
- <el-button type="primary" plain @click="imgUpload">上传图片</el-button>
- </div>
- </div>
- </div>
- </template>
- <style scoped lang="scss"></style>
|