簡體   English   中英

THREE.js 旋轉煙霧效果只適用於一個元素而不適用於所有元素

[英]THREE.js revolving smoke effect works only for one element instead of applying to all elements

我正在嘗試為論壇網站創建自定義帖子 header 背景。 但是因為我總是想讓我的生活變得更加艱難,所以我試圖讓它變得花哨。 我還需要在每篇文章中鏈接到該腳本。

當我復制帖子(或僅通過 ctrl+a ctrl+c ctrl+v ctrl+v HTMP 代碼模擬它)時,只有最后一個帖子獲得任何煙霧效果背景。 我試圖在 init 上將 function 添加到 window 並使用 SiffrinSmoke class 為每個元素循環它,但仍然只顯示一根煙霧 - 在底部。

HTML:

<div class="SiffrinBody">
    <div class="SiffrinHeader">
        <div class="SiffrinSmoke">
            <!--h1>Siffrin<br>Drauglir</h1-->
            <h1 data-heading="Siffrin&#xa;Drauglir"></h1>
        </div>
        <div class="SiffrinCanvasBackground" id="SiffrinCanvasBackground"></div>
        <div class="SiffrinCanvasForeground" id="SiffrinCanvasForeground"></div>
        <img id="SiffrinHeaderBackground" src="https://i.imgur.com/iYnkBdZ.jpg">
        <img id="SiffrinWolf" src="https://i.imgur.com/MBLqG00.png">
    </div>
</div>

