-
Notifications
You must be signed in to change notification settings - Fork 657
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
19ccf8b
commit b0a43a7
Showing
4 changed files
with
86 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,76 +1,90 @@ | ||
<script setup lang="ts"> | ||
import { useDesign } from '@/hooks/web/useDesign' | ||
import { propTypes } from '@/utils/propTypes' | ||
import { CSSProperties, computed } from 'vue' | ||
import { nextTick, unref, ref, watch, onBeforeUnmount, onMounted } from 'vue' | ||
import Cropper from 'cropperjs' | ||
import 'cropperjs/dist/cropper.min.css' | ||
// interface CropperOptions extends /* @vue-ignore */ Cropper.Options { | ||
// imageUrl: string | ||
// } | ||
const { getPrefixCls } = useDesign() | ||
const prefixCls = getPrefixCls('image-cropping') | ||
const bgIcon = | ||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC' | ||
const props = defineProps({ | ||
imageUrl: propTypes.string, | ||
boxWidth: propTypes.oneOfType([propTypes.number, propTypes.string]).def('100%'), | ||
boxHeight: propTypes.oneOfType([propTypes.number, propTypes.string]).def('100%'), | ||
dragWidth: propTypes.oneOfType([propTypes.number, propTypes.string]).def(200), | ||
dragHeight: propTypes.oneOfType([propTypes.number, propTypes.string]).def(200), | ||
cropWidth: propTypes.oneOfType([propTypes.number, propTypes.string]).def(200), | ||
cropHeight: propTypes.oneOfType([propTypes.number, propTypes.string]).def(200) | ||
imageUrl: { | ||
type: String, | ||
default: '', | ||
required: true | ||
}, | ||
cropBoxWidth: { | ||
type: Number, | ||
default: 200 | ||
}, | ||
cropBoxHeight: { | ||
type: Number, | ||
default: 200 | ||
} | ||
}) | ||
const boxStyles = computed((): CSSProperties => { | ||
return { | ||
width: (typeof props.boxWidth === 'number' ? `${props.boxWidth}px` : props.boxWidth) ?? '100%', | ||
height: | ||
(typeof props.boxHeight === 'number' ? `${props.boxHeight}px` : props.boxHeight) ?? '100%', | ||
position: 'relative', | ||
backgroundImage: `url(${bgIcon})` | ||
} | ||
const imgRef = ref<HTMLImageElement>() | ||
const cropperRef = ref<Cropper>() | ||
const intiCropper = () => { | ||
if (!unref(imgRef)) return | ||
const imgEl = unref(imgRef)! | ||
cropperRef.value = new Cropper(imgEl, { | ||
aspectRatio: 1, | ||
viewMode: 1, | ||
dragMode: 'move', | ||
cropBoxResizable: false, | ||
cropBoxMovable: false, | ||
toggleDragModeOnDblclick: false, | ||
checkCrossOrigin: false, | ||
ready() { | ||
const containerData = unref(cropperRef)?.getContainerData() | ||
unref(cropperRef)?.setCropBoxData({ | ||
width: props.cropBoxWidth, | ||
height: props.cropBoxHeight, | ||
left: (containerData?.width || 0) / 2 - 100, | ||
top: (containerData?.height || 0) / 2 - 100 | ||
}) | ||
} | ||
}) | ||
} | ||
onMounted(() => { | ||
intiCropper() | ||
}) | ||
const dragStyles = computed((): CSSProperties => { | ||
return { | ||
width: (typeof props.dragWidth === 'number' ? `${props.dragWidth}px` : props.dragWidth) ?? 200, | ||
height: | ||
(typeof props.dragHeight === 'number' ? `${props.dragHeight}px` : props.dragHeight) ?? 200, | ||
position: 'absolute', | ||
top: '50%', | ||
left: '50%', | ||
transform: 'translate(-50%, -50%)', | ||
zIndex: 1, | ||
boxShadow: '0 0 0 1px var(--el-color-primary),0 0 0 10000px rgba(0,0,0,.5)', | ||
cursor: 'move' | ||
watch( | ||
() => props.imageUrl, | ||
async (url) => { | ||
await nextTick() | ||
if (url) { | ||
unref(cropperRef)?.replace(url) | ||
} | ||
} | ||
) | ||
onBeforeUnmount(() => { | ||
unref(cropperRef)?.destroy() | ||
}) | ||
const cropStyles = computed((): CSSProperties => { | ||
return { | ||
width: (typeof props.cropWidth === 'number' ? `${props.cropWidth}px` : props.cropWidth) ?? 300, | ||
height: | ||
(typeof props.cropHeight === 'number' ? `${props.cropHeight}px` : props.cropHeight) ?? 300, | ||
position: 'absolute', | ||
top: '50%', | ||
left: '80px', | ||
transform: 'translate(0, -50%)', | ||
overflow: 'hidden', | ||
borderRadius: '50%', | ||
border: '1px solid var(--el-border-color)' | ||
} | ||
defineExpose({ | ||
cropperExpose: () => unref(cropperRef) | ||
}) | ||
</script> | ||
|
||
<template> | ||
<div :class="prefixCls" class="flex"> | ||
<div class="flex-1"> | ||
<div :style="boxStyles"> | ||
<img :src="imageUrl" class="w-full absolute top-[50%] left-[50%]" alt="" srcset="" /> | ||
<div :style="dragStyles"> </div> | ||
</div> | ||
</div> | ||
<div class="relative w-full"> | ||
<div :style="cropStyles"></div> | ||
</div> | ||
<div :class="prefixCls" class="flex justify-center items-center"> | ||
<img | ||
ref="imgRef" | ||
:src="imageUrl" | ||
class="block max-w-full" | ||
crossorigin="anonymous" | ||
alt="" | ||
srcset="" | ||
/> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,25 @@ | ||
<script setup lang="ts"> | ||
import { ContentWrap } from '@/components/ContentWrap' | ||
import { ImageCropping } from '@/components/ImageCropping' | ||
import { ref, unref } from 'vue' | ||
import { ElButton, ElInput } from 'element-plus' | ||
const cropperExpose = ref<InstanceType<typeof ImageCropping>>() | ||
const base64 = ref('') | ||
const getBase64 = () => { | ||
base64.value = unref(cropperExpose)?.cropperExpose()?.getCroppedCanvas()?.toDataURL() ?? '' | ||
} | ||
</script> | ||
|
||
<template> | ||
<ContentWrap title="图片裁剪"> | ||
<ElButton type="primary" class="mb-20px" @click="getBase64">裁剪</ElButton> | ||
<ElInput v-model="base64" class="mb-20px" type="textarea" /> | ||
<ImageCropping | ||
:box-width="350" | ||
:box-height="380" | ||
image-url="https://images6.alphacoders.com/657/thumbbig-657194.webp" | ||
ref="cropperExpose" | ||
image-url="https://hips.hearstapps.com/hmg-prod/images/%E5%AE%8B%E6%99%BA%E5%AD%9D-1597774015.jpg?crop=0.500xw:1.00xh;0.500xw,0&resize=640:*" | ||
/> | ||
</ContentWrap> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters