javascript 将圆角应用于路径/多边形
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19269622/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Applying rounded corners to paths/polygons
提问by MaPaBa
I'm gathering some info for a project that has to start within a few weeks. This project contains a browser-based drawing tool where users can add predefined shapes or forming shapes themselves. Shapes must be selectable, freely scalable and rotatable with a Illustrator-like transformtool (handles). Predefined shapes that we have in mind are: rectangles, ellipses, half ellipses and (isosceles) triangles.
我正在为一个必须在几周内开始的项目收集一些信息。该项目包含一个基于浏览器的绘图工具,用户可以在其中添加预定义的形状或自己形成形状。形状必须是可选的、可自由缩放和可旋转的,使用类似 Illustrator 的变换工具(手柄)。我们想到的预定义形状是:矩形、椭圆、半椭圆和(等腰)三角形。
So far so good, to achieve this I was thinking of RaphaelJS or FabricJS but... Every shape (polygon/path) must be drawn with a certain cornerradius. And the cornerradius must be maintained while scaling, so no distortion occurs. The user can specify the rounding by input.
到目前为止一切顺利,为了实现这一点,我想到了 RaphaelJS 或 FabricJS,但是......每个形状(多边形/路径)都必须用某个角半径绘制。并且在缩放时必须保持角半径,因此不会发生失真。用户可以通过输入指定舍入。
There's a few obstacles/questions:
有一些障碍/问题:
- Is there some uniform mathemetical formula to apply a cornerradius to the shapes I mentioned? Or must every shape be treated as a mini-project itself? I want to return it as a path or poly, so it can be drawn with SVG or canvas.
- Every scale or rotate operation, by dragging the transformhandles, will result in (massive) calculations to retrieve an updated shape I think. Rectangles are the easiest to achieve and except ellipses, all the other shapes will be a lot harder to compute. Is there some way to speed up the process?
- 是否有一些统一的数学公式可以将角半径应用于我提到的形状?或者每个形状都必须被视为一个小项目本身?我想将它作为路径或多边形返回,因此可以使用 SVG 或画布绘制。
- 通过拖动变换手柄,每次缩放或旋转操作都会导致(大量)计算以检索我认为的更新形状。矩形是最容易实现的,除了椭圆之外,所有其他形状都很难计算。有什么方法可以加快这个过程吗?
I found a site where users can draw flowcharts and apply a cornerradius on almost all shapes the are offered. It works so smoothly, I can't nail how they did it. Link: https://www.lucidchart.com/(try button)
我找到了一个网站,用户可以在其中绘制流程图并在几乎所有提供的形状上应用角半径。它运行得如此顺利,我无法确定他们是如何做到的。链接:https: //www.lucidchart.com/(尝试按钮)
For now, I'm a bit clueless, I guess to mediocre in mathematics. Perhaps someone can push me in the right direction and share some experiences?
就目前而言,我有点无知,我想我的数学很一般。也许有人可以将我推向正确的方向并分享一些经验?
Thanks in advance.
提前致谢。
BTW. Performance is key in this project. The ouput of the drawing must be SVG format.
顺便提一句。性能是这个项目的关键。绘图的输出必须是 SVG 格式。
回答by Yona Appletree
I ended up having a similar problem, and wasn't able to find a simple solution. I ended up writing a fairly generic corner-rounding function based on Adobe Illustrator's operation. It uses Bezier curves instead of arcs, but I think the result is pretty decent.
我最终遇到了类似的问题,并且无法找到简单的解决方案。我最终根据 Adobe Illustrator 的操作编写了一个相当通用的圆角函数。它使用贝塞尔曲线代替圆弧,但我认为结果相当不错。
It supports rounding with a radius given in the coordinate space of the SVG image or as a fraction of the distance between a corner and its neighbors.
它支持使用 SVG 图像坐标空间中给定的半径或角与其相邻角之间距离的一部分进行舍入。
To use this, include rounding.js in your project and call the function:
要使用它,请在您的项目中包含 rounding.js 并调用该函数:
roundPathCorners(pathString, radius, useFractionalRadius)
The code and some test paths are here: http://embed.plnkr.co/kGnGGyoOCKil02k04snu/preview
代码和一些测试路径在这里:http: //embed.plnkr.co/kGnGGyoOCKil02k04snu/preview
This is how the examples from the Plnkr render:
这是来自 Plnkr 的示例的呈现方式:
回答by Timo K?hk?nen
The starting point could be using-svg-curves-to-imitate-rounded-corners. The principle is to convert every corner with shorthand relative cubic (s). This example is very basic and works only with two possible corner cases.
起点可能是using-svg-curves-to-imitiate-rounded-corners。原理是用简写的相对立方(s)转换每个角。此示例非常基础,仅适用于两种可能的极端情况。
I think expanding this like corner replace with shorthand relative cubic is possible to expand to cover also other path segments. Every segment has a on-curve coordinate point, which have to be replaced with s
segment. The math can be interesting part of this solution.
我认为像用速记相对立方体代替角替换这样的扩展可以扩展以覆盖其他路径段。每个线段都有一个曲线上坐标点,必须用s
线段替换。数学可能是这个解决方案的有趣部分。
回答by Sebastian Schmitt
Despite this question being around for some time, some may stop by and try this solution:
尽管这个问题已经存在了一段时间,但有些人可能会停下来尝试这个解决方案:
var BORDER_RADIUS = 20;
function roundedPath( /* x1, y1, x2, y2, ..., xN, yN */ ){
context.beginPath();
if (!arguments.length) return;
//compute the middle of the first line as start-stop-point:
var deltaY = (arguments[3] - arguments[1]);
var deltaX = (arguments[2] - arguments[0]);
var xPerY = deltaY / deltaX;
var startX = arguments[0] + deltaX / 2;
var startY = arguments[1] + xPerY * deltaX / 2;
//walk around using arcTo:
context.moveTo(startX, startY);
var x1, y1, x2, y2;
x2 = arguments[2];
y2 = arguments[3];
for (var i = 4; i < arguments.length; i += 2) {
x1 = x2;
y1 = y2;
x2 = arguments[i];
y2 = arguments[i + 1];
context.arcTo(x1, y1, x2, y2, BORDER_RADIUS);
}
//finally, close the path:
context.arcTo(x2, y2, arguments[0], arguments[1], BORDER_RADIUS);
context.arcTo(arguments[0], arguments[1], startX, startY, BORDER_RADIUS);
context.closePath();
}
The trick is to start (and stop) at the middle of the first line, and then use the arcTo
function which is described very nicely here.
诀窍是在第一行的中间开始(和停止),然后使用这里arcTo
描述得非常好的函数。
Now you "just" have to find a way to express all of your shapes as polygons.
现在您“只需要”找到一种方法将所有形状表示为多边形。