排列元素点击优先级

时间:2017-07-01 11:39:02

标签: javascript html css canvas flexbox

我有以下代码:(JSFIDDLE:https://jsfiddle.net/cjpLa44m/2/

<style>
body,
html {
  width: 100%;
  height: 100%;
  border: 0;
  padding: 0;
  margin: 0;
  overflow: hidden
}

.everything {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;

}
.mainImg img {
  width: 100%;
  height: 100%;
}
.mainImg {
  width: 50vh;
  height: 50vh;
  position: relative
}
#canvas{
    position: absolute;
    top: 0;
    left: 0;
}
</style>

<div class="everything">
    <div class="mainImg"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/SNice.svg/1200px-SNice.svg.png"></div>
</div>

<script>
var canvas      = document.createElement("canvas");
var width       = innerWidth;
var height      = innerHeight;
var ctx     = canvas.getContext('2d');
canvas.width    = width;
canvas.id = "canvas";
canvas.height   = height; 

ctx.fillStyle = "green";
ctx.fillRect(0,0, 50, 50);
ctx.fillRect(width / 2, height / 2, 50, 50);

window.onload = function () {
    document.body.appendChild(canvas);
    document.body.style.margin = "0";
    document.body.style.overflow = "hidden";    
};

canvas.onclick = function(){
    alert("Canvas called, although it shouldn't");
}

var smile = document.getElementsByClassName("mainImg")[0];
smile.onclick = function(){
alert("i should be called");
}
</script>

我有一个以浏览器为中心的图像,以及一个位于绝对位置的画布,遍布整个屏幕。 在显示方面,画布的显示优先于图像,这就是我想要它的方式,因为我使用画布的一些transperent部分来显示图像。

问题是点击优先级:正如您所看到的,当您点击笑脸图像时,画布的点击功能会被调用,因为它会在整个屏幕上传播。但就点击优先级而言,我希望调用我的图像。可以吗?

谢谢你的时间,我很感激。

2 个答案:

答案 0 :(得分:1)

如果您向#canvas规则添加pointer-events: none;,则会将点击转到图片

Updated fiddle

答案 1 :(得分:0)

事件无法冒泡,因为您将图像和画布放在单独的不相关元素中。如果将画布放在与图像相同的包含元素中,则单击事件将从一个映射到下一个

此外,您最好使用addEventListener而不是直接将事件侦听器分配给onclick属性。

在您的HTML中

<div class="everything">
    <div class="mainImg" id="contain">
        <img src="smile.png">
    </div>
    <!-- this is where the canvas will go -->
    <div id="canvasContainer"></div> <!-- add this div to hold the canvas -->
</div>

然后,当您添加画布时,将其添加到容器中,而不是document.body,然后添加事件侦听器。

window.onload = function () {
    document.getElementById("canvasContainer").appendChild(canvas);
    var smile = document.getElementsByClassName("mainImg")[0];
    smile.addEventListener("click",imageEvent);
    canvas.addEventListener("click",canvasEvent,true); // last arg true to capture the event (ie get it first)
};

执行此操作并希望画布首先获取事件时,必须将事件捕获标志设置为true

canvas.addEventListener("click",canvasEvent,true); // last argument true

如果您将其设置为false

canvas.addEventListener("click",canvasEvent,false); // last argument false
// or
canvas.addEventListener("click",canvasEvent); // or defaults to false

然后,图像元素(在画布下)将首先获得事件。

事件监听器

function imageEvent(e){ alert("Image") } // not much to do 
// the canvas event you need to either prevent the event bubbling
// or let it through depending on what your needs are.
function canvasEvent(e){
    if( /*only for canvas */){
       alert("Canvas handling it");
       e.cancelBubble = true;
    }else{
       alert("Canvas is passing the event onto the image");
    }
};