Created
November 16, 2011 00:11
-
-
Save nowa/1368840 to your computer and use it in GitHub Desktop.
Draw arrows
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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