簡體   English   中英

使用 React 將動態 canvas 作為 div 的背景

[英]Making dynamic canvas a background to a div using React

我想使用 React 為我網站中的特定組件制作動態背景。 我想這樣做,所以這個背景是運行 react-particle-js 模擬的 canvas。 一切都在 React 組件中,並像往常一樣使用render()方法進行渲染。 結果應該看起來

像這樣的東西

具有背景的組件的代碼應如下所示:

class ParticleBackgrondComponent extends Component{

render(){
    return (

        <div>
            <Particles/> {//The particle background}

            <h3>
                Some other content
            </h3>
            <p>
                Lorem ipsum dolor sit amet...
            </p>

        </div>
    )
}

}

我嘗試將所述 canvas 的 position 設置為絕對值並手動將其放在我想要的 div 后面,但是當我調整 window 的大小時它不起作用。

您正在尋找CSS element() function

.dynamic-background {
  background: element(.particle-canvas);
}

但是,目前(2020 年 4 月)它僅受 firefox 使用非標准-moz-element()支持。 如果您目前計划針對更多瀏覽器,我建議您尋找替代解決方案。

雖然element()仍然不受支持,但您絕對可以 position 將背景元素放在前景元素后面,並根據前景的大小動態設置 canvas 的寬度和高度:

 const TAU = 2 * Math.PI; class Circle { constructor(canvas) { this.x = Math.random() * canvas.width; this.y = Math.random() * canvas.height; this.r = Math.random() * Math.sqrt(canvas.width ** 2 + canvas.height ** 2) / 8; this.growth = Math.random() * 4; this.decay = Math.max(Math.random() * 0.005, 0.0005); this.rgb = [ Math.random() * 255, Math.random() * 255, Math.random() * 255, ]; this.alpha = Math.random() * 0.35; } get fillStyle() { return `rgba(${this.rgb.join(',')},${this.alpha})`; } render(ctx) { ctx.beginPath(); ctx.fillStyle = this.fillStyle; ctx.arc(this.x, this.y, this.r, 0, TAU); ctx.fill(); this.r += this.growth; this.alpha -= this.decay; } } function render(ctx, foreground, circles = []) { const { width, height } = foreground.getBoundingClientRect(); ctx.canvas.width = width; ctx.canvas.height = height; ctx.clearRect(0, 0, width, height); if (circles.length === 0) { circles.push(new Circle(ctx.canvas)); } if (Math.random() > 0.98) { circles.push(new Circle(ctx.canvas)); } for (const circle of circles) { circle.render(ctx); } window.requestAnimationFrame(() => { render(ctx, foreground, circles.filter(circle => circle.alpha > 0)) }); } window.addEventListener("DOMContentLoaded", () => { const canvas = document.querySelector("canvas"); const foreground = document.querySelector(".foreground"); render(canvas.getContext("2d"), foreground); });
 .container { position: relative; }.background { position: absolute; z-index: -1; }
 <div class="container"> <canvas class="background"></canvas> <div class="foreground"> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur placerat quam a vulputate tincidunt. Aliquam pretium leo quis justo pretium, in pellentesque augue viverra.</p> <p>Quisque lacinia ipsum id purus varius molestie. Integer tincidunt elementum condimentum. Praesent molestie, nunc sed ullamcorper accumsan, augue urna maximus lorem, at venenatis orci tellus vitae leo.</p> <p>Pellentesque eget lacus sagittis, sollicitudin mauris eget, hendrerit est. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sapien odio, ullamcorper in erat vitae, mollis vulputate leo.</p> </div> </div>

所以,我找到了一種方法。 基本上,我試圖調整 canvas 的大小和位置,基於getBoundingClientRect方法( 參見文檔),每次 window 調整大小時:

class ParticleBackgroundComponent extends Component{
    constructor(props){
        super(props);

        //to help us get the boundingClientRect
        this.selector = React.createRef();

        //our state variables that store dimensions an position of the background
        this.state = {
            width: 0,
            height: 0,
            top: 0
        };
    }

    componentDidMount() {
        /*the first event listener to figure out when the page is done loading
        (use this if you have images in the component)*/
        window.addEventListener('load', () => {

            //setting the state to draw the background the first time
            var rect = this.selector.current.getBoundingClientRect();
            this.setState({
                width: rect.width,
                height: rect.height,
                top: rect.top + window.scrollY
            });

            //second event listener for resizing
            window.addEventListener('resize', ()=>{
                //redraw the background every time the page resizes 
                rect = this.selector.current.getBoundingClientRect();
                this.setState({
                    width: rect.width,
                    height: rect.height,
                    top: rect.top + window.scrollY
                })
            });

        });
    }

    //to render the particles
    renderBackground(){
        var width = this.state.width;
        var height = this.state.height;
        var top = this.state.top;

        //using a div to set the position of the background
        return (
            <div style={{position: "absolute", top: t, zIndex: -1}}>
                <Particles width={width} height={height}/>
            </div>
        )
    }

    render(){
        return (
            <div ref={this.selector}>

                <h1>
                    Some more content
                </h1>
                <p>
                    Lorem Ipsum dolor sit amet...
                </p>

                {this.renderBackground()}

            </div>
        )
    }
}

多么長的答案。 我不認為這是最好的方法(而且絕對不是最有效的),因為我對使用 React 甚至 Javascript 還是很陌生。 如果有人可以改進這個答案,一定要這樣做

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM