vue.js3: 调节图片的亮度/对比度/饱和度并保存(vue@3.2.37)
一,js代码
<template> <div style="position:relative;"> <div style="width: 700px;margin: auto;"> <h1>亮度/对比度/饱和度</h1> <div><input type="file" accept="image/*" @change="open" /> <button @click="reset">重置</button> </div> <div style="display: flex;margin-top: 5px;"><span style="width:56px;">亮度</span> <el-slider style="margin-left:10px;width:640px;" v-model="slideBright" :min="0" :max="300" show-input /></div> <div style="display: flex;margin-top: 5px;"><span style="width:56px;">对比度</span> <el-slider style="margin-left:10px;width:640px;" v-model="slideContrast" :min="0" :max="300" show-input /></div> <div style="display: flex;margin-top: 5px;"><span style="width:56px;">饱和度</span> <el-slider style="margin-left:10px;width:640px;" v-model="slideSaturate" :min="0" :max="300" show-input /></div> <div :style="{marginLeft:imgLeft+'px',width:imgDispWidth+'px',height:imgDispHeight+'px',overflow:'hidden',marginTop:'10px'}"> <div :width="imgWidth" :height="imgHeight" :style="{transform: 'scale('+scale+')',transformOrigin: originLeft+'% 0% 0px'}"> <!-- --> <svg id="mysvg" :width="imgWidth" :height="imgHeight" class="mysvg" :style="{transformOrigin: '50% 50% 0px',filter: 'brightness('+valueBright+') contrast('+valueContrast+') saturate('+valueSaturate+')'}"> <defs> </defs> <image id="img" :xlink:href="imgSrc" :width="imgWidth" :height="imgHeight" /> </svg> </div> </div> <div style="margin-top: 10px;"><button @click="save">保存</button></div> </div> </div> </template> <script> import {computed, ref} from "vue"; export default { name: "ImgBrightness", setup() { //亮度的滑杆值 const slideBright = ref(100); //对比度的滑杆值 const slideContrast = ref(100); //饱和度的滑杆值 const slideSaturate = ref(100); //亮度的值 let valueBright = computed( ()=> { return slideBright.value / 100; } ); //对比度的值 let valueContrast = computed( ()=> { return slideContrast.value / 100; } ); //饱和度的值 let valueSaturate = computed( ()=> { return slideSaturate.value / 100; } ); //保存修改 const save = () => { var str = document.getElementById("mysvg") let serializer = new XMLSerializer() var source = serializer.serializeToString(str); source = '<?xml version = "1.0" standalone = "no"?>\r\n' + source; var url = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(source); var canvas = document.createElement("canvas") canvas.width = imgWidth.value; canvas.height = imgHeight.value; var context = canvas.getContext("2d"); var image = new Image; image.src = url; image.crossOrigin = ''; image.onload = function () { context.drawImage(image, 0, 0,imgWidth.value,imgHeight.value); downJpgByCanvas(canvas); } } //下载图片 const downJpgByCanvas = (canvas) => { var oA = document.createElement("a"); let time = timeFormat(); oA.download = "img_"+time+'.jpg';// 设置下载的文件名,默认是'下载' oA.href = canvas.toDataURL("image/jpeg"); document.body.appendChild(oA); oA.click(); oA.remove(); // 下载之后把创建的元素删除 } //重置 const reset = () => { slideBright.value = 100; slideContrast.value = 100; slideSaturate.value = 100; }; //补0 const add0 = (m) => { return m<10?'0'+m:m } //格式化时间 const timeFormat = ()=>{ var time = new Date(); var y = time.getFullYear(); var m = time.getMonth()+1; var d = time.getDate(); var h = time.getHours(); var mm = time.getMinutes(); var s = time.getSeconds(); let res = y+add0(m)+add0(d)+add0(h)+add0(mm)+add0(s); return res; } //图片的src const imgSrc = ref(""); //图片的原宽高 const imgWidth = ref(0); const imgHeight = ref(0); //图片的显示宽高 const imgDispWidth = ref(0); const imgDispHeight = ref(0); //svg显示时缩放的比例 const scale = ref(0); //图片的left const imgLeft = ref(0); //svg显示位置的left: const originLeft = ref(0); //读取图片的信息 const open = (e) => { let file = e.target.files[0]; let reader = new FileReader(); reader.readAsDataURL(file); //文件加载成功 reader.onload = () =>{ //重置 reset(); //显示图片 imgSrc.value = reader.result; //得到宽高 let img = new Image(); img.src= reader.result; img.onload = () => { //保存原始宽高 imgWidth.value = img.width; imgHeight.value = img.height; if (img.width >= img.height) { imgDispWidth.value = 700; imgDispHeight.value = (700 * img.height) / img.width; scale.value = 700 / img.width; imgLeft.value = 0; } else { imgDispHeight.value = 500; imgDispWidth.value = (500 * img.width) / img.height; scale.value = 500 / img.height; imgLeft.value = (700-imgDispWidth.value) / 2; } if (scale.value > 1) { originLeft.value = 50; } else { originLeft.value = 0; } } } } return { valueBright, valueContrast, valueSaturate, slideBright, slideContrast, slideSaturate, save, open, imgSrc, imgWidth, imgHeight, imgDispWidth, imgDispHeight, imgLeft, originLeft, scale, reset, } } } </script> <style scoped> .mysvg { background: rgba(255, 255, 255, 0); border-radius: 0px; transform: scale(1, 1); } </style>
说明:刘宏缔的架构森林是一个专注架构的博客,
网站:https://blog.imgtouch.com
本文: https://blog.imgtouch.com/index.php/2023/06/03/vue-js3-tiao-jie-tu-pian-de-liang-du-dui-bi-du-bao-he-du/
对应的源码可以访问这里获取: https://github.com/liuhongdi/
或: https://gitee.com/liuhongdi
说明:作者:刘宏缔 邮箱: 371125307@qq.com
二,测试效果
三,查看vue框架的版本:
liuhongdi@lhdpc:/data/vue/pdf/image2pdf$ npm list vue image2pdf@0.1.0 /data/vue/pdf/image2pdf ├─┬ @vue/cli-plugin-babel@5.0.8 │ └─┬ @vue/babel-preset-app@5.0.8 │ ├─┬ @vue/babel-preset-jsx@1.3.0 │ │ └── vue@3.2.37 deduped invalid: "2.x" from node_modules/@vue/babel-preset-jsx │ └── vue@3.2.37 deduped └─┬ vue@3.2.37 └─┬ @vue/server-renderer@3.2.37 └── vue@3.2.37 deduped