in src/main.js [4606:4753]
TimelineStoryteller.prototype._loadAnnotations = function (scene, scene_index) {
this.clearCanvas();
this._prevTransitioning = false;
const that = this;
log("Loading Annotations");
if (this._currentSceneIndex !== scene_index) {
return;
}
// is the legend expanded in this scene?
globals.legend_expanded = scene.s_legend_expanded;
if (scene.s_legend_expanded) {
this.expandLegend();
} else {
this.collapseLegend();
}
/**
* Creates a mapper, that adds a type property
* @param {string} type The type of the item
* @returns {object} An object with the type and item properties
*/
function mapWithType(type) {
return function (item) {
return {
id: item.id,
type,
item
};
};
}
this._pruneAnnotations();
var captionAnnos = globals.caption_list.map(mapWithType("caption"));
var imageAnnos = globals.image_list.map(mapWithType("image"));
var textAnnos = globals.annotation_list.map(mapWithType("annotation"));
// TODO: this would be better if the scenes had a more generic property called "annotations", that have a list of all the
// annotations that had a "type" property
// These are are technically annotations, just different types, so concat them all together
const allAnnos = captionAnnos.concat(imageAnnos).concat(textAnnos);
let nextId = getHighestId(allAnnos);
allAnnos
.filter(function (anno) { // Filter out annotations not on this scene
// Basically maps the type to scene.s_images or scene.s_annotations or scene.s_captions
var sceneList = scene["s_" + anno.type + "s"];
for (var i = 0; i < sceneList.length; i++) { // eslint-disable-line no-shadow
// Basically the id property in the scene, so image_id or caption_id or annotation_id
if (sceneList[i][anno.type + "_id"] === anno.item.id) {
return true;
}
}
})
// We sort the annotations by z-order, and add the annotations in that order
// this is important cause with svgs, the order in which elements are added dictates their z-index
.sort(function (a, b) { return (a.item.z_index || 0) - (b.item.z_index || 0); })
// Iterate through all of our annotations
.forEach(function (anno) {
// Make a copy so existing scenes do not get modified
const item = Object.assign({}, anno.item);
item.id = ++nextId;
if (anno.type === "caption") {
addCaption(item.caption_text, item.caption_width * 1.1, item.x_rel_pos, item.y_rel_pos, item);
} else if (anno.type === "image") {
addImage(that._timeline_vis, item.i_url, item.x_rel_pos, item.y_rel_pos, item.i_width, item.i_height, item);
} else {
var itemSel = selectWithParent("#event_g" + item.item_index).select("rect.event_span");
var itemEle = itemSel[0][0].__data__,
item_x_pos = 0,
item_y_pos = 0;
if (scene.s_representation !== "Radial") {
item_x_pos = itemEle.rect_x_pos + itemEle.rect_offset_x + globals.padding.left + globals.unit_width * 0.5;
item_y_pos = itemEle.rect_y_pos + itemEle.rect_offset_y + globals.padding.top + globals.unit_width * 0.5;
} else {
item_x_pos = itemEle.path_x_pos + itemEle.path_offset_x + globals.padding.left;
item_y_pos = itemEle.path_y_pos + itemEle.path_offset_y + globals.padding.top;
}
const { element } = annotateEvent(that._timeline_vis, item.content_text, item_x_pos, item_y_pos, item.x_offset, item.y_offset, item.x_anno_offset, item.y_anno_offset, item.label_width, item.item_index, item);
element
.transition()
.duration(that.options.animations ? 50 : 0)
.style("opacity", 1)
.each(function () {
// If after running the transition, the scene has changed, then hide this annotation.
if (that._currentSceneIndex !== scene_index) {
this.style.opacity = 0;
}
});
}
if (anno.type === "caption") {
globals.caption_list.push(item);
} else if (anno.type === "image") {
globals.image_list.push(item);
} else {
globals.annotation_list.push(item);
}
});
// Set read-only state for annotations in playback mode
d3.selectAll(".annotation_control, .annotation_drag_area, .image_drag_area, .caption_drag_area")
.style("display", globals.playback_mode ? "none" : "");
// toggle selected events in the scene
this._main_svg.selectAll(".timeline_event_g")[0].forEach(function (event) {
if (scene.s_selections.indexOf(event.__data__.event_id) !== -1) {
event.__data__.selected = true;
selectWithParent("#event_g" + event.__data__.event_id)
.selectAll(".event_span")
.attr("filter", "url(#drop-shadow)")
.style("z-index", 1)
.style("stroke", "#f00")
.style("stroke-width", "1.25px");
selectWithParent("#event_g" + event.__data__.event_id)
.selectAll(".event_span_component")
.style("z-index", 1)
.style("stroke", "#f00")
.style("stroke-width", "1px");
} else {
event.__data__.selected = false;
selectWithParent("#event_g" + event.__data__.event_id)
.selectAll(".event_span")
.attr("filter", "none")
.style("stroke", "#fff")
.style("stroke-width", "0.25px");
selectWithParent("#event_g" + event.__data__.event_id)
.selectAll(".event_span_component")
.style("stroke", "#fff")
.style("stroke-width", "0.25px");
}
});
if (this._timeline_vis.tl_representation() !== "Curve") {
selectWithParent("#timecurve").style("visibility", "hidden");
} else {
selectWithParent("#timecurve").style("visibility", "visible");
}
this._main_svg.style("visibility", "visible");
};