Pointer
Pointer

Reputation: 649

Canvas 3D drawing using both 2D and 3D context

Since the webgl/opengl doesn't support text drawing, so it possible to draw 3D object using 3D context and text drawing using 2D context ?

Upvotes: 24

Views: 23824

Answers (4)

Kent Weigel
Kent Weigel

Reputation: 1178

What I've been doing, whether I just need troubleshooting feedback or 2D text content on a 3D canvas, is just use CSS to put some HTML elements on top of the canvas.

You can make a canvas and a group of text fields share the same space, and ensure that the text fields are on top as follows:

HTML:

<div id="container">
  <canvas id="canvas"></canvas>
  <div id="controlsContainer">
    <label>Mouse Coordinates</label>
      <div>
        <label for="xPos">X</label>
        <span id="xPos"></span>
      </div>
      <div>
        <label for="yPos">Y</label>
        <span id="yPos"></span>
      </div>
  </div>
</div>

CSS:

canvas {
    margin: 0px;
    position: relative;
    top: 0px;
    left: 0px;
    width: 100%;
}

#container {
  position: relative;
}

#controlsContainer {
  position: absolute;
  left: 10px;
  top: 10px;
  z-index: 3;
}

  #controlsContainer div {
    padding-left: 8px;
  }

  #controlsContainer label {
    color: white;
    z-index: 4;
  }

  #controlsContainer span {
    color: white;
    z-index: 4;
  }

The z-index will ensure which elements are in front, and position: relative for the container and position: absolute, in coordination with the top and left for the controls will ensure that they share the same space.

I have been having very good luck with this, and the troubleshooting feedback is invaluable.

enter image description here

An example of the Javascript (ES6 in this case) is:

let xPos = document.getElementById("xPos");
let yPos = document.getElementById("yPos");
let x = event.clientX - containerDiv.offsetLeft -parseInt(window.getComputedStyle(pageBody).getPropertyValue("margin-left"));
let y = event.clientY - containerDiv.offsetTop - parseInt(window.getComputedStyle(pageBody).getPropertyValue("margin-top"));
xPos.innerText = x;
yPos.innerText = y;

which I've placed in a mousemove handler.

Upvotes: 4

dave
dave

Reputation: 2181

No, unfortunately not.

The HTML 5 spec says that if you call getContext on a canvas element that is already in a different context mode and the two contexts are not compatible then return null.

Unfortunately "webgl" and "2d" canvases are not compatible and thus you will get null:

var canvas = document.getElementById('my-canvas');
var webgl = canvas.getContext("webgl"); // Get a 3D webgl context, returns a context
var twod = canvas.getContext("2d"); // Get a 2D context, returns null

Upvotes: 41

Drew Noakes
Drew Noakes

Reputation: 310917

As stated, you cannot do this.

However you can put one canvas on top of another and draw to them separately. I've done this before and it can work out quite well.

Upvotes: 21

Marcelo Cantos
Marcelo Cantos

Reputation: 185862

Create the text as a texture using canvas 2D, then render it in 3D. See here for a tutorial.

Upvotes: 6

Related Questions