6188

Displaying DIV inside a Canvas clipping path

Question:

I have a DIV container that I want to place inside a Canvas element, how do I set the clipping path of the #canvasContents to the Canvas shape?

<canvas id="myCanvas" width="500" height="400"></canvas> <div id="canvasContents" width="500" height="400">canvas contents</div> <script> var canvas = document.getElementById('myCanvas'); var context = canvas.getContext('2d'); var x = 120, y = 70; context.beginPath(); context.moveTo(x, y); context.bezierCurveTo(x, y, x + 6, y - 82, x + 98, y - 25); context.bezierCurveTo(x + 210, y - 5, x + 325, y + 2, x + 283, y + 78); context.bezierCurveTo(x + 244, y + 173, x + 237, y + 270, x + 138, y + 235); context.bezierCurveTo(x - 29, y + 185, x - 145, y + 154, x - 65, y + 99); context.closePath(); context.lineWidth = 1; context.fillStyle = '#FFF'; context.fill(); context.strokeStyle = '#000'; context.stroke(); </script>

Answer1:

You can't place anything inside a canvas element. The content inside a canvas element will only show if canvas is not supported in a browser. In other cases it's ignored.

You can try to use SVG to place a div inside by wrapping the code inlined for the SVG but there are some restrictions related to external content.

You need to build an inline SVG like this:

var inlineSVG = '<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">' + '<foreignObject width="100%" height="100%">' + ourHTMLgoesHere + '</foreignObject></svg>';

Then convert it to blob and url:

var svg = new Blob([inlineSVG], {type:"image/svg+xml;charset=utf-8"}); var url = URL.createObjectURL(svg);

Now you can set this as an image source, load it and then draw it to canvas.

For simplicity I made this function to do all the hard work (please see link above for details). Text can be any HTML including the div you need to wrap inside. Just remember it cannot contain links to external content (images, css, fonts etc.):

/** * Canvas extension: drawHTMLText(txt, options) * By Ken Fyrstenberg, Epistemex * http://epistemex.com/ * * USAGE: * myContext.drawHTMLText(txt [, options]); * * var options = {x: startPosition, * y: startPosition, * width: maxWidth, * height: maxHeight, * callback: myFunction, * callbackError: myErrorFunction} * * Each individual option is optional in themself. The callback * on success contains an object with reference to result and * originalText. Error callback is provided with the error object. * * License: MIT */ CanvasRenderingContext2D.prototype.drawHTMLText = function(txt, options) { /// make sure we have an object if none was provided options = options || {}; var ctx = this, /// build inline SVG iSVG = '<svg xmlns="http://www.w3.org/2000/svg" width="' + (options.width ? options.width : ctx.canvas.width) + '" height="' + (options.height ? options.height : ctx.canvas.height) + '"><foreignObject width="100%" height="100%">' + '<div xmlns="http://www.w3.org/1999/xhtml" style="font:' + ctx.font + ';color:' + ctx.fillStyle + '">' + txt + "</div></foreignObject></svg>", /// create Blob of inlined SVG svg = new Blob([iSVG],{type:"image/svg+xml;charset=utf-8"}), /// create URL (handle prefixed version) domURL = self.URL || self.webkitURL || self, url = domURL.createObjectURL(svg), /// create Image img = new Image; /// handle image loading img.onload = function () { /// draw SVG to canvas ctx.drawImage(img, (options.x ? options.x : 0), (options.y ? options.y : 0)); domURL.revokeObjectURL(url); /// invoke callback if provided if (typeof options.callback === 'function') options.callback({result: img, originalText: txt}); }; /// handle potential errors img.onerror = function(e) { if (typeof options.callbackError === 'function') { options.callbackError(e); } else { console.log(e); } } img.src = url; }

If you need clipping just add that to the canvas itself using context.clip() after defining a path.

Answer2:

<strong><a href="http://jsfiddle.net/loktar/6znHS/1/" rel="nofollow">Live Demo</a></strong>

Here is one way to accomplish it, first I put the canvas element over the div just using absolute positioning like so

canvas { position:absolute } #canvasContents { position:absolute; background:blue; width:500px; height:400px; line-height:400px; text-align:center }

Then I fill the canvas and use clipping to show the effect.

var canvas = document.getElementById('myCanvas'); var context = canvas.getContext('2d'); var x = 120, y = 70; context.fillRect(0, 0, canvas.width, canvas.height); context.save(); context.beginPath(); context.moveTo(x, y); context.bezierCurveTo(x, y, x + 6, y - 82, x + 98, y - 25); context.bezierCurveTo(x + 210, y - 5, x + 325, y + 2, x + 283, y + 78); context.bezierCurveTo(x + 244, y + 173, x + 237, y + 270, x + 138, y + 235); context.bezierCurveTo(x - 29, y + 185, x - 145, y + 154, x - 65, y + 99); context.closePath(); context.clip(); context.clearRect(0, 0, canvas.width, canvas.height); ctx.restore();

The key with clipping is to save the context, draw your path, and then call clip. After that you can do a fill, or in this example a clearRect which will show whatever is positioned behind the canvas element.

Recommend

  • Set text width or put text in a div
  • Html content on canvas
  • Display BLOB data PHP?
  • JDBC 4's java.sql.Clob.free() method and backwards compatibility
  • AngularJS is breaking the routing url
  • Ensure Ruby version in Nix Dev Environment when using latest version
  • How to get a list of all blobs in a repository in Git
  • How to get or calculate size of Azure File/Share or Service
  • Selecting a subset of data in ServiceStack.OrmLite
  • Using Nested Table variables / Collections in SQL inside PL/SQL blocks
  • Feature detection of foreignObject in SVG
  • XSD with multi occurrences unordered
  • Convert SQLite database to XML
  • WPF Visiblity Binding to Boolean Expression with multiple Variables
  • Conversion from string “a” to type 'Boolean' is not valid
  • How can I enlarge video fullscreen without the affected interface project in as3?
  • Jetty 9 HashLoginService
  • Display images in Django
  • How to render a blob on a canvas element?
  • Python urlparse: small issue
  • Read a local file using javascript
  • ImageMagick, replace semi-transparent white with opaque white
  • Seeking advice on Jetty HttpClient Hang
  • FileReader+canvas image loading problem
  • Cannot connect to cassandra from Spark
  • Why is an OPTIONS request sent to the server?
  • Spring security and special characters
  • Cross-Platform Protobuf Serialization
  • Can a Chrome extension content script make an jQuery AJAX request for an html file that is itself a
  • Alternatives to the OPTIONAL fallback SPARQL pattern?
  • Circular dependency while pushing http interceptor
  • Arrays break string types in Julia
  • AngularJs get employee from factory
  • How can I get HTML syntax highlighting in my editor for CakePHP?
  • How to set the response of a form post action to a iframe source?
  • How do I configure my settings file to work with unit tests?
  • Change div Background jquery
  • IndexOutOfRangeException on multidimensional array despite using GetLength check
  • python draw pie shapes with colour filled
  • Binding checkboxes to object values in AngularJs