是否可以在 canvas 标签内创建下拉菜单

Is it possible to create a drop down menu within a canvas tag

我正在使用 HTML5 <canvas></canvas> 标签,我一直在尝试查找有关 是否可以在 [=19] 中包含下拉菜单的信息=]?

据我所知这是不可能的。

没有...

canvas 不是容器元素,因此您不能在 canvas 中包含下拉菜单。

如果需要,您可以使用 CSS 在 canvas 上放置一个下拉小部件。

看完这个问题。我试图在 canvas 中创建一个下拉菜单。这是经过大量努力后的结果:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var selected = "Selected item";
var labels = ["1","2","3"];
var mainDrop = {
 x: 50,
  y: 50,
  width: 100,
  height: 20
};
var itemDrop = {
 x: mainDrop.x,
 width: 100,
  height: 20
};
var visible = false;

function getMousePos(canvas, event)
{
  var rect = canvas.getBoundingClientRect();
  return {
    x: event.clientX - rect.left,
    y: event.clientY - rect.top
  };
}
function isInside(pos, rect)
{
  return pos.x > (rect.x-(rect.x/100*10)) && pos.x < rect.x+rect.width && pos.y < rect.y+(rect.height/2) && pos.y > (rect.y-(rect.y/100*50));
}

function drawDropdown(selected, items, x, y, w, h){
 ctx.strokeStyle = "black";
 ctx.strokeRect(x,y, w,h);
  
  ctx.fillText(selected, x+(x/10), y+(y/4));
}

function drawItems(labels, x,y, w,h)
{
 for(var i=0; i < labels.length; i++)
  {
   if(i==0)
    {
     ctx.strokeRect(x, y+h, w,h);
      ctx.fillText(labels[i], x+(x/10), y+h+(h/2));
    }
    else{
     ctx.strokeRect(x, y+(h*(i+1)), w, h);
      ctx.fillText(labels[i], x+(x/10), y+(h*(i+1))+(h/2));
    }
  }
}

function onItemClick(mousePos, labels)
{
 if(isInside(mousePos, {x:itemDrop.x, y: mainDrop.y+(mainDrop.height*(labels.length)), width: mainDrop.width, height: mainDrop.height}))
  {  
    var item = insideItem(mousePos);
    var oldItem = selected;
    if(item != selected)
     newLabel(item, oldItem);
  }
}

function insideItem(mousePos){
 var mouseY = mousePos.y;
  var startPos;
  var nextPos;
  for(var i=0; i < labels.length; i++)
  {
    startPos = mainDrop.y + (mainDrop.height*(i+1));
      nextPos = startPos + mainDrop.height;
      if(mouseY < nextPos && mouseY > startPos)
      {
       return labels[i];
      }        
  }
  return selected;
}

function newLabel(newLabel, removedLabel){
 ctx.clearRect(mainDrop.x, mainDrop.y, canvas.width, canvas.height);
  selected = newLabel;
  labels[labels.indexOf(selected)] = removedLabel;
  ctx.clearRect(0,0, canvas.width, canvas.height);
    drawDropdown(selected, labels, mainDrop.x, mainDrop.y, mainDrop.width, mainDrop.height);
    visible = false;
}

$('#canvas').on('mousemove', function(e){
 var labelsHeight = mainDrop.y + mainDrop.height + (mainDrop.height * (labels.length+1));
 var mousePos = getMousePos(canvas, e);
 if(isInside(mousePos, mainDrop))
  {
   drawItems(labels, mainDrop.x, mainDrop.y, mainDrop.width, mainDrop.height);
    visible = true;
  }
  else if(!isInside(mousePos, {x:mainDrop.x,y:mainDrop.x,width:mainDrop.width, height:labelsHeight}))
  {
   ctx.clearRect(0,0, canvas.width, canvas.height);
    drawDropdown(selected, labels, mainDrop.x, mainDrop.y, mainDrop.width, mainDrop.height);
    visible = false;
  }
});

$('#canvas').click(function(e){
 var labelsHeight = mainDrop.y + mainDrop.height*labels.length;
  var mousePos = getMousePos(canvas, e);
  if(visible)
   onItemClick(mousePos, labels);
});

drawDropdown(selected, labels, mainDrop.x, mainDrop.y, mainDrop.width, mainDrop.height);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas"></canvas>