CSS:

 @import url('https://fonts.googleapis.com/css2?family=Arvo:ital@0;1&family=Carter+One&family=Dosis:wght@400;500;600&display=swap');

    .SiffrinBody .SiffrinHeader .SiffrinCanvasBackground{
        height: 330px;
        width: 656px;
        position: absolute;
        left: inherit;
        top: inherit;
        z-index: 5;
    }

    .SiffrinBody .SiffrinHeader .SiffrinCanvasForeground{
        height: 330px;
        width: 656px;
        position: absolute;
        left: inherit;
        top: inherit;
        z-index: 7;
    }

    .SiffrinBody .SiffrinHeader img{
        position: absolute;
        height: 330px;
        width: 656px;
        grid-row: 1;
    }

    .SiffrinBody .SiffrinHeader .SiffrinSmoke{
        width: 328px;
        height: 330px;
        position: relative;
        z-index: 6;
        float: right;
        display: block;
    }

    .SiffrinBody .SiffrinHeader .SiffrinSmoke canvas{
        position: absolute;
        top: 0;
        left: 0;
        z-index: -4;
    }

    .SiffrinBody .SiffrinHeader #SiffrinHeaderBackground{
        z-index: 4;
    }

    .SiffrinBody .SiffrinHeader #SiffrinWolf{
        z-index: 6;

    }

    .SiffrinBody .SiffrinHeader h1{
        font-family: Carter One;
        z-index: 1000;
        color: white;
        grid-column: 2;
        font-size: 50;
        margin-top: 32%;
        text-align: center;
        background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/209981/6963bbf342d87b3a2150bd8f59682b89.jpg);
        -webkit-background-clip: text;
        background-size: cover;
        width: 100%;
        color: transparent;
        font-weight: 900;
        display: block;
        white-space: pre-wrap !important;
        line-height: 1.1em;
        text-shadow:  2px 2px 6px rgba(46,146,211,0.8);
    }

    .SiffrinBody .SiffrinHeader h1::before{
        content: attr(data-heading);
        position: relative;
        left: 0;
        top: 0;
        width: 100%;
        background: linear-gradient(45deg, rgba(255,255,255,0) 45%,rgba(255,255,255,0.8) 50%,rgba(255,255,255,0) 55%,rgba(255,255,255,0) 100%);
        -webkit-background-clip: text;
        color: transparent;
        mix-blend-mode: screen;
        animation: SiffrinShine 15s infinite linear;
        background-size: 200%;
    }

    .SiffrinBody .SiffrinHeader #SiffrinName{
        z-index: 22;
        transform: scale(0.8);
        left: 150px;
    }

    .SiffrinBody .SiffrinHeader{
        grid-row: 1;
        mask-image: linear-gradient(
            to top,
            rgba(255, 255, 255, 0) 0,
            rgba(255, 255, 255, 1) 15px
        );
    }

    .SiffrinBody .SiffrinHeader > *{
        user-select: none;
    }

    .SiffrinBody{
        color: white;
        display: grid;
        grid-template-rows: 330px auto auto;
        grid-template-columns: 1fr;
        margin: 0;
        padding: 0;
        width: 656px;
        /*background-image: linear-gradient(#bad4eb, #bad4eb, #a7c8e7, #4789c6, #037ccf);*/
        background-image: url("https://i.imgur.com/UqFcRzS.jpg");
        background-repeat: repeat;
    }

    .SiffrinBody *::selection{
        background: rgba(225, 0, 255, 0.3);
        color: inherit;
    }

    .SiffrinBody .SiffrinHeader{
        /*
        z-index: 7;
        text-align: center;
        font-family: Oleo Script;
        margin: auto;
        font-size: 30px;
        transition-duration: 2s;
        transition-timing-function: ease-in-out;
        background-image: radial-gradient(#0e111800, #232b3e00, #24212a00, #403b6600);
        user-select: none;
        */
    }

    .SiffrinBody .SiffrinBody:hover .SiffrinHeader{
        /*
        letter-spacing: 0.35em;
        transition-duration: 3s;
        transition-timing-function: ease-in-out;
        transform: translate(0px, 40px);
        */
    }

    .SiffrinBody .SiffrinText{
        z-index: 7;
        margin: 10px 50px;
        padding: 20px;
        background-color: rgba(0, 0, 0, 0.5);
        font-family: Dosis;
        font-size: 17px;
        margin-bottom: 0;
        line-height: 1.235em;
        font-weight: 500;
    }

    .SiffrinBody .SiffrinText::before{
  
        border-top: 3px solid blue;
        border-right: 3px solid blue;
    }

    .SiffrinBody .SiffrinText::after{

        border-bottom: 3px solid orange;
        border-left: 3px solid orange;
    }

    .SiffrinBody .SiffrinText p{
        padding: 0;
        margin-bottom: 1em;
    }

    .SiffrinBody .SiffrinText p u,
    .SiffrinBody .SiffrinText p i,
    .SiffrinBody .SiffrinText p q{
        font-family: Arvo;
        font-size: 16px;
    }

    .SiffrinBody .SiffrinText p u{
        text-decoration: none;
        color:rgb(250, 210, 255);
    }

    .SiffrinBody .SiffrinText p u::before {
        content: "“"
    }

    .SiffrinBody.SiffrinText p u::after {
        content: "”"
    }

    .SiffrinBody .SiffrinText p i{
        font-family: Arvo;
        color:rgb(250, 210, 255);
        font-style: italic;
    }

    .SiffrinBody .SiffrinText p q{
        text-decoration: none;
        color:rgb(219, 223, 255);
    }

    .SiffrinBody .SiffrinText p:last-child{
        margin: 0;
    }

    .SiffrinBody .SiffrinText p:first-child{
        margin-top: 0;
    }

    .SiffrinBody .SiffrinFooter{
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 10px;
        margin: 0;
    }

    .SiffrinBody .SiffrinFooter p{
        text-align: center;
        font-size: 20px;
        color: #f8f7fd;
        text-align: center;
    }

    @keyframes SiffrinShine {
        0% {background-position: 110%;}
        60% {background-position: -90%;}
        100% {background-position: -90%;}
    }

進口三:

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>

記者:

