<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:40px;">反色</span> <el-slider style="margin-left:10px;width:640px;" v-model="slideInvert" :min="0" :max="100" show-input /></div> <div style="display: flex;margin-top: 5px;"><span style="width:40px;">灰度</span> <el-slider style="margin-left:10px;width:640px;" v-model="slideGray" :min="0" :max="100" show-input /></div> <div style="display: flex;margin-top: 5px;"><span style="width:40px;">褐色</span> <el-slider style="margin-left:10px;width:640px;" v-model="slideSepia" :min="0" :max="100" 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: 'invert('+valueInvert+') grayscale('+valueGray+') sepia('+valueSepia+')'}"> <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: "grayScale", setup() { //反色的滑杆值 const slideInvert = ref(0); //灰度的滑杆值 const slideGray = ref(0); //褐色的滑杆值 const slideSepia = ref(0); //反色的值 let valueInvert = computed( ()=> { return slideInvert.value / 100; } ); //灰度的值 let valueGray = computed( ()=> { return slideGray.value / 100; } ); //褐色的值 let valueSepia = computed( ()=> { return slideSepia.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 = () => { slideInvert.value = 0; slideGray.value = 0; slideSepia.value = 0; }; //补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 { valueInvert, valueGray, valueSepia, slideInvert, slideGray, slideSepia, 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://www.cnblogs.com/architectforest
对应的源码可以访问这里获取: https://github.com/liuhongdi/
或: https://gitee.com/liuhongdi
说明:作者:刘宏缔 邮箱: 371125307@qq.com
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