escher-vis
Version:
Escher: A Web Application for Building, Sharing, and Embedding Data-Rich Visualizations of Biological Pathways
129 lines (119 loc) • 4.09 kB
JavaScript
/** DirectionArrow. A constructor for an arrow that can be rotated and dragged,
and supplies its direction. */
var utils = require('./utils');
var d3_drag = require('d3-drag').drag
var d3_mouse = require('d3-selection').mouse
var d3_selection = require('d3-selection')
var DirectionArrow = utils.make_class();
DirectionArrow.prototype = {
init: init,
set_location: set_location,
set_rotation: set_rotation,
displace_rotation: displace_rotation,
get_rotation: get_rotation,
toggle: toggle,
show: show,
hide: hide,
right: right,
left: left,
up: up,
down: down,
_setup_drag: _setup_drag
};
module.exports = DirectionArrow;
// definitions
function init(sel) {
this.arrow_container = sel.append('g')
.attr('id', 'direction-arrow-container')
.attr('transform', 'translate(0,0)rotate(0)');
this.arrow = this.arrow_container.append('path')
.classed('direction-arrow', true)
.attr('d', path_for_arrow())
.style('visibility', 'hidden')
.attr('transform', 'translate(30,0)scale(2.5)');
this.sel = sel;
this.center = { x: 0, y: 0 };
this._setup_drag();
this.dragging = false;
this.is_visible = false;
this.show();
// definitions
function path_for_arrow() {
return "M0 -5 L0 5 L20 5 L20 10 L30 0 L20 -10 L20 -5 Z";
}
}
function set_location(coords) {
/** Move the arrow to coords.
*/
this.center = coords;
var transform = utils.d3_transform_catch(this.arrow_container.attr('transform'));
this.arrow_container.attr('transform',
'translate('+coords.x+','+coords.y+')rotate('+transform.rotate+')');
}
function set_rotation(rotation) {
/** Rotate the arrow to rotation.
*/
var transform = utils.d3_transform_catch(this.arrow_container.attr('transform'));
this.arrow_container.attr('transform',
'translate('+transform.translate+')rotate('+rotation+')');
}
function displace_rotation(d_rotation) {
/** Displace the arrow rotation by a set amount.
*/
var transform = utils.d3_transform_catch(this.arrow_container.attr('transform'));
this.arrow_container.attr('transform',
'translate('+transform.translate+')'+
'rotate('+(transform.rotate+d_rotation)+')');
}
function get_rotation() {
/** Returns the arrow rotation.
*/
return utils.d3_transform_catch(this.arrow_container.attr('transform')).rotate;
}
function toggle(on_off) {
if (on_off===undefined) this.is_visible = !this.is_visible;
else this.is_visible = on_off;
this.arrow.style('visibility', this.is_visible ? 'visible' : 'hidden');
}
function show() {
this.toggle(true);
}
function hide() {
this.toggle(false);
}
function right() {
this.set_rotation(0);
}
function down() {
this.set_rotation(90);
}
function left() {
this.set_rotation(180);
}
function up() {
this.set_rotation(270);
}
function _setup_drag() {
var b = d3_drag()
.on("start", function(d) {
// silence other listeners
d3_selection.event.sourceEvent.stopPropagation();
this.dragging = true;
}.bind(this))
.on("drag.direction_arrow", function(d) {
var displacement = { x: d3_selection.event.dx,
y: d3_selection.event.dy },
location = { x: d3_mouse(this.sel.node())[0],
y: d3_mouse(this.sel.node())[1] },
d_angle = utils.angle_for_event(displacement,
location,
this.center);
this.displace_rotation(utils.to_degrees(d_angle));
}.bind(this))
.on("end", function(d) {
setTimeout(function() {
this.dragging = false;
}.bind(this), 200);
}.bind(this));
this.arrow_container.call(b);
}