web端获取图片主色调

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Awesome-color-picker</title>
    <style>
        .banner-container {
            background-size: contain;
            background-position: center;
            background-repeat: no-repeat;
            box-sizing: border-box;
            /*padding-top: 16%;*/
            aspect-ratio: 2;
            background-image: url(http://localhost:63342/awesome-banner/assets/demo3.png);
        }
        #img-contaner{
            margin-top: 10px;
            font-size: 0;
        }
        #box {
            width: 100px;
            height: 100px;
            background-color: #000;
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<input type="file" accept="image/png,image/jpep,image/jpg"/>
<div id="img-contaner">
    <img/>
</div>
<div id="box"></div>
<script>
    let canPickColor = false
    let imageData = null
    let imageSize = null
    document.querySelector('input').onchange = (e) => {
        const file = e.target.files[0];
        const fileReader = new FileReader()
        fileReader.onload = (e) => {
            //get image data
            getImgDataBySrc(e.target.result, (_imgData, _imgSize) => {
                document.querySelector('#img-contaner > img').src = e.target.result;
                canPickColor = true
                imageData = _imgData
                imageSize = _imgSize
            })
        }
        fileReader.readAsDataURL(file)
    }

    document.querySelector('#img-contaner > img').addEventListener('mousemove', (event) => {
        if (event.offsetX > 0 && event.offsetY > 0 && canPickColor) {
            const colors = getSectionsMainColor(imageData, imageSize, [
                {
                    sx: event.offsetX,
                    sy: event.offsetY,
                    sw: 1,
                    sh: 1
                },
            ])
            document.querySelector('#box').style.backgroundColor = colors[0]
        }
    })
    const getImgDataBySrc = (imgSrc, callback) => {
        const imgEle = document.createElement('img')
        const canvas = document.createElement('canvas')
        imgEle.src = imgSrc
        imgEle.onload = () => {
            var ctx = canvas.getContext("2d");
            var naturalImgSize = [imgEle.naturalWidth, imgEle.naturalHeight];
            canvas.width = naturalImgSize[0];
            canvas.height = naturalImgSize[1];
            ctx.drawImage(imgEle, 0, 0);
            //获取imageData
            var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            //打印该数据
            callback(imgData, {
                width: canvas.width,
                height: canvas.height
            })
        }
    }
    /**
     * @param imgData: ImageData
     * @param imgSize:{ width:number,height:number }
     * @param sections: Array<{
     *     sx,
     *     sy,
     *     sw,
     *     sh
     * }>
     */
    const getSectionsMainColor = (imgData, imgSize, sections) => {
        //one pxl dot has four values:rgba
        const oneRowImgDataLen = imgSize.width * 4;
        if (sections.sx > imgSize.width || (sections.sx + sections.sw) > imgSize.width) {
            throw 'section error'
        }
        if (sections.sy > imgSize.height || (sections.sy + sections.sh) > imgSize.height) {
            throw 'section error'
        }

        //[[avg,r,g,b],...]
        const sectionColorsData = []
        //[133,131,124,...]
        const sectionAverageValues = []
        imgData.data.forEach((colorVal, i) => {
            //extract sections
            sections.forEach((section, sectionIdx) => {
                if (i % oneRowImgDataLen >= 4 * section.sx && i % oneRowImgDataLen <= 4 * (section.sx + section.sw)) {
                    if (Math.ceil(i / oneRowImgDataLen) >= section.sy && Math.ceil(i / oneRowImgDataLen) <= (section.sy + section.sh)) {
                        if (i % 4 === 0) {
                            //get average value of rgb
                            const curAverageRGB = (imgData.data[i] + imgData.data[i + 1] + imgData.data[i + 2]) / 3;
                            if (!sectionColorsData[sectionIdx]) {
                                sectionColorsData[sectionIdx] = []
                            }
                            sectionColorsData[sectionIdx].push([curAverageRGB, imgData.data[i], imgData.data[i + 1], imgData.data[i + 2]])
                        }
                    }
                }
            })
        })
        //generate section's average rgb
        sectionColorsData.forEach((sectionColorData, idx) => {
            sectionAverageValues[idx] = Math.round(sectionColorData.reduce((_cur, sectionColor) => {
                return _cur + sectionColor[0]
            }, 0) / sectionColorData.length)
        })

        //find the most near color
        const findNearestIndex = (sectionColorData, averageVal) => {
            let _gapValue = Math.abs(averageVal - sectionColorData[0][0])
            let _nearColorIndex = 0
            sectionColorData.forEach((colorData, index) => {
                const curGapValue = Math.abs(colorData[0] - averageVal)
                if (curGapValue < _gapValue) {
                    _gapValue = curGapValue
                    _nearColorIndex = index
                }
            })
            return _nearColorIndex
        }

        const sectionMainColors = sectionColorsData.map((sectionColorData, idx) => {
            const color = sectionColorData[findNearestIndex(sectionColorData, sectionAverageValues[idx])]
            return `rgb(${color[1]},${color[2]},${color[3]})`
        })
        return sectionMainColors
    }
</script>
</body>
</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值