js realizes image direction gradient

1. Background

        In order to make the company's customized app website more diverse in style, a new gradient mode is proposed, which involves the gradient of the picture, and the transparency of the gradient of the picture can also be set

2. The core idea of ​​gradient

  1. draw the picture to the canvas
  2. Get the image pixels on the canvas
  3. Convert the color in hex format to the color in rgba format
  4. Obtain a list of color gradients based on two colors
  5. Then assign a value to each pixel according to the direction
  6. Finally, export the canvas as an image address in png format

3. Code implementation

1. Encapsulate a method for converting hex to rgba

export const hexToRgba = (hex) => {
	const rgb = []
	for (let i = 1; i < hex.length; i += 2) {
		rgb.push(parseInt('0x' + hex.slice(i, i + 2)))
	}
	return rgb
}

2. Encapsulate a method to get the list of gradient colors

import { hexToRgba } from "@/utils/icon-gradient/hexToRgba";

export const getGradientList = (startColor, endColor, step) => {
	const sColor = hexToRgba(startColor)
	const eColor = hexToRgba(endColor)

	const rStep = (eColor[0] - sColor[0]) / (step - 1)
	const gStep = (eColor[1] - sColor[1]) / (step - 1)
	const bStep = (eColor[2] - sColor[2]) / (step - 1)
	let aStep
    // 判断颜色有没有透明度
	if (eColor[3] && sColor[3]) {
		aStep = (eColor[3] - sColor[3]) / (step - 1)
	}

	const gradientColorsList = []

	for (let i = 0; i < step; i++) {
		if (aStep) {
			gradientColorsList.push(new Array(Math.round(rStep * i + sColor[0]), Math.round(gStep * i + sColor[1]), Math.round(bStep * i + sColor[2]), Math.round(aStep * i + sColor[3])))
		} else {
			gradientColorsList.push(new Array(Math.round(rStep * i + sColor[0]), Math.round(gStep * i + sColor[1]), Math.round(bStep * i + sColor[2])))
		}
	}

	return gradientColorsList
}

3. Encapsulate a method to get the address of the image after the gradient

import { getGradientList } from "@/utils/icon-gradient/getGradientList";

export const getImageUrl = (canvasDom, imageUrl, gradientColors, callback) => {
    const startColor = gradientColors.colors[0]
    const endColor = gradientColors.colors[1]
    const angle = gradientColors.angle
    const ctx = canvasDom.getContext('2d', { willReadFrequently: true })
    const w = canvasDom.width
    const h = canvasDom.height
    ctx.clearRect(0, 0, w, h)
    const image = new Image()
    image.src = imageUrl
    image.crossOrigin = "Anonymous";
    image.onload = () => {
        // 将图片绘制到画布上
        ctx.drawImage(image, 0, 0, w, h)
        // 获取画布上的图像像素
        const imgData = ctx.getImageData(0, 0, w, h)
        let gradientList
        if (angle == 0) {
            // 从下到上
            gradientList = getGradientList(startColor, endColor, h)
            for (let i = 0; i < w; i++) {
                for (let j = 0; j < h; j++) {
                    imgData.data[((i * (imgData.width * 4)) + (j * 4)) + 0] = gradientList[gradientList.length - 1 - i][0]
                    imgData.data[((i * (imgData.width * 4)) + (j * 4)) + 1] = gradientList[gradientList.length - 1 - i][1]
                    imgData.data[((i * (imgData.width * 4)) + (j * 4)) + 2] = gradientList[gradientList.length - 1 - i][2]
                    if (gradientList[gradientList.length - 1 - i][3]) {
                        imgData.data[((i * (imgData.width * 4)) + (j * 4)) + 3] = Math.round(imgData.data[((i * (imgData.width * 4)) + (j * 4)) + 3] * gradientList[gradientList.length - 1 - i][3] / 255)
                    }
                }
            }
        } else if (angle == 90) {
            // 从左到右
            gradientList = getGradientList(startColor, endColor, w)
            for (let i = 0; i < h; i++) {
                for (let j = w - 1; j >= 0; j--) {
                    imgData.data[((j * (imgData.width * 4)) + (i * 4)) + 0] = gradientList[i][0]
                    imgData.data[((j * (imgData.width * 4)) + (i * 4)) + 1] = gradientList[i][1]
                    imgData.data[((j * (imgData.width * 4)) + (i * 4)) + 2] = gradientList[i][2]
                    if (gradientList[i][3]) {
                        imgData.data[((j * (imgData.width * 4)) + (i * 4)) + 3] = Math.round(imgData.data[((j * (imgData.width * 4)) + (i * 4)) + 3] * gradientList[i][3] / 255)
                    }
                }
            }
        }
        // 将修改后的代码复制回画布中
        ctx.putImageData(imgData, 0, 0)
        // 图片导出为 png 格式
        const imgType = "image/png"
        canvasDom.toBlob((blob) => {
            callback(URL.createObjectURL(blob))
        }, imgType, 1)
    }
}

Note: If the address of the picture is a remote address, a cross-domain error will be reported, and the backend needs to change the header to *

Guess you like

Origin blog.csdn.net/m0_68349563/article/details/128442392