Chris
Chris

Reputation: 1131

Create links in HTML canvas

Is it possible to create html links out of text that is rendered in a canvas element?

Upvotes: 36

Views: 65458

Answers (6)

dogbane
dogbane

Reputation: 274612

There is no easy way. You will have to draw the link text onto the canvas and then check for mouseclicks. Here is a demo html page:

var canvas = document.getElementById("myCanvas");
var ctx;
var linkText = "https://stackoverflow.com";
var linkX = 5;
var linkY = 15;
var linkHeight = 10;
var linkWidth;
var inLink = false;

// draw the balls on the canvas
function draw() {
  canvas = document.getElementById("myCanvas");
  // check if supported
  if (canvas.getContext) {

    ctx = canvas.getContext("2d");

    //clear canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    //draw the link
    ctx.font = '10px sans-serif';
    ctx.fillStyle = "#0000ff";
    ctx.fillText(linkText, linkX, linkY);
    linkWidth = ctx.measureText(linkText).width;

    //add mouse listeners
    canvas.addEventListener("mousemove", on_mousemove, false);
    canvas.addEventListener("click", on_click, false);

  }
}

//check if the mouse is over the link and change cursor style
function on_mousemove(ev) {
  var x, y;

  // Get the mouse position relative to the canvas element.
  if (ev.layerX || ev.layerX == 0) { //for firefox
    x = ev.layerX;
    y = ev.layerY;
  }
  x -= canvas.offsetLeft;
  y -= canvas.offsetTop;

  //is the mouse over the link?
  if (x >= linkX && x <= (linkX + linkWidth) && y <= linkY && y >= (linkY - linkHeight)) {
    document.body.style.cursor = "pointer";
    inLink = true;
  } else {
    document.body.style.cursor = "";
    inLink = false;
  }
}

//if the link has been clicked, go to link
function on_click(e) {
  if (inLink) {
    window.location = linkText;
  }
}
<html>

<body onload="draw()">
  <center>
    <canvas id="myCanvas" width="200" height="200" style="border-style:solid;border-width:1px">Canvas not supported.</canvas>
  </center>
</body>

</html>

Upvotes: 34

Yakovenko Max
Yakovenko Max

Reputation: 337

This example shows how you can add multiple links to your HTML canvas:

function OnLoad() {
  // Get canvas
  var canvas = document.getElementById("myCanvas");

  // 2d context 
  var ctx = canvas.getContext("2d");
  ctx.translate(0.5, 0.5); // * Move the canvas by 0.5px to fix blurring

  // Block border
  ctx.strokeStyle = "#5F7FA2";
  ctx.strokeRect(50, 50, 185, 90);

  // Photo
  var img = new Image();
  img.src = "http://www.cs.washington.edu/education/courses/csep576/05wi/projects/project4/web/artifact/liebling/average_face.gif";
  img.onload = function() {
    ctx.drawImage(img, 59.5, 59.5); // Use -0.5px on photos to prevent blurring caused by * fix
  }

  // Text
  ctx.fillStyle = "#000000";
  ctx.font = "15px Tahoma";
  ctx.textBaseline = "top";
  ctx.fillText("Username", 95, 65);

  // ***** Magic starts here *****

  // Links
  var Links = new Array(); // Links information
  var hoverLink = ""; // Href of the link which cursor points at
  ctx.fillStyle = "#0000ff"; // Default blue link color
  ctx.font = "15px Courier New"; // Monospace font for links
  ctx.textBaseline = "top"; // Makes left top point a start point for rendering text

  // Draw the link
  function drawLink(x, y, href, title) {
    var linkTitle = title,
      linkX = x,
      linkY = y,
      linkWidth = ctx.measureText(linkTitle).width,
      linkHeight = parseInt(ctx.font); // Get lineheight out of fontsize

    // Draw the link
    ctx.fillText(linkTitle, linkX, linkY);

    // Underline the link (you can delete this block)
    ctx.beginPath();
    ctx.moveTo(linkX, linkY + linkHeight);
    ctx.lineTo(linkX + linkWidth, linkY + linkHeight);
    ctx.lineWidth = 1;
    ctx.strokeStyle = "#0000ff";
    ctx.stroke();

    // Add mouse listeners
    canvas.addEventListener("mousemove", on_mousemove, false);
    canvas.addEventListener("click", on_click, false);

    // Add link params to array
    Links.push(x + ";" + y + ";" + linkWidth + ";" + linkHeight + ";" + href);
  }

  // Link hover
  function on_mousemove(ev) {
    var x, y;

    // Get the mouse position relative to the canvas element
    if (ev.layerX || ev.layerX == 0) { // For Firefox
      x = ev.layerX;
      y = ev.layerY;
    }

    // Link hover
    for (var i = Links.length - 1; i >= 0; i--) {
      var params = new Array();

      // Get link params back from array
      params = Links[i].split(";");

      var linkX = parseInt(params[0]),
        linkY = parseInt(params[1]),
        linkWidth = parseInt(params[2]),
        linkHeight = parseInt(params[3]),
        linkHref = params[4];

      // Check if cursor is in the link area
      if (x >= linkX && x <= (linkX + linkWidth) && y >= linkY && y <= (linkY + linkHeight)) {
        document.body.style.cursor = "pointer";
        hoverLink = linkHref;
        break;
      } else {
        document.body.style.cursor = "";
        hoverLink = "";
      }
    };
  }

  // Link click
  function on_click(e) {
    if (hoverLink) {
      window.open(hoverLink); // Use this to open in new tab
      //window.location = hoverLink; // Use this to open in current window
    }
  }

  // Ready for use ! You are welcome !
  drawLink(95, 93, "http://www.facebook.com/", "Me at facebook");
  drawLink(95, 110, "http://plus.google.com/", "Me at G+");
}
<!DOCTYPE html>

