1.在uilt文件中添加close.ts用于封装
/**
* 使用canvas获取图片平均色
* @param imgs
* @param callback
*/
export function canvasImgColor(imgs:any, callback:any) {
var imgSrc = imgs
var upload:any = document.getElementById('uploadImg')
const imgEle = document.createElement('img')
const canvas = document.createElement('canvas')
imgEle.src = imgSrc
imgEle.crossOrigin = '';
imgEle.onload = () => {
var ctx:any = canvas.getContext("2d");
var naturalImgSize = [imgEle.naturalWidth, imgEle.naturalHeight];
canvas.width = naturalImgSize[0];
canvas.height = naturalImgSize[1];
//绘制到canvas
ctx.drawImage(imgEle, 0, 0);
//获取imageData:rgba像素点
var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const leftSectionData:any = []
const rightSectionData:any = []
const oneLineImgDataLen = canvas.width * 4;
imgData.data.forEach((colorVal:any, i:any) => {
if (i % oneLineImgDataLen <= 0.5 * oneLineImgDataLen || i % oneLineImgDataLen >= 0.6 * oneLineImgDataLen) {
const inLeft = i % oneLineImgDataLen <= 0.5 * oneLineImgDataLen
if (i % 4 === 0) {
// 获取rgb均值
const curAverageRGB = (imgData.data[i] + imgData.data[i + 1] + imgData.data[i + 2]) / 3;
let leftOrRightRef = inLeft ? leftSectionData : rightSectionData;
//每个数组里存四个值:本颜色值中的r、g、b的均值,以及r、g、b三个值。
//均值一方面用于累加计算本区域的整体均值,然后再跟每个均值对比拿到与整体均值最接近的项的索引,再取该数组里的后三个值:rgb,对应着颜色
leftOrRightRef[leftOrRightRef.length] = [curAverageRGB, imgData.data[i], imgData.data[i + 1], imgData.data[i + 2]]
}
}
})
//generate average rgb
const averageOfLeft = Math.round(leftSectionData.reduce((_cur:any, item:any) => {
return _cur + item[0]
}, 0) / leftSectionData.length)
const averageOfRight = Math.round(rightSectionData.reduce((_cur:any, item:any) => {
return _cur + item[0]
}, 0) / rightSectionData.length)
//find the most near color
const findNearestIndex = (averageVal:any, arrBox:any) => {
let _gapValue = Math.abs(averageVal - arrBox[0])
let _nearColorIndex = 0
arrBox.forEach((item:any, index:any) => {
const curGapValue = Math.abs(item - averageVal)
if (curGapValue < _gapValue) {
_gapValue = curGapValue
_nearColorIndex = index
}
})
return _nearColorIndex
}
const leftNearestColor = leftSectionData[findNearestIndex(averageOfLeft, leftSectionData)]
const rightNearestColor = rightSectionData[findNearestIndex(averageOfRight, rightSectionData)]
upload.style.backgroundColor = `rgba(${leftNearestColor[1]},${leftNearestColor[2]},${leftNearestColor[3]},1) 0%,rgba(${rightNearestColor[1]},${rightNearestColor[2]},${rightNearestColor[3]},1)`
callback(upload.style.backgroundColor)
}
}
2.在需要使用的组件中引入使用
重点在于该代码canvasImgColor(form.value.imgUrl, (e: string) => {//第一个参数是图片路径
form.value.color = e
}),其他的上传图片组件没作用
<!-- 在html中 -->
<el-form-item label="广告图片" label-width="200px" style="width:100%;" v-show="picRequire" id="uploadImg" :style="{ background: form.color }">
<!-- action="http://192.168.1.188:8080/upload/admin"是上传图片的路径,一般后端提供 -->
<el-upload class="avatar-uploader" action="http://192.168.1.188:8080/upload/admin" :show-file-list="false"
:headers="headers" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
<img v-if="form.imgUrl" :src="form.imgUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
</el-form-item>
<script setup lang="ts">
import { Plus, Search } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox, type FormInstance, type UploadProps } from 'element-plus'
// 上传图片
// action="http://192.168.1.188:8080/upload/admin"//上传图片的路径(一般有提供上传路径,写在标签上的)
// 上传图片的请求头
const headers = reactive({
"AdminToken": Cookies.get("token")
})
// 成功后的回调
const handleAvatarSuccess: UploadProps['onSuccess'] = (
response,
uploadFile
) => {
form.value.imgUrl = response.url
//将背景色统一为第一个像素点的封装函数(按照需求是否引入调用)
canvasImgColor(form.value.imgUrl, (e: string) => {//第一个参数是图片路径
form.value.color = e
})
}
// 上传图片前的回调
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
if (rawFile.type !== 'image/jpeg' && rawFile.type !== 'image/png' && rawFile.type !== 'image/webp') {
ElMessage.error('Avatar picture must be JPG format!')
return false
} else if (rawFile.size / 1024 / 1024 > 1) {
ElMessage.error('Avatar picture size can not exceed 1MB!')
return false
}
return true
}
</script>
<style lang="less" scoped>
.avatar-uploader .avatar {
width: 178px;
height: 178px;
display: block;
}
</style>
<style>
.avatar-uploader .el-upload {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.avatar-uploader .el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
</style>
说明:该代码直接复制看不到效果,只是提供做法
3.最终效果