function initiateSmoke() {
        smokeBackgrounds = document.getElementsByClassName('SiffrinSmoke');
        clock = new THREE.Clock();
        renderW = smokeBackgrounds[0].offsetWidth;
        renderH = smokeBackgrounds[0].offsetHeight;
        renderer = new THREE.WebGLRenderer({ alpha: true });
        renderer.setSize( renderW, renderH );

        scene = new THREE.Scene();
    
        camera = new THREE.PerspectiveCamera( 75, renderW / renderH , 1, 10000 );
        camera.position.z = 1300;
        scene.add( camera );
    
        geometry = new THREE.CubeGeometry( 200, 200, 200 );
        material = new THREE.MeshLambertMaterial( { color: 0xaa6666, wireframe: false } );
        mesh = new THREE.Mesh( geometry, material );
        cubeSineDriver = 0;
    
        textGeo = new THREE.PlaneGeometry(300,300);
        THREE.ImageUtils.crossOrigin = ''; //Need this to pull in crossdomain images from AWS

        light = new THREE.DirectionalLight(0xffffff, 1);
        light.position.set(-1,0,1);
        scene.add(light);
    
        smokeTexture = THREE.ImageUtils.loadTexture('https://s3-us-west-2.amazonaws.com/s.cdpn.io/95637/Smoke-Element.png');
        smokeMaterial = new THREE.MeshLambertMaterial({color: 0x333333, opacity: 1, map: smokeTexture, transparent: true});
        smokeGeo = new THREE.PlaneGeometry(650,650);
        smokeParticles = [];

        for (p = 0; p < 36; p++) {
            particle = new THREE.Mesh(smokeGeo,smokeMaterial);
            particle.position.set(Math.random() * 950 - 500, Math.random() * 620 - 300, Math.random() * 200 - 100);
            particle.rotation.z = Math.random() * 360;
            particle.scale.set(2,2,2);
            scene.add(particle);
            smokeParticles.push(particle);
        }
        for(i = 0; i < smokeBackgrounds.length; i++) {
            smokeBackgrounds[i].appendChild( renderer.domElement );
        }
    }
        
    function animateSmoke() {
        // note: three.js includes requestAnimationFrame shim
        delta = clock.getDelta();
        requestAnimationFrame( animateSmoke );
        evolveSmoke();
        render();
    }
        
    function evolveSmoke() {
        var sp = smokeParticles.length;
        while(sp--) {
            smokeParticles[sp].rotation.z += (delta * 0.2);
        }
    }

    function render() {
        mesh.rotation.x += 0.005;
        mesh.rotation.y += 0.01;
        cubeSineDriver += .01;
        mesh.position.z = 100 + (Math.sin(cubeSineDriver) * 500);
        renderer.render( scene, camera );
    }

    window.onload = function Snowfall(){
        initiateSmoke();
        animateSmoke();
}

你知道如何為 class 的每個元素應用與背景相同的效果嗎? 也許另一種工具更適合這項工作?

編輯:解決方案Smoke init function 接受之前的背景元素並返回相關對象

function initiateSmoke(smokeBackground) {
[...]
        return({
            "renderer": renderer,
            "scene": scene,
            "camera": camera,
            "mesh": mesh,
            "cubeSineDriver": cubeSineDriver,
            "smokeParticles": smokeParticles
        })
}

然后在 window.onload 我有這個循環

        smokeBackgrounds = document.getElementsByClassName('SiffrinSmoke');

        for(i = 0; i < smokeBackgrounds.length; i++) {
            smokeScenes[i] = initiateSmoke(smokeBackgrounds[i]);
            smokeBackgrounds[i].appendChild(smokeScenes[i]['renderer'].domElement);
        }
        
        animateSmoke();

我還編輯了動畫功能

    function animateSmoke() {
        delta = clock.getDelta();
        requestAnimationFrame(animateSmoke);
        evolveSmoke();
        render();
    }
        
    function evolveSmoke() {
        for(i = 0; i < smokeScenes.length; i++) {
            smokeScene = smokeScenes[i];
            var sp = smokeScene['smokeParticles'].length;
            while(sp--) {
                smokeScene['smokeParticles'][sp].rotation.z += (delta * 0.2);
            }
        }
    }

    function render() {
        for(i = 0; i < smokeScenes.length; i++) {
            smokeScene = smokeScenes[i];
            smokeScene['mesh'].rotation.x += 0.005;
            smokeScene['mesh'].rotation.y += 0.01;
            smokeScene['cubeSineDriver'] += .01;
            smokeScene['mesh'].position.z = 100 + (Math.sin(smokeScene['cubeSineDriver']) * 500);
            smokeScene['renderer'].render( smokeScene['scene'], smokeScene['camera']);
        }
    }

    let smokeScenes = []
    let clock = new THREE.Clock();

那行得通!

這是因為您只創建了一個 canvas,並將其附加到循環中的每個“smokeBackgrounds”。 但是每一個都會覆蓋最后一個,因為只有一個 canvas (renderer.domElement)。

有幾種方法可以解決它:

  1. 在此代碼之外創建一個循環,循環通過 smokeBackgrounds,並調用 initiateSmoke(smokeBackgrounds[i]),然后將該循環更改為使用傳入的 dom 元素的方法末尾。
  2. 克隆 canvas 本身,並為每個新實例分配一個 smokeBackgrounds。
  3. (困難)在代碼中創建多個 threejs 場景,並在頁面上為每個場景分配一個 position。 通過這種方式,您可以將 canvas 拉伸到整頁,只需移動煙霧位置即可與 HTML 元素所在的位置相關聯。 這樣做的好處是它更輕,因為您不會同時運行多個畫布。

暫無
暫無

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

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