Skip to content

Instantly share code, notes, and snippets.

@nowa
Created November 16, 2011 00:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nowa/1368840 to your computer and use it in GitHub Desktop.
Save nowa/1368840 to your computer and use it in GitHub Desktop.
Draw arrows
function ArrowContainer(container, strokeStyle) {
this.init(container, strokeStyle);
}
$.extend(ArrowContainer.prototype, {
canvas: null,
strokeStyle: null,
arrows: [],
init: function(container, strokeStyle) {
this.strokeStyle = strokeStyle;
this.container = container;
this.container.css({
'position': 'relative',
'background-color': 'transparent'
});
this.canvas = $('<canvas id="' + this.container.attr('id') + '-canvas"></canvas>');
this.setupCanvas();
this.canvas.css({
'position': 'absolute',
'left': 0,
'top': 0,
'z-index': '-10'
});
this.canvas.appendTo(this.container);
var c = this;
$(window).resize(function() {c.redraw()}); // register with window resize event
},
setupCanvas: function() {
var width = this.container.width();
var height = this.container.height();
this.canvas.attr('width', width);
this.canvas.attr('height', height);
this.containerOffset = this.container.offset();
this.context = this.canvas[0].getContext('2d');
this.context.strokeStyle = this.strokeStyle;
},
redraw: function() {
// clear canvas
this.context.clearRect(0, 0, this.canvas.width(), this.canvas.height());
// resize canvas
this.setupCanvas();
for (var i in this.arrows) {
a = this.arrows[i];
this.drawArrow(a[0], a[1], a[2], a[3], a[4], a[5]);
}
},
addArrow: function(from, img, x1, y1, width, height) {
img.css({
'z-index': '-100',
'position': 'relative'
});
this.arrows.push([from, img, x1, y1, width, height]);
this.drawArrow(from, img, x1, y1, width, height);
},
drawArrow: function(from, img, x1, y1, width, height) {
var baseOffset = this.containerOffset;
var fromOffset = from.offset();
var fromX1 = fromOffset.left - baseOffset.left;
var fromY1 = fromOffset.top - baseOffset.top;
var fromX2 = fromX1 + from.width();
var fromY2 = fromY1 + from.height();
var imgOffset = img.offset();
var toX1 = imgOffset.left - baseOffset.left + x1;
var toY1 = imgOffset.top - baseOffset.top + y1;
var toX2 = toX1 + width;
var toY2 = toY1 + height;
var startX, startY, endX, endY, c1X, c1Y, c2X, c2Y, a1X, a1Y, a2X, a2Y;
if (fromX2 < toX1) {
startX = (fromX1 + fromX2) / 2;
if (fromY2 < toY1 || fromY1 > toY2) {
startY = fromY2 < toY1 ? fromY2 : fromY1;
endX = toX1;
endY = (toY1 + toY2) / 2;
c1X = startX;
c1Y = (startY + endY) / 2;
c2X = (startX + endX) / 2;
c2Y = endY;
a1X = endX - 5;
a1Y = endY - 5;
a2X = endX - 5;
a2Y = endY + 5;
} else {
startY = fromY2;
endX = (toX1 + toX2) / 2;
endY = toY2;
c1X = startX;
c1Y = c2Y = (fromY2 > toY2 ? fromY2 : toY2) + 50;
c2X = endX;
a1X = endX - 5;
a1Y = endY + 5;
a2X = endX + 5;
a2Y = endY + 5;
}
} else if (fromX1 > toX2) {
startX = (fromX1 + fromX2) / 2;
if (fromY2 < toY1 || fromY1 > toY2) {
startY = fromY2 < toY1 ? fromY2 : fromY1;
endX = toX2;
endY = (toY1 + toY2) / 2;
c1X = startX;
c1Y = (startY + endY) / 2;
c2X = (startX + endX) / 2;
c2Y = endY;
a1X = endX + 5;
a1Y = endY - 5;
a2X = endX + 5;
a2Y = endY + 5;
} else {
startY = fromY2;
endX = (toX1 + toX2) / 2;
endY = toY2;
c1X = startX;
c1Y = c2Y = (fromY2 > toY2 ? fromY2 : toY2) + 50;
c2X = endX;
a1X = endX - 5;
a1Y = endY + 5;
a2X = endX + 5;
a2Y = endY + 5;
}
} else {
startX = fromX2;
startY = (fromY1 + fromY2) / 2;
endX = toX2;
endY = (toY1 + toY2) / 2;
c1Y = startY;
c1X = c2X = (fromX2 > toX2 ? fromX2 : toX2) + 50;
c2Y = endY;
a1X = endX + 5;
a1Y = endY - 5;
a2X = endX + 5;
a2Y = endY + 5;
}
//this.context.strokeStyle = '#09f';
this.context.moveTo(startX, startY);
// draw curve
this.context.bezierCurveTo(c1X, c1Y, c2X, c2Y, endX, endY);
// draw arrow head
this.context.lineTo(a1X, a1Y);
this.context.moveTo(endX, endY);
this.context.lineTo(a2X, a2Y);
this.context.stroke();
},
});
function drawArrows(json) {
var container = new ArrowContainer($('#post-content'), '#3366CC');
// Get pointers on the page
var pointers = {};
$('#post-content .pointer').each(function(i) {
var ids = this.id.substring(9).split('-')
for (var i in ids) {
var id = parseInt(ids[i]);
if (id in pointers) {
pointers[id].push($(this));
} else {
pointers[id] = [$(this)];
}
}
});
// Get Images in the post
var images = {};
$('#post-content img').each(function(i) {
images[this.src] = $(this);
});
var imageTargets = {}; // For drawing overlay and notes
var areas = $.parseJSON(json);
for (var i in areas) {
var area = areas[i];
if (area.image_url in images) {
// Put this area into mapping
if (area.image_url in imageTargets) {
imageTargets[area.image_url].push(area);
} else {
imageTargets[area.image_url] = [area];
}
if (area.id in pointers) {
for (var j in pointers[area.id]) {
p = pointers[area.id][j];
container.addArrow(p, images[area.image_url],
area.x, area.y, area.width, area.height);
}
}
}
}
// Draw overlays
for (var image_url in imageTargets) {
areas = imageTargets[image_url];
drawNotes(images[image_url], areas);
}
}
function drawNotes(image, areas) {
// Calc image position
var imgPos = image.position();
// Create overlay div
var overlay = $('<div></div>', {'class': 'note-container'}).css({
'left': imgPos.left + 'px',
'top': imgPos.top + 'px',
'width': image.width() + 'px',
'height': image.height() + 'px'
}).appendTo('#post-content');
// create notes
for (var i in areas) {
var area = areas[i];
var tag = area.url ? '<a />' : '<div />';
var targetArea = $(tag).attr('class', 'target-area').css({
'left': area.x - 3 + 'px',
'top': area.y - 3 + 'px',
'width': area.width + 6 + 'px',
'height': area.height + 6 + 'px'
}).html('<span class="box-outer" /><span class="box-main" /><span class="box-inner" />');
// note text
var noteHtml = '<div class="note-content">' + area.title;
if (area.price) {
noteHtml += ' - <span class="note-price">' + area.price + '</span>';
}
noteHtml += '</div>';
$('<span class="area-note"></span>').html(noteHtml).appendTo(targetArea);
// Add url attribute
if (area.url) {
targetArea.attr({
'href': area.url,
'target': '_blank'
});
}
targetArea.appendTo(overlay);
}
}
$(window).load(function () {
drawArrows('[{"title": "\u6469\u6258\u7f57\u62c9 TN30", "url": "/go/7", "price": "\uffe5699", "height": 107, "width": 183, "image_url": "http://pic.yupoo.com/qingbo/BmPnsDHc/medish.jpg", "y": 178, "x": 237, "post_id": 580, "id": 11}, {"title": "\u79cb\u53f6\u539f\u58a8\u7389\u72481.8\u7c73", "url": "/go/10", "price": "\uffe539", "height": 189, "width": 159, "image_url": "http://pic.yupoo.com/qingbo/BmPnsDHc/medish.jpg", "y": 204, "x": 81, "post_id": 580, "id": 12}]');
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment