使用JavaScript在图像上绘制

3
我有一张图片,其中包含多个对象,我有一个列表,其中包含分割所有对象的多边形的所有点的像素坐标(请查看下面的图片)。
例如,对于人物,我有一个列表l1 = [x0,y0,x1,y1,...,xn,yn],对于猫,我有一个列表l2 = [x0',y0',x1',y1',...,xk',yk'],其他所有对象也类似。
我的问题有两个:
  1. 在图片上绘制内容,使用什么最好的javascript库?给定原始图像,我想获得以下结果。

  2. 每个对象只在鼠标悬停在其上方时可见。为此,我认为应将此绘图函数绑定到鼠标位置。

我考虑以下结构,但不知道如何填充空缺,请给我一些提示吧!
$(.container).hover( function(e) {
    //get coordinates of mouse
    //if mouse is over one object
    //draw on top of image the segmentation for that object
});

container 是包含图片的 div 的类名,因此我应该可以获取鼠标的坐标,因为图片从 container div 的左上角开始。

输入图像描述


这是一道作业题吗? - Alex Weinstein
1
我建议您查看ImageMapster插件;它是基于jQuery的(虽然您没有在问题中提到或标记,但您的示例脚本是jQ),并且支持您所描述的用例。http://www.outsharked.com/imagemapster/ - Stevangelista
SVG和Canvas都可以映射非矩形路径并在悬停在这些路径上时显示文本。由于SVG是一个完整的DOM元素,您可以要求每个非矩形SVG元素在悬停时做出反应。Canvas允许您使用context.isPointInPath命中测试非矩形路径。如果您的设计需求不超出在非矩形路径上悬停时显示文本,则我会选择SVG,因为它可以直接与用户交互。 - markE
@AlexWeinstein - 不... - Matteo
@Stevangelista - 可能有点晚了,但那是一个很好的指针。谢谢!你有关于如何使用这些演示来回答这个问题的建议吗? - Matteo
2个回答

4

只需要从每个数组中重新构建多边形并使用鼠标位置进行命中测试。

首先:如果你有许多定义形状的数组,那么更好的方法是以一种更通用的方式来处理它,而不是为每个数组使用变量,因为这很快就会难以维护。最好的做法是使用一个包含数组和例如id的对象。

使用对象,你可以这样做- 例如:

function Shape(id, points, color) {
    this.id = id;
    this.points = points;
    this.color = color;
}

// this will build the path for this shape and do hit-testing:
Shape.prototype.hitTest = function(ctx, x, y) {
    ctx.beginPath();

    // start point
    ctx.moveTo(this.points[0], this.points[1]);

    // build path
    for(var i = 2, l = this.points.length; i < l; i += 2) {
        ctx.lineTo(this.points[i], this.points[i+1]);
    }

    ctx.closePath();

    return ctx.isPointInPath(x, y);
};

现在,您可以使用各种点数组来创建新实例,就像这样:
var shapes = [];

shapes.push(new Shape("Cat", [x0,y0,x1,y1, ...], "rgba(255,0,0,0.5)");
shapes.push(new Shape("Woman", [x0,y0,x1,y1, ...], "rgba(0,255,0,0.5)"));
...

当您获得鼠标位置时,只需对每个形状进行命中测试:
$(".container").hover( function(e) {
    //get corrected coordinates of mouse to x/y
    // redraw canvas without shapes highlighted

    for(var i = 0, shape; shape = shapes[i]; i++) { // get a shape from array
        if (shape.hitTest(ctx, x, y)) {             // is x/y inside shape?
            ctx.fillStyle = shape.color;            // we already have a path
            ctx.fill();                             // when testing so just fill
            // other tasks here...
            break;
        }
    }

});

谢谢你的回答!只是想澄清一下,ctx 到底是什么?它是一个库还是像这个例子中的变量?另外,我需要使用某种 canvas 元素才能在图像上绘制吗?或者我可以直接在 container 上面进行绘制? - Matteo
@Matteo 是的,ctx 就是那个链接中提到的画布上下文(canvas context)。你需要一个画布元素来绘制(如果你不选择使用 SVG 的话)。这个网站上有很多关于如何设置和使用画布元素本身的例子。如果你不确定的话,我建议你去看看这些例子。 - user1693593

0

检查一下链接,它可能会解决你的问题。

包含必要的JavaScript库文件 jquery.min.js、raphael.min.js、json2.min.js、raphael.sketchpad.js

创建编辑器

<div id="editor"></div>
   <form action="save.php" method="post">
   <input type="hidden" name="data" />
   <input type="submit" value="Save" />
</form>

<script type="text/javascript">
    var sketchpad = Raphael.sketchpad("editor", {
    width: 400,
    height: 400,
    editing: true
});
// When the sketchpad changes, update the input field.
  sketchpad.change(function() {
  $("#data").val(sketchpad.json());
  });
</script>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接