繁体   English   中英

Javascript-画布CSS边框半径模仿

[英]Javascript - Canvas CSS border-radius imitation

我正在尝试在画布上模仿CSS border-radius属性的行为。 我已经做了一些有效的事情,但是浏览器正在处理一些缺少的修改,我无法在画布上复制这些修改(请参见下面的图片链接作为示例)

但是,当边界变形时,我会努力调整边界。

这是一个示例,我们以HTML形状为100px(宽度)X 100px(高度),然后应用以下半径: border-radius: 100px 52px 1px 1px;

然后在具有相同参数的画布中绘制此形状。

然后我得到这个(红色形状=画布形状,绿色形状= HTML形状) https://imgur.com/a/XGuca

(抱歉,由于我的声誉,我无法上传图片)

我正在使用此功能绘制形状

function (xx, yy, ww, hh, rad, fill, stroke) {
    if (typeof(rad) === "undefined") rad = 5;
    this.beginPath();
    this.moveTo(xx, yy);
    this.arcTo(xx + ww, yy, xx + ww, yy + hh, rad.tr);
    this.arcTo(xx + ww, yy + hh, xx, yy + hh, rad.br);
    this.arcTo(xx, yy + hh, xx, yy, rad.bl);
    this.arcTo(xx, yy, xx + ww, yy, rad.tl);
    if (stroke) this.stroke();  // Default to no stroke
    if (fill || typeof(fill) === "undefined") this.fill();  // Default to fill
};

这是参数的描述

xx: X axis position yy: Y axis position ww: Width hh: Height rad: {tl:0, tr:0, br:0, bl: 0} (For top-left, top-right, bottom-right, bottom-left RADIUS)

我没有获得使它正常工作的能力,有人可以帮助我还是给我小费以实现目标? 谢谢 !

PS:对不起,我英语不好

(请参见下面的代码段)

  // Ctx var ctx = document.getElementById("rounded-rect").getContext("2d"); //Round rect func ctx.constructor.prototype.fillRoundedRect = function (xx, yy, ww, hh, rad, fill, stroke) { if (typeof(rad) === "undefined") rad = 5; this.beginPath(); this.moveTo(xx, yy); this.arcTo(xx + ww, yy, xx + ww, yy + hh, rad.tr); this.arcTo(xx + ww, yy + hh, xx, yy + hh, rad.br); this.arcTo(xx, yy + hh, xx, yy, rad.bl); this.arcTo(xx, yy, xx + ww, yy, rad.tl); if (stroke) this.stroke(); // Default to no stroke if (fill || typeof(fill) === "undefined") this.fill(); // Default to fill }; ctx.fillStyle = "red"; ctx.strokeStyle = "#ddf"; var copy = document.getElementById('copy'); var tl = document.getElementById('tl'); var tr = document.getElementById('tr'); var bl = document.getElementById('bl'); var br = document.getElementById('br'); var off = document.getElementById('off'); function test() { ctx.clearRect(0, 0, 600, 500); /* 1.Top left */ /* 2. Top right */ /* 3. Bottom right */ /* 4. Bottom left */ var borders = [tl.value, tr.value, br.value, bl.value].join('px ') + 'px'; copy.style.borderRadius = borders; var copyRad = borders.replace(/px/g, '').split(' ').map(function (a) { return parseInt(a) }); var rad = { tl: copyRad[0], tr: copyRad[1], br: copyRad[2], bl: copyRad[3] }; var o = +off.value; ctx.fillRoundedRect(15 + o, 15 + o, 100, 100, rad); } tl.oninput = test; tr.oninput = test; bl.oninput = test; br.oninput = test; off.oninput = test; test(); 
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> html, body { margin: 0; padding: 0; } </style> </head> <body> <div style="display:inline-block; position: absolute; left:120px;top:120px; width: 100px; height: 100px; background:green; border-radius: 10px 5px 10px 20px;" id="copy"> </div> <canvas style="display: inline-block; position: absolute; zindex:0; left:0; top:0;" id="rounded-rect" width="600" height="500"> </canvas> <div style="top: 300px; position:absolute; z-index: 1;"> <label> Top left <input type="range" min="1" max="100" value="0" class="slider" id="tl"></label><br/> <label> Top right <input type="range" min="1" max="100" value="0" class="slider" id="tr"></label><br/> <label> Bottom left <input type="range" min="1" max="100" value="0" class="slider" id="bl"></label><br/> <label> Bottom right <input type="range" min="1" max="100" value="0" class="slider" id="br"></label><br/> <label> Offset <input type="range" min="1" max="200" value="0" class="slider" id="off"></label><br/> </div> </body> </html> 

