用帆布填充svg路径?

时间:2016-11-10 19:17:31

标签: javascript canvas svg snap.svg

我正在使用SVG使用路径制作自定义形状:

e.g。 <path d="M 180,160 0,218 0,0 180,0 z" >

我还使用snap.svg将该路径转换为:

m 180,34.57627 -180,0 L 0,0 180,0 z

我想要实现的是使用画布填充该路径,我使用javascript制作动画并将其设置在形状内,并在悬停时使用形状进行转换。

有没有办法做到这一点?

1 个答案:

答案 0 :(得分:0)

根据您的具体需求,您有多种选择。以下是其中一些选择:

  • 您可以使用<foreignObject> 将画布直接附加到svg中,然后在其上使用clipPath,但这会限制对IE&gt; = 11的支持。

&#13;
&#13;
 data_stack[, Weighted_average := c((10*0.2 + 60*0.8),(20*0.3 + 70*0.7),(30*0.4 + 80*0.6),(40*0.4 + 80*0.4 + 100*0.2))]
 data_stack
   CompA_value CompB_value CompC_value CompA_weight   CompB_weight CompC_weight   Weighted_average
1:          10          60          NA          0.2          0.8           NA               50
2:          20          70          NA          0.3          0.7           NA               55
3:          30          80          NA          0.4          0.6           NA               60
4:          40          80         100          0.4          0.4          0.2               68
&#13;
&#13;
&#13;

  • 你可以将你的画布放在带有CSS 的svg和绝对定位的背后,你还必须在你的svg中附加一个背景,你的路径设置为掩码,并且副本您处理鼠标事件的路径。在这里,您可以获得所有HTML5浏览器支持,但是您在svg z-index定位中会松散。

&#13;
&#13;
<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>
&#13;
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();
&#13;
canvas {
  position: absolute;
  z-index: 0;
}
svg {
  position: absolute;
  z-index: 1;
}
&#13;
&#13;
&#13;

  • 或者你可以在画布上做所有事情。
    在下面的示例中,我使用<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>构造函数,这在canvas API的早期实现中不受支持,但您也可以使用不同的函数调用实现相同的功能,或者甚至存在一些Path2D polyfill。

&#13;
&#13;
Path2D
&#13;
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 really needed with 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();
&#13;
&#13;
&#13;