javascript - Fill svg path with canvas? -
i using svg make custom shape using path:
e.g. <path d="m 180,160 0,218 0,0 180,0 z" >
i use snap.svg transform path on hover to:
m 180,34.57627 -180,0 l 0,0 180,0 z
what want achieve fill path canvas animate javascript , make inside shape , transform shape on hover.
is there way that?
you have multiple choices depending on exact needs. here of these choices :
- you use
<foreignobject>
append canvas directly in svg, use clippath on it, limit support ie>=11.
<svg id="svg" width="300" height="300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs> <style> #clickhandler { pointer-events: all; } </style> <clippath id="myclip"> <path id="yourpath" d="m 180,160 0,218 0,0 180,0 z" /> </clippath> </defs> <foreignobject id="fo" width="100%" height="100%" clip-path="url(#myclip)"> <canvas xmlns="http://www.w3.org/1999/xhtml" id="canvas" width="600" height="300"></canvas> </foreignobject> <script> var pathes = ["m 180,160 0,218 0,0 180,0 z", "m 180,34.57627 -180,0 l 0,0 180,0 z"] var current = 0; fo.onclick = function() { current = (current + 1) % 2; yourpath.setattribute('d', pathes[current]); }; // canvas noise var ctx = canvas.getcontext('2d'); var imagedata = ctx.createimagedata(300, 300); function animcanvas() { requestanimationframe(animcanvas); imagedata.data.foreach(function(v, i, a) { a[i] = math.random() * 255; }); ctx.putimagedata(imagedata, 0, 0); } animcanvas(); </script> </svg>
- you place canvas behind svg css , absolute positioning, you'd have append background inside svg, path set mask, , copy of path handle mouse event. here you'd gain html5 browsers support, you'll loose in svg z-index positioning.
var pathes = ["m 180,160 0,218 0,0 180,0 z", "m 180,34.57627 -180,0 l 0,0 180,0 z"] var current = 0; clickhandler.onclick = function() { current = (current + 1) % 2; yourpath.setattribute('d', pathes[current]); }; // canvas noise var ctx = canvas.getcontext('2d'); var imagedata = ctx.createimagedata(300, 300); function animcanvas() { requestanimationframe(animcanvas); imagedata.data.foreach(function(v, i, a) { a[i] = math.random() * 255; }); ctx.putimagedata(imagedata, 0, 0); } animcanvas();
canvas { position: absolute; z-index: 0; } svg { position: absolute; z-index: 1; }
<canvas id="canvas" width="600" height="300"></canvas> <svg id="svg" width="300" height="300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs> <style> #clickhandler { pointer-events: all; } </style> <path id="yourpath" d="m 180,160 0,218 0,0 180,0 z" /> <rect id="bg" x="-1%" y="-1%" width="102%" height="102%" /> <mask id="mymask"> <use xlink:href="#bg" fill="white" /> <use xlink:href="#yourpath" fill="black" /> </mask> </defs> <use xlink:href="#bg" mask="url(#mymask)" fill="white" /> <use xlink:href="#yourpath" fill="none" id="clickhandler" /> </svg>
- or on canvas.
in below example, usepath2d
constructor, wasn't supported in earlier implementations of canvas api, can achieve same different functions calls, or there exist path2d polyfills.
var pathes = [ new path2d("m 180,160 0,218 0,0 180,0 z"), new path2d("m 180,34.57627 -180,0 l 0,0 180,0 z") ]; var current = 0; canvas.onclick = function(evt) { var x = evt.clientx - this.offsetleft, y = evt.clienty - this.offsettop; if (ctx.ispointinpath(pathes[current], x, y)) { current = (current + 1) % 2; } }; function clipcanvas() { ctx.globalcompositeoperation = 'destination-in'; ctx.fill(pathes[current]); ctx.globalcompositeoperation = 'source-over'; // not needed putimagedata } // canvas noise var ctx = canvas.getcontext('2d'); var imagedata = ctx.createimagedata(300, 300); function animcanvas() { requestanimationframe(animcanvas); imagedata.data.foreach(function(v, i, a) { a[i] = math.random() * 255; }); ctx.putimagedata(imagedata, 0, 0); clipcanvas(); } animcanvas();
<canvas id="canvas" width="600" height="300"></canvas>
Comments
Post a Comment