似乎浏览器如果变形会以某种方式校正半径。 我创建了correctRadius函数,该函数可以执行以下操作。 当然,结果并不完全相同,但至少形状没有任何间隙。

 // Ctx var ctx = document.getElementById("rounded-rect").getContext("2d"); function correctRadius(r, w, h) { if (r.tl + r.tr > w) { r.tl -= (r.tl + r.tr - w) / 2; r.tr = w - r.tl; } if (r.bl + r.br > w) { r.br -= (r.br + r.bl - w) / 2; r.bl = w - r.br; } if (r.tl + r.bl > h) { r.tl -= (r.tl + r.bl - h) / 2; r.bl = h - r.tl; } if (r.tr + r.br > h) { r.tr -= (r.tr + r.br - h) / 2; r.br = h - r.tr; } } //Round rect func ctx.constructor.prototype.fillRoundedRect = function (xx, yy, ww, hh, rad, fill, stroke) { correctRadius(rad, ww, hh); if (typeof(rad) === "undefined") rad = 5; this.beginPath(); this.moveTo(xx, yy); this.arcTo(xx + ww, yy, xx + ww, yy + hh, rad.tr); this.arcTo(xx + ww, yy + hh, xx, yy + hh, rad.br); this.arcTo(xx, yy + hh, xx, yy, rad.bl); this.arcTo(xx, yy, xx + ww, yy, rad.tl); if (stroke) this.stroke(); // Default to no stroke if (fill || typeof(fill) === "undefined") this.fill(); // Default to fill }; ctx.fillStyle = "red"; ctx.strokeStyle = "#ddf"; var copy = document.getElementById('copy'); var tl = document.getElementById('tl'); var tr = document.getElementById('tr'); var bl = document.getElementById('bl'); var br = document.getElementById('br'); var off = document.getElementById('off'); function test() { ctx.clearRect(0, 0, 600, 500); /* 1.Top left */ /* 2. Top right */ /* 3. Bottom right */ /* 4. Bottom left */ var borders = [tl.value, tr.value, br.value, bl.value].join('px ') + 'px'; copy.style.borderRadius = borders; var copyRad = borders.replace(/px/g, '').split(' ').map(function (a) { return parseInt(a) }); var rad = { tl: copyRad[0], tr: copyRad[1], br: copyRad[2], bl: copyRad[3] }; var o = +off.value; ctx.fillRoundedRect(15 + o, 15 + o, 100, 100, rad); } tl.oninput = test; tr.oninput = test; bl.oninput = test; br.oninput = test; off.oninput = test; test(); 
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> html, body { margin: 0; padding: 0; } </style> </head> <body> <div style="display:inline-block; position: absolute; left:120px;top:120px; width: 100px; height: 100px; background:green; border-radius: 10px 5px 10px 20px;" id="copy"> </div> <canvas style="display: inline-block; position: absolute; zindex:0; left:0; top:0;" id="rounded-rect" width="600" height="500"> </canvas> <div style="top: 300px; position:absolute; z-index: 1;"> <label> Top left <input type="range" min="1" max="100" value="0" class="slider" id="tl"></label><br/> <label> Top right <input type="range" min="1" max="100" value="0" class="slider" id="tr"></label><br/> <label> Bottom left <input type="range" min="1" max="100" value="0" class="slider" id="bl"></label><br/> <label> Bottom right <input type="range" min="1" max="100" value="0" class="slider" id="br"></label><br/> <label> Offset <input type="range" min="1" max="200" value="0" class="slider" id="off"></label><br/> </div> </body> </html> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM