图片裁剪不行
This commit is contained in:
@@ -65,7 +65,7 @@ defineExpose({
|
||||
</span>
|
||||
<input
|
||||
class="form-control"
|
||||
placeholder="Select a date"
|
||||
:placeholder="t('message.select_date')"
|
||||
ref="datepicker"
|
||||
value=""
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<div class="image-cropper">
|
||||
<div class="cropper-actions">
|
||||
<input
|
||||
type="file"
|
||||
ref="fileInput"
|
||||
@change="handleFileSelect"
|
||||
accept="image/*"
|
||||
style="display: none"
|
||||
/>
|
||||
<button @click="$refs.fileInput.click()">选择图片</button>
|
||||
|
||||
<div v-if="haveImageSrc" class="action-buttons">
|
||||
<button @click="setAspectRatio(1)">1:1</button>
|
||||
<button @click="setAspectRatio(16 / 9)">16:9</button>
|
||||
<button @click="setAspectRatio(4 / 3)">4:3</button>
|
||||
<button @click="rotate(-90)">↺</button>
|
||||
<button @click="rotate(90)">↻</button>
|
||||
<button @click="crop">裁剪</button>
|
||||
<button @click="reset">重置</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="haveImageSrc" class="cropper-container">
|
||||
<img ref="imageEl" alt="裁剪图片" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, nextTick } from "vue";
|
||||
import Cropper from "cropperjs";
|
||||
|
||||
const emit = defineEmits(["cropped", "error"]);
|
||||
|
||||
const imageEl = ref(null);
|
||||
const fileInput = ref(null);
|
||||
const haveImageSrc = ref(false);
|
||||
const resultImage = ref("");
|
||||
let cropperInstance = null;
|
||||
|
||||
// 读取文件为DataURL
|
||||
const readFileAsDataURL = (file) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => resolve(e.target.result);
|
||||
reader.onerror = reject;
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
};
|
||||
|
||||
// 选择文件
|
||||
const handleFileSelect = async (event) => {
|
||||
const file = event.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
if (!file.type.startsWith("image/")) {
|
||||
emit("error", "请选择图片文件");
|
||||
return;
|
||||
}
|
||||
console.log("选择了文件:", file.name);
|
||||
try {
|
||||
const dataUrl = await readFileAsDataURL(file);
|
||||
haveImageSrc.value = true;
|
||||
console.log("图片加载完成,初始化裁剪器");
|
||||
await nextTick();
|
||||
if (cropperInstance) {
|
||||
cropperInstance.destroy();
|
||||
console.log("销毁旧的Cropper实例");
|
||||
}
|
||||
console.log("加载图片进行裁剪");
|
||||
imageEl.value.src = dataUrl;
|
||||
|
||||
cropperInstance = new Cropper(imageEl.value, {
|
||||
aspectRatio: 1,
|
||||
viewMode: 2,
|
||||
autoCropArea: 0.8,
|
||||
zoomable: true,
|
||||
zoomOnWheel: true,
|
||||
zoomOnTouch: true,
|
||||
wheelZoomRatio: 0.1,
|
||||
ready: function () {
|
||||
console.log("Cropper 初始化成功");
|
||||
},
|
||||
crop: function (event) {
|
||||
// 可以在这里获取裁剪区域的信息
|
||||
console.log(event.detail);
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
emit("error", "图片加载失败");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.image-cropper {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.cropper-actions {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.action-buttons button {
|
||||
margin: 0 5px 5px 0;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.cropper-container {
|
||||
max-height: 400px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.result-container {
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.result-container img {
|
||||
max-width: 300px;
|
||||
max-height: 300px;
|
||||
border: 1px solid #ddd;
|
||||
margin: 10px 0;
|
||||
}
|
||||
</style>
|
||||
@@ -45,7 +45,8 @@
|
||||
"user_home": "Profile",
|
||||
"user_settings": "Settings",
|
||||
"preferences": "Preferences",
|
||||
"administrator": "Administrator"
|
||||
"administrator": "Administrator",
|
||||
"select_date":"Select a date"
|
||||
},
|
||||
"settings": {
|
||||
"account_settings": "Account Settings",
|
||||
|
||||
@@ -45,7 +45,8 @@
|
||||
"user_home": "个人主页",
|
||||
"user_settings": "个人资料",
|
||||
"preferences": "偏好设置",
|
||||
"administrator": "管理员"
|
||||
"administrator": "管理员",
|
||||
"select_date":"选择日期"
|
||||
},
|
||||
"settings": {
|
||||
"account_settings": "个人设置",
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ref } from "vue";
|
||||
import { my_network_func } from "@/my_network_func";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import MyOffcanvas from "@/components/MyOffcanvas.vue";
|
||||
import imageCropper from "@/components/imageCropper.vue";
|
||||
const user = useUserStore();
|
||||
const mos = ref();
|
||||
|
||||
@@ -32,5 +33,6 @@ function tt(){
|
||||
<button @click="tt">333</button>
|
||||
{{ user.userInfo }}
|
||||
</main>
|
||||
<imageCropper />
|
||||
<MyOffcanvas ref="mos" />
|
||||
</template>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { onMounted, watch, ref } from "vue";
|
||||
import settingNavigation from "@/components/settingNavigation.vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import datePicker from "@/components/datePicker.vue";
|
||||
import imageCropper from "@/components/imageCropper.vue";
|
||||
const { t } = useI18n();
|
||||
|
||||
const birthday = ref();
|
||||
@@ -46,6 +47,13 @@ function updataInfo() {
|
||||
console.log("备注:", userremarkValue);
|
||||
console.log("生日:", birthdayValue);
|
||||
}
|
||||
|
||||
onMounted(()=>{
|
||||
//console.log("account mounted");
|
||||
//username.value.value="Kevin";
|
||||
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -74,6 +82,7 @@ function updataInfo() {
|
||||
style="background-image: url(./static/avatars/000m.jpg)"
|
||||
></span>
|
||||
</div>
|
||||
<imageCropper />
|
||||
<div class="col-auto">
|
||||
<button class="btn">
|
||||
{{ t("settings.change_avatar") }}
|
||||
|
||||
Reference in New Issue
Block a user