【问题标题】:Wrap image around cylinder using canvas drawImage opacity issue使用画布 drawImage 不透明度问题将图像包裹在圆柱体周围
【发布时间】:2020-08-17 02:52:35
【问题描述】:

我需要使用 javascript 将图像包裹在杯子的另一个图像周围,我发现了这个: Wrap an image around a cylindrical object in HTML5 / JavaScript

这有助于加载左侧有杯子手柄的图像。但是,当使用相同的函数(调整位置值)时,图像会应用不透明度。我无休止地搜索以找出发生这种情况的原因,但我一无所获:/

这是用于包装带有右手柄的杯子的图像的函数:

function canvas2() {
 var canvas = document.getElementById('canvas2');
 var ctx = canvas.getContext('2d');

 var productImg = new Image();
 productImg.onload = function() {
   var iw = productImg.width;
   var ih = productImg.height;

   canvas.width = iw;
   canvas.height = ih;

   ctx.drawImage(
     productImg,
     0,
     0,
     productImg.width,
     productImg.height,
     0,
     0,
     iw,
     ih
   );
   loadUpperIMage();
 };

 productImg.src =
   'https://i.ibb.co/B2G8y1m/white-right-ear.jpg';

 function loadUpperIMage() {
   var img = new Image();
   img.src =
     'https://i.ibb.co/BnQP0TL/my-mug-image.png';

   img.onload = function() {
     var iw = img.width;
     var ih = img.height;

     var xOffset = 48, //left padding
         yOffset = 68; //top padding

     var a = 70; //image width
     var b = 8; //round ness

     var scaleFactor = iw / (6 * a);

     // draw vertical slices
     for (var X = 0; X < iw; X += 1) {
       var y = (b / a) * Math.sqrt(a * a - (X - a) * (X - a)); // ellipsis equation

       if (!isNaN(y)) {
         ctx.drawImage(
           img,
           X * scaleFactor,
           0,
           iw / 0.78,
           ih,
           X + xOffset,
           y + yOffset,
           1,
           162
         );
       }
     }
   };
 }

}

希望有人可以帮助解决这个问题!

这里是https://jsfiddle.net/L20aj5xr/的问题@

【问题讨论】:

    标签: javascript html canvas html5-canvas


    【解决方案1】:

    这是因为您传递给 drawImage 的第四个参数 - iw / 0.78。通过将图像宽度乘以小于 1 的值,可以得到大于图像宽度的值。 spec for drawImage 说:

    当源矩形在源图像之外时,必须将源矩形剪裁到源图像和目标矩形必须按相同比例剪裁。

    ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
    

    由于您使用的源宽度 (sw) 大于源图像大小,因此目标矩形“被按相同比例裁剪”。目标矩形宽度为 1 像素,因为您选择了它作为您绘制的每条垂直线的宽度,剪裁后它的宽度变为 1 * 0.78 = 0.78 像素。宽度现在小于 1px,老实说,我不确定它实际上是如何工作的,但我的猜测是浏览器仍然需要绘制 1px,但是因为源是 0.78px,它有点拉伸源到该 1px 并添加一些抗锯齿以平滑过渡,从而增加透明度(即浏览器没有足够的信息用于该 1px,它会尽力填充它)。你可以通过增加sw 来解决这个问题,并观察透明度的增加。

    为了解决您的问题,我使用值 20 而不是 0.78 就像第一个杯子一样,它看起来还不错。

    【讨论】:

    • 感谢您的回答迈克尔。但是iw 表示图像的宽度,例如,如果图像是 1080 像素宽,iw / 0.78 的值等于 1384.62。如果我理解正确,这是决定将绘制多少图像的值。您所指的值应该是 1px 是最后一个 dWidth 之前的参数。虽然当您将值更改为 iw / 20 时看起来不错,但情况并非如此,因为它是正确的,原始图像的右侧部分应该是绘制画布的末端。
    • 是的,如果您的sWidth = 1384.64dWidth = 1,每次调用ctx.drawImage() 时,您将把整个图像绘制到一个像素中。我想这将有助于了解您为什么将此值更改为 0.78 以及您想要实现的目标。
    • 我通过调整值来到0.78,使图像的右侧从杯子的右侧开始。但是,正如您指出的那样,这没有意义。最后,我试图模拟环绕杯子的图像,就像在现实生活中一样。但我真的不知道是什么使图像在右侧透明/扭曲。我整天都在和这个作斗争,似乎无法深究!
    • 如果你想移动图像,你应该调整sxsy 参数——它将是源图像矩形的左上角。例如,您可以使用sx = (X * scaleFactor) + 400。我已经在我的答案中添加了一个解释图像,源矩形和目标矩形是如何相互关联的,也许它会有所帮助。透明度是调整错误参数的副作用。
    • 工作就像一个魅力!非常感谢您的帮助!
    猜你喜欢
    • 2014-12-16
    • 2021-11-04
    • 2011-08-23
    • 2017-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-01
    相关资源
    最近更新 更多