vue3中使用canvas获取图片平均色

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.最终效果

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值