簡體   English   中英

canvas js用圖像填充圓弧

[英]canvas js fill an arc with image

我正在嘗試用圖像填充圓(弧)。

這是我的代碼:

draw() {
ctx.save();
let boulePat = new Image();
switch(this.couleur) {
  case "red":
    boulePat.src = "images/red.png";
    break;
  case "green":
    boulePat.src = "images/green.png";
    break;
  case "orange":
    boulePat.src = "images/orange.png";
    break;
  case "yellow":
    boulePat.src = "images/yellow.png";
    break; 
  case "purple":
    boulePat.src = "images/purple.png";
    break;
 }
  var pattern = ctx.createPattern(boulePat, "repeat");
  ctx.beginPath();
  ctx.arc(this.x, this.y, 15, 0, 2 * Math.PI);
  ctx.fillStyle = pattern;
  ctx.fill();
  ctx.restore();
}

有了這個,我有空的或黑色的圓圈......

請問你能幫幫我嗎 ? 非常感謝。

您必須等待圖像加載,然后才能在createPattern使用它,如下所示:

看到這個堆棧答案

請記住,圖像將從相對於畫布的0,0坐標開始。 如有必要ctx.transform(xOffset, yOffset)您需要將其計入任何偏移量(使用ctx.transform(xOffset, yOffset) )。

 var canvas = document.getElementById("myCanvasNoTranslate"); var canvas2 = document.getElementById("myCanvasWithTranslate"); function drawCanvas(_canvas) { var context = _canvas.getContext("2d"); draw(context); } function draw(ctx) { ctx.save(); ctx.strokeSyle = "rgb(0, 0, 0)"; ctx.lineWidth = 3; ctx.strokeRect(0, 0, 400, 200); let boulePat = new Image(); boulePat.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e9/16777216colors.png/100px-16777216colors.png"; boulePat.onload = function () { var pattern = ctx.createPattern(boulePat, "repeat"); ctx.fillStyle = pattern; ctx.beginPath(); ctx.arc(100, 100, 50, 0, 2 * Math.PI); // translate canvas to offset where the image coordinates are for .fill() if (ctx.canvas === canvas2) { ctx.translate(50, 50); } ctx.fill(); // restore ctx back to before the translate() ctx.restore(); } } drawCanvas(canvas); drawCanvas(canvas2);
 With ctx.translate() for background fill<br/> <canvas id="myCanvasWithTranslate" height="200px" width="400px"></canvas> <br/><br/> Without ctx.translate() for background fill<br/> <canvas id="myCanvasNoTranslate" height="200px" width="400px"></canvas>

下面的代碼采用圖像 URL、弧的半徑和弧的角度/大小,並返回一個畫布,該畫布將該圖像剪輯到給定的弧,並“包含”在弧內,以便圖像填充arc 而不改變圖像的縱橫比:

  async function getArcClippedCanvas(imageUrl, radius, arcSizeDeg) {   
    let arcSizeRad = (arcSizeDeg/360)*2*Math.PI;
    
    // derive required width and height of canvas from radius and arc size
    let width;
    if(arcSizeDeg >= 180) {
      width = radius*2;
    } else {
      width = radius*Math.sin(arcSizeRad/2)*2;
    }
    
    let height;
    if(arcSizeDeg <= 180) {
      height = radius;
    } else {
      height = radius + radius*Math.sin( (arcSizeRad-Math.PI)/2 );
    }
    
    let arcCenterX = width/2;
    let arcCenterY = radius; // remember, y axis starts from top of canvas
     
    let canvas = document.createElement("canvas");
    let ctx = canvas.getContext("2d");
    
    canvas.width = width;
    canvas.height = height;
    
    let img = new Image();
    await new Promise(resolve => {
      img.onload = resolve;
      img.src = imageUrl;
    });
    
    let centerAngle = -Math.PI/2;
    
    ctx.beginPath();
    ctx.moveTo(arcCenterX, arcCenterY); 
    ctx.arc(arcCenterX, arcCenterY, radius, centerAngle - (arcSizeDeg/2)*2*Math.PI/360, centerAngle + (arcSizeDeg/2)*2*Math.PI/360);
    ctx.clip();
    
    // we want to "cover" the canvas with the image without changing the image's aspect ratio
    drawImageToCanvasContained(ctx, img, 0, 0, canvas.width, canvas.height);
    
    return canvas;
  }


  function drawImageToCanvasContained(ctx, img, x, y, w, h, offsetX, offsetY) {
    // By Ken Fyrstenberg Nilsen: https://stackoverflow.com/a/21961894/11950764
    if(arguments.length === 2) {
      x = y = 0;
      w = ctx.canvas.width;
      h = ctx.canvas.height;
    }

    // default offset is center
    offsetX = typeof offsetX === "number" ? offsetX : 0.5;
    offsetY = typeof offsetY === "number" ? offsetY : 0.5;

    // keep bounds [0.0, 1.0]
    if(offsetX < 0) offsetX = 0;
    if(offsetY < 0) offsetY = 0;
    if(offsetX > 1) offsetX = 1;
    if(offsetY > 1) offsetY = 1;

    let iw = img.width;
    let ih = img.height;
    let r = Math.min(w / iw, h / ih);
    let nw = iw * r;   // new prop. width
    let nh = ih * r;   // new prop. height
    let cx, cy, cw, ch, ar = 1;

    // decide which gap to fill    
    if(nw < w) ar = w / nw;                             
    if(Math.abs(ar - 1) < 1e-14 && nh < h) ar = h / nh;  // updated
    nw *= ar;
    nh *= ar;

    // calc source rectangle
    cw = iw / (nw / w);
    ch = ih / (nh / h);

    cx = (iw - cw) * offsetX;
    cy = (ih - ch) * offsetY;

    // make sure source rectangle is valid
    if(cx < 0) cx = 0;
    if(cy < 0) cy = 0;
    if(cw > iw) cw = iw;
    if(ch > ih) ch = ih;

    // fill image in dest. rectangle
    ctx.drawImage(img, cx, cy, cw, ch,  x, y, w, h);
  }
  

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM