HTML5画布是否必须是矩形?

Oli*_*lle 2 javascript canvas shapes html5-canvas

我对具有任何形状的画布感兴趣的原因是,然后可以用贝塞尔曲线剪切图像并且使网页的文本围绕画布形状流动,即切出图像.

我们需要的是拥有自由形状的div,SVG和HTML5画布的可能性.(应用于SVG,我知道这相当于Flash符号.)然后你可以设想为形状应用一个盒子模型(填充,边框和边距),但它不是一个盒子(它将与形状平行) )!

我想也可能有一个文本包裹在一个形状内,就像在一个形状周围流动的文本一样.

我在这里阅读了一篇有趣的博客文章"使用CSS形状创建非矩形布局":http://sarasoueidan.com/blog/css-shapes/

但它不包括文本包装在形状内.

然后,还有一个用于Brackets的CSS Shapes编辑器(代码编辑器):http: //blogs.adobe.com/webplatform/2014/04/17/css-shapes-editor-in-brackets/

小智 5

虽然听起来很简单但实际上需要完成很多步骤.

大纲看起来像这样:

  • 将形状定义为多边形,即.点阵
  • 查找多边形的边界(多边形适合的区域)
  • 使用cetronid算法或简单使用边界中心的强力方法进行填充的合约多边形
  • 定义文本的行高,并将其用作扫描行数的基础
  • 基本上使用多边形填充算法来查找可以填充文本的形状内的线段.这个步骤是:
    • 通过使用文本扫描线和多边形中的点之间的每条线获得交叉点(使用线交叉数学)来使用奇数/偶数扫描仪
    • 按x对点进行排序
    • 使用奇数和偶数点来创建一个段.该段始终位于多边形内
  • 使用原始多边形添加剪裁
  • 画图
  • 使用线段获得宽度.开始解析文本以填充并测量宽度.
  • 当文本宽度适合段宽度时,则打印适合的字符
  • 重复下一个文本/单词/字符,直到文本或段的结尾

换句话说:您需要实现多边形填充算法,但不是填充行(每像素行),而是使用该行作为文本的基础.

这是完全可行的; 实际上,我继续为这个问题为自己创造一个挑战,为了它的乐趣,所以我创建了一个通用的解决方案,我把它放在GITHub上,在MIT许可下发布.

实现上述原则,并可视化步骤:

定义多边形和填充 - 在这里我选择只使用一个简单的蛮力,并根据中心和填充值计算一个较小的多边形 - 浅灰色是原始多边形,黑色显然是缩小版本:

多边形

这些点被定义为一个数组[x1, y1, x2, y2, ... xn, yn]和用于收缩它的代码(请参阅项目链接到所有这些部分的完整源代码):

var pPoints = [],
    i = 0, x, y, a, d, dx, dy;

for(; i < points.length; i += 2) {
    x = points[i];
    y = points[i+1];
    dx = x - bounds.px;
    dy = y - bounds.py;
    a = Math.atan2(dy, dx);
    d = Math.sqrt(dx*dx + dy*dy) - padding;

    pPoints.push(bounds.px + d * Math.cos(a),
                 bounds.py + d * Math.sin(a));
}
Run Code Online (Sandbox Code Playgroud)

下一步是定义我们要扫描的行.这些行基于字体的行高:

扫描线

这很简单 - 只需确保起点和终点在多边形之外.

我们使用奇数/偶数扫描方法并检查扫描线与多边形中所有线的交点.如果我们得到一个交叉点,我们将其存储在该行的列表中.

检测相交线的代码是:

function getIntersection(line1, line2) {

    // "unroll" the objects
    var p0x = line1.x1,
        p0y = line1.y1,
        p1x = line1.x2,
        p1y = line1.y2,
        p2x = line2.x1,
        p2y = line2.y1,
        p3x = line2.x2,
        p3y = line2.y2,

    // calc difference between the coords
        d1x = p1x - p0x,
        d1y = p1y - p0y,
        d2x = p3x - p2x,
        d2y = p3y - p2y,

    // determinator
        d = d1x * d2y - d2x * d1y,

        px, py,
        s, t;

    // if is not intersecting/is parallel then return immediately
    if (Math.abs(d) < 1e-14)
        return null;

    // solve x and y for intersecting point
    px = p0x - p2x;
    py = p0y - p2y;

    s = (d1x * py - d1y * px) / d;
    if (s >= 0 && s <= 1) {

        // if s was in range, calc t
        t = (d2x * py - d2y * px) / d;
        if (t >= 0 && t <= 1) {

            return {x: p0x + (t * d1x),
                    y: p0y + (t * d1y)}
        }
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

交叉口

然后我们对每一行的点进行排序,并使用成对的点来创建段 - 这实际上是一个多边形填充算法.结果将是:

段

构建段的代码对于这篇文章来说有点广泛,所以请查看上面链接的项目.

最后我们使用这些段来替换实际文本.我们需要从当前文本指针扫描文本,看看在段宽度内适合多少.当前的代码有些基本,并且省略了许多注意事项,例如分词,文本基线位置等等,但是对于初始使用它会这样做.

放在一起的结果将是:

结果

希望这能让我们了解所涉及的步骤.