首页 > 解决方案 > 当元素的所有像素都透明时触发事件

问题描述

我有一个网页,其中两个画布元素堆叠在一起。这是一些功能的基础,可以让我“擦除”顶部画布以显示加载到底部画布中的图像。该功能运行良好。

我现在要做的是在顶部画布完全“擦除”后触发一个事件,即顶部上下文的所有像素都是透明的。我在 SO 上找到了通过 getImageData 检查特定像素的 alpha 值的方法,但我试图找出一种方法来确定最后一个像素的 alpha 值何时 = 0。

我已经包含了我的代码以及使用 for 和 if 循环执行此操作的未完成尝试(但这似乎不是最好的方法)。我发现的另一个问题是,当我使用 getImageData 时,画布的两个边缘周围会出现一个细灰色边框。

提前感谢您的帮助!

在此处输入图像描述

window.onload = function() {
    //Move speaker image across page
    var speaker = document.getElementById('speaker');
    speaker.onload = MoveElement(speaker, "right", 1000);

    //Create canvases & contexts
    var canvas = document.getElementById('canvas');
    var ctxB = canvas.getContext('2d');
    var canvas2 = document.getElementById('canvas2');
    var ctxT = canvas2.getContext('2d');

    //Get waterfall image object
    var waterfall = document.getElementById('waterfall');

    //Set canvas w&h properties
    canvas.width = canvas2.width = .3*waterfall.width;
    canvas.height = canvas2.height = .3*waterfall.height;

    //Populate Bottom canvas with waterfall image
    ctxB.drawImage(waterfall, 0, 0, canvas.width, canvas.height);

    //Populate Top canvas with white rectangle
    ctxT.fillStyle = "white";
    ctxT.fillRect(0, 0, canvas2.width, canvas2.height);

    //Make Top canvas "erasable"
    canvas2.addEventListener('mousemove', event => {
        var x = event.offsetX;
        var y = event.offsetY;  
        const eraseSize = 125;
        ctxT.clearRect(x-eraseSize/2, y-eraseSize/2, eraseSize, eraseSize);
    })

    //Attempt to trigger an event when all pixels of top canvas have alpha = 0
    var imageDataTop = ctxT.getImageData(0, 0, canvas2.width, canvas2.height);
    console.log(imageDataTop);

    for (var i = 0; i < imageDataTop; i++) {
        if (imageDataTop.data[i] = 0) {
            //
        }

    }
}

function PlayAudio() {
    document.getElementById('boyfriend').play();
}


//Move an element in a given direction a certain distance
function MoveElement(element, direction, totalDistance) {
    //Determine horizontal or vertical direction
    var LeftOrTop = (direction=="left" || direction=="right") ? "left" : "top";
    
    //Set default frame distance
    var frameDistance = 150;

    //Adjust for backwards direction
    if (direction=="left" || direction=="up") {
        totalDistance *= -1;
        frameDistance = -1;
    }
    
    //Get style data object for element
    var elementStyle = window.getComputedStyle(element);

    //Get Left or Top position of element
    var positionValue = elementStyle.getPropertyValue(LeftOrTop).replace("px", "");

    //Apply direction and distance change to element
    var destination = (Number(positionValue) + totalDistance) + "px";

    function MoveFrame() {
        //If element reaches its destination...
        if (elementStyle.getPropertyValue(LeftOrTop) == destination) {
            //...stop the interval motion
            clearInterval(movingFrames);
        }
        //Otherwise, continue the interval movement
        else {
            elementStyle = window.getComputedStyle(element);
            positionValue = elementStyle.getPropertyValue(LeftOrTop).replace("px", "");
            element.style[LeftOrTop] = (Number(positionValue) + frameDistance) + "px";
        }
    }
    //Define time interval for movement
    var movingFrames = setInterval(MoveFrame, 500);
}
#stack {
    position: relative;
}
#stack canvas {
    position: absolute;
    display: block;
    left: 50%;
    transform: translateX(-50%);
    margin-top: 150px;
}

#speaker {
    position: absolute;
    top: 20px;

    animation-duration: 800ms;
    animation-name: fadein;
    animation-iteration-count: 10;
}
@keyframes fadein {
    from {
        opacity: 0.25;
    }
    50% {
        opacity: 1;
    }
    to {
        opacity: 0.25;
    }
}
<!DOCTYPE html>
{% load static %}
<html>
    <head>
        <meta charset="utf-8">
        <link rel="stylesheet" href="{% static 'entrance/entrance.css' %}">
        <script src="{% static 'entrance/entrance.js' %}"></script>
    </head>

    <body>
        <p hidden>
            <img src="{% static 'entrance/Waterfall.jpg' %}" alt="issue here" id="waterfall" />
        </p>
        
        <img src="{% static 'entrance/sound-icon.svg' %}" id="speaker" />
        <p id="test"></p>

        <audio id="boyfriend" source src="{% static 'entrance/02 30 Minute Boyfriend.mp3' %}" type="audio/mp3"></audio>
        <div id="stack" onmouseenter="PlayAudio()">
            <canvas id="canvas"></canvas>
            <canvas id="canvas2"></canvas>
        </div>
    </body>
</html>

标签: javascripthtmlcsscanvasalpha

解决方案


您获得的数据图像将是一个数组,在画布上每个点有 4 个字节,其中前 3 个字节是 RGB 颜色,第 4 个字节是 alpha。

如果颜色是透明的,则第 4 个将是 0。每次擦除完成时,您都需要查看数组中的每个第 4 个字节。如果你遇到一个不为零的,你就会知道擦除不完整。

这是一个非常有用的参考:https ://www.w3schools.com/tags/canvas_getimagedata.asp


推荐阅读