<!-- This page shows how to add multiple links to <canvas> (by Yakovenko Max) -->

<html>

<head>
  <title>Canvas Links Example</title>
</head>

<body onload="OnLoad();">
  <canvas id="myCanvas" width="450" height="250" style="border:1px solid #eee;">  
Canvas is not supported in your browser ! :(  
</canvas>
</body>

</html>

Upvotes: 17

John Hood
John Hood

Reputation: 29

"I think another easy idea is to put a div at the position where you want the link to appear on the canvas and put your link at the div. All you will have to do is to position and style the div correctly." -Shamaila Tahir

I personally like the idea of using links on top of the canvas and here is a full page sized canvas example. You could use this example for many things, and not just the canvas, so why not get comfortable with it.

window.addEventListener('load', canvas, false);

function canvas() {
  var link = "contact";
  var canvas = document.getElementById("canvas");
  var context = canvas.getContext('2d');
  canvas.width = document.body.clientWidth;
  canvas.height = document.body.clientHeight;
  contact = document.getElementById("contact");
  onOff = document.getElementById("onOff");
  document.getElementById("onOff").style.visibility = "visible";
  switchLinks(link);

  function switchLinks(isLink) {
    if (isLink != "contact") {
      document.getElementById("contact").style.visibility = "hidden";
    }
    if (isLink == "contact") {
      document.getElementById("contact").style.visibility = "visible";
    }
  }
  onOff.addEventListener("mousedown", contactFunction, false);

  function contactFunction() {
    if (link == "contact") {
      link = "";
    } else {
      link = "contact";
    }
    switchLinks(link);
  }
}
html {
  height: 100%;
  width: 100%;
  overflow: hidden;
}

body {
  position: absolute;
  height: 100%;
  width: 100%;
  overflow: hidden;
}

#contactBackground {
  position: absolute;
  height: 100%;
  width: 100%;
  border: 2px solid green;
}

#contactBackground:hover {
  border: 2px solid red;
}

#contact {
  position: absolute;
  height: 15%;
  top: 52%;
  left: 70%;
  width: 10%;
  background-size: 20%, 20%;
}

#onOff {
  position: absolute;
  height: 15%;
  top: 52%;
  left: 20%;
  width: 10%;
  background-size: 20%, 20%;
}

#onOff:hover {
  border: 2px solid red;
}
<!DOCTYPE html>

<HEAD>
  <TITLE>Kewl!! Buttons and Links with Canvas</TITLE>
</HEAD>
<script type="text/javascript">
</script>

<body>
  <canvas id="canvas" width="0" height="0">Your browser does not support the HTML 5 Canvas.
</canvas>
  <span id="contact" style="display:hidden"> 
<a  href="mailto:Dude your Awesome!"><img id="contactBackground" src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/High-contrast-emblem-mail.svg/72px-High-contrast-emblem-mail.svg.png" alt="Send a message" title="Email" /></a>
</span>
  <img id="onOff" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Hamburger_icon.svg/138px-Hamburger_icon.svg.png" style="display:hidden" />
</body>

</HTML>

Upvotes: 2

Ted OBrien
Ted OBrien

Reputation: 1

A simpler solution can be implemented by using a mousedown event listener. First create two arrays for the x and y coordinates of your links on the canvas. Then test if a click was within a range of a link on a mouseup. It it was, use a window.open('http://myurl.com') method to open the link.

var links = ['Google','Yahoo','Bing','Baidu','DuckDuckGo'];
var coordx = [425,332,251,306,458];
var coordy = [267,402,335,304,438];

myCanvas.mousedown(function(e){
    lastEvent = e;
    mouseDown = true;
}).mouseup(function(){
if((lastEvent.offsetX) > (coordx[0] - 5) && 
(lastEvent.offsetX) <= (coordx[0] + 5) && 
(lastEvent.offsetY) > (coordy[0] - 5) && 
(lastEvent.offsetY) < (coordy[0] + 5)){

// use a console.log('x = "+lastEvent.offsetX) first to find the coordinates and ranges for the links.
// link to 1st url in myArray
window.open('http://myFirstURL.com');
}    `
    });

You will need tests for each set of coordinates, or you can specify a variable for a current active link.

This is my first stackoverflow post. Thanks to all you guys who have helped me over the years.

Upvotes: 0

Shamaila Tahir
Shamaila Tahir

Reputation: 998

I think another easy idea is to put a div at the position where you want the link to appear on the canvas and put your link at the div. All you will have to do is to position and style the div correctly.

Upvotes: 2

Simon Sarris
Simon Sarris

Reputation: 63812

There is nothing built in to do it, but you can emulate the function of links if you wanted to. You can remember where the text is, color it differently, give it a different cursor when the user mouses-over that area, and redirect the user to another page when he or she clicks on it.

Upvotes: 2

Related Questions