1

I have a set of unlabeled images which I need to present labeled and unlabeled. I have the label text and positions. I do not want to have two images (labeled and unlabeled); rather, I want to put the text over the image, either in relatively-positioned divs or as SVG text elements using Raphaël, those being two approaches I'm technically comfortable with. The nature of the project dictates that the image and the labels be delivered to the browser as distinct resources.

Ideally the labels would include indicator lines as in this image (N.B. I'm aware that the labels are part of the image file in the example - I want my end result to look like this.)

I'm wondering if there is any reason to prefer one approach over the other (either divs or SVG elements)? An existing javascript library for positioning labels would be a strong recommendation for either approach; otherwise I suppose drawing the indicator lines would be easier in SVG using Raphaël. jQuery and Raphaël are already available in the project.

pjmorse
  • 9,204
  • 9
  • 54
  • 124
  • Why not using PHP's gd library? Probably the best option IMHO – jeremy Jan 01 '13 at 02:24
  • Because the larger project is not in PHP. I'll clarify the question: the images and the labeling data will be delivered to the browser as separate resources. – pjmorse Jan 01 '13 at 12:04

1 Answers1

2

I see two main reasons to use absolutely positioned divs over SVG text items within a Raphael drawing:

  • You have multiline text and don't want to wrap it manually (like tooltips)
  • You really need the full CSS styling available to HTML text

In your case, I'd make a small Raphael function to place the labels and draw a line to the appropriate spot on the image. This example puts the labels on the margins of the image at the y value of the spot it indicates, but you could easily adjust to put the label over the image and at a different altitude (that is, diagonal lines).

//x and y relative to image
Raphael.el.label = function (label, dx, dy) {
    //absolute x and y
    var x = dx + this.attr("x"),
        y = dy + this.attr("y"),
        label,
        line;
    //decide whether to put label on left or right
    if (dx < this.attr("width") / 2) {
        label = paper.text(this.attr("x") - 10, y, label).attr("text-anchor" , "end");
        line = paper.path("M" + (this.attr("x") - 5) + "," + y + "l" + (dx + 5) + ",0").attr("stroke", 2);
    } else {
        label = paper.text(this.attr("x") + this.attr("width") + 10, y, label).attr("text-anchor" , "start");
        line = paper.path("M" + (this.attr("x") + this.attr("width") + 5) + "," + y + "L" + (x) + "," + y).attr("stroke", 2);   
    }            
};

jsFiddle

Chris Wilson
  • 6,599
  • 8
  • 35
  • 71
  • I like this. Solid explanation of why to go this way, good placement algorithm (smart, but not so smart as to be incomprehensible) and code! Thanks. – pjmorse Jan 02 '13 at 02:32