123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- <template>
- <div>
- <Confirm :title="title" :func="clickHandler" :no-text="noText" :ok-text="okText">
- <template #content>
- <div>
- <div class="cropper-layer" :style="style">
- <VueCropper v-if="show" ref="vmRef" v-bind="option" v-on="on" />
- </div>
- <div v-if="showSize" class="size">
- <ui-input :label="`Logo-${longSize}`" type="radio" name="size" :model-value="sizeType == 1" @update:modelValue="changSize(1)" />
- <ui-input :label="`Logo-${squareSize}`" type="radio" name="size" :model-value="sizeType == 2" @update:modelValue="changSize(2)" />
- </div>
- </div>
- </template>
- </Confirm>
- </div>
- </template>
- <script setup lang="ts">
- import { computed, defineProps, nextTick, ref } from 'vue'
- import { VueCropper } from 'vue-cropper'
- import Confirm from '../dialog/confirm.vue'
- import 'vue-cropper/dist/index.css'
- // import { useI18n } from '@/i18n'
- // const { t } = useI18n({ useScope: 'global' })
- const sizeType = ref(1)
- const layerWidth = 500
- defineOptions({
- name: 'UICropper',
- })
- const props = defineProps({
- fixedNumber: {
- type: Array,
- default: () => [1, 1],
- },
- img: { type: String },
- cb: {
- type: Function,
- },
- showSize: {
- type: Boolean,
- default: false,
- },
- noText: {
- type: String,
- default: '取消',
- },
- okText: {
- type: String,
- default: '确认',
- },
- title: {
- type: String,
- default: '裁剪',
- },
- longSize: {
- type: String,
- default: '长型',
- },
- squareSize: {
- type: String,
- default: '方型',
- },
- })
- const show = ref(true)
- // const fixedNumber = props.fixedNumber
- const getHeight = width => (fixedNumber[1] / fixedNumber[0]) * width
- const option = {
- outputSize: 1,
- outputType: 'png',
- info: false,
- full: true,
- fixed: true,
- canScale: true,
- fixedNumber: props.fixedNumber,
- canMove: true,
- canMoveBox: true,
- fixedBox: false,
- original: false,
- autoCrop: true,
- autoCropWidth: layerWidth / 2,
- autoCropHeight: getHeight(layerWidth / 2),
- centerBox: false,
- mode: 'contain',
- maxImgSize: 400,
- // ...props,
- }
- const changSize = type => {
- if (sizeType.value != type) {
- sizeType.value = type
- show.value = false
- if (type == 1) {
- option.fixedNumber = [2, 1]
- } else {
- option.fixedNumber = [1, 1]
- }
- nextTick(() => {
- show.value = true
- })
- }
- }
- const style = computed(() => ({
- width: `${layerWidth}px`,
- height: `${getHeight(layerWidth)}px`,
- }))
- const vmRef = ref()
- const on = {
- imgLoad(status) {
- if (status !== 'success') {
- props.cb('图片加载失败')
- }
- },
- }
- const clickHandler = async status => {
- if (status === 'ok') {
- const data = await Promise.all([new Promise(resolve => vmRef.value.getCropBlob(resolve)), new Promise(resolve => vmRef.value.getCropData(resolve))])
- if (props.showSize) {
- data.push(sizeType.value)
- }
- props.cb(null, data)
- } else {
- props.cb()
- }
- }
- </script>
- <script>
- export default { name: 'UiCropper' }
- </script>
- <style lang="scss">
- .vue-cropper {
- background-repeat: repeat;
- }
- .cropper-view-box {
- outline-color: var(--color-main-normal) !important;
- }
- .crop-point {
- background-color: var(--color-main-normal) !important;
- }
- .size {
- width: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- margin-top: 20px;
- }
- .ui-input {
- margin-right: 30px;
- &:last-of-type {
- margin-right: 0;
- }
- }
- </style>
|