The cause of

Today, the product manager came to say that we need to add a rotation chart similar to tmall on the home page. The rotation chart of Tmall is the picture with fixed width and height. When the screen with different resolutions is displayed, the left and right gaps of the container will be filled according to the background color of the picture. For example, a 1800px screen:

3000 px screen:

First reaction: no matter js or CSS, there is no way to get the color value of the image, that must be the server to me. Either the background CMS specified the background color in the last image, or the server called the image API to get the background color and gave it to me.

That’s what Tmall should do.

AutoImg

Pure front-end, is there a way to get the color value? It occurred to me that when I was doing WebGL textures, I could get the color value of every pixel of the image in the pixel shader. WebGL is definitely too big to use, is Canvas ok? Query is ok, there are methods getImageData. So at least pure front-end cooking is possible. Let’s start with an AutoImg component. The img in AutoImg has a fixed height and width, and the container’s background color is filled with the IMG background color.

export default class AutoImg extends Component {
    static propTypes = {
        height: PropTypes.number.isRequired,
        width: PropTypes.number.isRequired,
        source: PropTypes.number.isRequired,
    }

    componentDidMount() {
        this.setImg(this.props.source)
    }

    componentWillReceiveProps(nextProps) {
        if(nextProps.source ! = =this.props.source) {
            this.setImg(nextProps.source)
        }
    }

    setImg(source) {
        const { width, height } = this.props

        const ima = new Image()
        ima.src = source
        ima.crossOrigin = ' ' // Handle cross-domain images
        ima.onload = (a)= > {
            const ctx = this.canva.getContext('2d')
            ctx.drawImage(ima, 0.0, width, height)

            const [r, g, b, a] = ctx.getImageData(0.0.1.1).data; // Get the background color
            this.inner.style.background = `rgba(${r}.${g}.${b}.${a}) `
        }
    }

    render() {
        const { width, height } = this.props
        return (
            <div ref={inner= > this.inner = inner}>
                <canvas
                    style={{
                        display: 'block',
                        margin: '0 auto'}}width={` ${width}px`}
                    height={` ${height}px`}
                    ref={canva= > this.canva = canva}
                >

                </canvas>
            </div>)}}Copy the code

GetImageData is an integer. Width and height must be of type number. 1000 means 1000px

github npm: npm install rc-autoimg --save

shuffling

We don’t make wheels, we just use nuka-Carousel.

import Carousel from 'nuka-carousel'

default class Banner extends Component {
    render() {
       const bannerImgList = [
        'https://img.alicdn.com/tps/i4/TB1yqAhcpmWBuNjSspdSuvugXXa.jpg'.'https://img.alicdn.com/tps/i4/TB1XVCsaTdYBeNkSmLySutfnVXa.jpg'.'https://img.alicdn.com/simba/img/TB1ror0cf5TBuNjSspcSuvnGFXa.jpg'.'https://img.alicdn.com/tfs/TB1ed2lggmTBuNjy1XbXXaMrVXa-1130-500.jpg_q100.jpg_.webp',]return (
            <div className={styles.banner}>
                <Carousel
                    autoplay={true}
                >
                    {
                        bannerImgList.map(source => (
                            <div key={source}>
                                <AutoImg
                                    width={1200}
                                    height={340}
                                    source={source}
                                />
                            </div>))}</Carousel>
            </div>)}}Copy the code

2500 px effect:

conclusion

Perhaps you also have this kind of rotation needs, if there is no hope to extract the color of the place, can inspire you.