图片裁剪工具ok

Signed-off-by: 吴文峰 <kevin@lmve.net>
This commit is contained in:
2026-01-09 21:59:14 +08:00
parent d4e0062b21
commit 38668d82c4
4 changed files with 150 additions and 77 deletions
@@ -1,9 +1,11 @@
<script setup> <script setup>
import { Modal } from "@tabler/core"; import { Modal } from "@tabler/core";
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import "cropperjs"; import "cropperjs";
import { useI18n } from "vue-i18n";
const { t, locale } = useI18n();
const cro_sele = ref(); const cro_sele = ref();
const cro_canv = ref(); const cro_canv = ref();
const cro_imag = ref(); const cro_imag = ref();
@@ -18,49 +20,74 @@ reader.onload = () => {
initCropper(reader.result); initCropper(reader.result);
}; };
const emit = defineEmits(['crop'])
onMounted(() => { onMounted(() => {
cro_sele.value.$change(0, 0, cor_size_width, cor_size_height); cro_sele.value.$change(0, 0, cor_size_width, cor_size_height);
cro_canv.value.style.width = cor_size_width.toString() + "px"; cro_canv.value.style.width = cor_size_width.toString() + "px";
cro_canv.value.style.height = cor_size_height.toString() + "px"; cro_canv.value.style.height = cor_size_height.toString() + "px";
cro_imag.value.src = "https://wnfed.com/usr/uploads/2020/07/736937178.jpg"; cro_imag.value.src = "";
//console.log(cro_canv.value.clientHeight) //console.log(cro_canv.value.clientHeight)
}); });
function initCropper(imageSrc) { function initCropper(imageSrc) {
is_have_URL.value = true; is_have_URL.value = true;
cro_imag.value.src = imageSrc; cro_imag.value.src = imageSrc;
} }
function cancel() {
is_have_URL.value = false;
}
function inputfile(e) { function inputfile(e) {
const file = e.target.files[0]; const file = e.target.files[0];
if (!file) { if (!file) {
e.target.value="" e.target.value = "";
is_have_URL.value = false; is_have_URL.value = false;
return; return;
} }
if (!file.type.startsWith('image/')) { if (!file.type.startsWith("image/")) {
e.target.value="" e.target.value = "";
is_have_URL.value = false; is_have_URL.value = false;
return; return;
} }
reader.readAsDataURL(file); reader.readAsDataURL(file);
}
function openFilePicker() {
const fileInput = document.createElement("input");
fileInput.type = "file";
fileInput.accept = "image/*"; // 可选:限制文件类型
fileInput.multiple = false; // 可选:是否允许多选
fileInput.onchange = (e) => {
inputfile(e);
};
fileInput.click(); // 触发文件选择
} }
function getsele() { function getsele() {
console.log(cro_canv.value.$toCanvas()) const canvas = cro_canv.value.$toCanvas().then((a) => {
//console.log(a);
const imageData = a.toDataURL("image/png");
emit('crop',imageData)
//console.log(imageData);
});
} }
</script> </script>
<template> <template>
<div> <div class="d-flex flex-column flex-md-row">
<div class="col-6 col-sm-4 col-md-2 col-xl py-3"> <div v-show="!is_have_URL" class="col-6 col-sm-4 col-md-2 col-xl py-3">
<input class="btn btn-outline-primary" type="file" accept="image/*" @change="inputfile"> <button class="btn btn-outline-primary" @click="openFilePicker">
{{ t("cropper.select_image") }}
</button>
</div> </div>
<cropper-canvas <cropper-canvas
@@ -91,14 +118,36 @@ function getsele() {
></cropper-handle> ></cropper-handle>
</cropper-selection> </cropper-selection>
</cropper-canvas> </cropper-canvas>
</div>
<div class="col-6 col-sm-4 col-md-2 col-xl py-3"> <div v-show="is_have_URL" class="thisbutton">
<button class="btn btn-outline-primary" @click="getsele">getsele</button> <button class="btn btn-outline-primary" @click="getsele">
{{ t("cropper.crop_image") }}
</button>
<button class="btn btn-outline-danger" @click="cancel">{{ t("cropper.closs") }}</button>
</div>
</div> </div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.container {
display: flex;
/* 默认就是水平排列 */
/* flex-direction: row; */
}
.thisbutton {
display: flex;
flex-direction: column;
margin-left: 20px;
margin-top: 20px;
gap: 20px; /* 所有子元素之间的间距 */
}
.box {
margin: 10px;
flex-direction: column; /* 关键:改为纵向排列 */
}
.cropper-container { .cropper-container {
/* 四个角相同圆角 */ /* 四个角相同圆角 */
border-radius: 10px; border-radius: 10px;
+7
View File
@@ -8,6 +8,13 @@
"purchase": "Purchase", "purchase": "Purchase",
"warehouse": "Warehouse" "warehouse": "Warehouse"
}, },
"cropper": {
"select_image": "Select Image",
"select_File": "Select File",
"crop_image": "Crop Image",
"cancel": "Cancel",
"closs": "Closs"
},
"purchase": { "purchase": {
"purchase_list": "Purchase List", "purchase_list": "Purchase List",
"item_name": "Item Name", "item_name": "Item Name",
+7
View File
@@ -7,6 +7,13 @@
"schedule":"日程", "schedule":"日程",
"purchase":"采购", "purchase":"采购",
"warehouse":"仓库" "warehouse":"仓库"
},
"cropper": {
"select_image": "选择图片",
"select_File": "选择文件",
"crop_image": "裁剪图片",
"cancel": "取消",
"closs": "关闭"
}, },
"purchase":{ "purchase":{
"purchase_list":"采购列表", "purchase_list":"采购列表",
@@ -29,6 +29,9 @@ const cnfPassInput = ref();
const isShowPassword = ref(false); const isShowPassword = ref(false);
const is_avatar_change=ref(false);
const avatar_temp_url=ref("");
function togglePasswordVisibility() { function togglePasswordVisibility() {
isShowPassword.value = !isShowPassword.value; isShowPassword.value = !isShowPassword.value;
} }
@@ -241,6 +244,12 @@ function changeAvatar() {
); );
} }
function rev_avatar_url(url){
is_avatar_change.value=true
avatar_temp_url.value=url
//console.log(url)
}
function functionupdataTitle() { function functionupdataTitle() {
document.title = "Operations." + t("settings.account_settings"); document.title = "Operations." + t("settings.account_settings");
} }
@@ -283,16 +292,17 @@ onMounted(() => {
<div class="row align-items-center"> <div class="row align-items-center">
<div class="col-auto"> <div class="col-auto">
<img <img
:src="userStore.getUserAvatarPath()" :src="is_avatar_change?avatar_temp_url:userStore.getUserAvatarPath()"
alt="" alt=""
class="avatar avatar-xl" class="avatar avatar-xl"
/> />
</div> </div>
<!-- <imageCropper /> --> <!-- <imageCropper /> -->
<div class="col-auto"> <div class="col-auto">
<button class="btn" @click="changeAvatar"> <imageCropper @crop="rev_avatar_url"></imageCropper>
<!-- <button class="btn" @click="changeAvatar">
{{ t("settings.change_avatar") }} {{ t("settings.change_avatar") }}
</button> </button> -->
</div> </div>
</div> </div>
<h3 class="card-title mt-4">-</h3> <h3 class="card-title mt-4">-</h3>