Skip to content

Commit

Permalink
feat(postionLine): make position line draggable in library and citize…
Browse files Browse the repository at this point in the history
…n science
  • Loading branch information
peichins committed Apr 20, 2017
1 parent ef11e79 commit 20a0344
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 99 deletions.
8 changes: 6 additions & 2 deletions src/app/annotationViewer/_positionLine.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
border-left: solid 1px $spectrogramProgressLine;
//background-color: $spectrogramProgressLine;
height: 100%;
width: 100%;
width: calc(100% - 1px);
width: 1px;
position: absolute;

@include vendor-prefix(transform, translate3d(0%, 0, 0));
Expand All @@ -26,6 +25,11 @@
display: none;
}

.grab-bottom-center {
left: 0px;
bottom: 0px;
}

}

}
159 changes: 71 additions & 88 deletions src/app/annotationViewer/positionLine.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,140 +5,123 @@ angular
return {
restrict: "A",
templateUrl: "annotationViewer/positionLine.tpl.html",
replace: true,
replace: false,
scope: {
media: "<media",
audioData: "<audioData",
// TODO: remove this binding
imageClass: "<imageClass"
media: "=media",
audioData: "=audioData"
},
controller: function () {
this.dragOptions = {
axis: "x",
containment: true,
useLeftTop: false,
dragMove: function dragMoveSetPosition(scope, draggie, event, pointer) {
controller: ["$scope", "$element", "lodash", function (scope, element, _) {

var position = scope.model.converters.pixelsToSeconds(draggie.position.x);
var self = this;
self.containerWidth = 0;

scope.model.audioElement.position = position;
self.updateContainerWidth = function () {
var container = element[0].parentElement;
self.containerWidth = (container.clientWidth > 0) ? container.clientWidth : 1;

//updateScope();
}
};
},
link: function (scope, elements, attributes, controller) {

// the dom element for the spectrogram image that is used to get
// the width to calculate the pixel offset for the position line
// TODO: remove the need to reference an image element.
var image;

/**
* Searches for the closest node to the position-line element that
* has the class scope.imageClass
* If there are multiple spectrograms on the page, for example generated in a loop,
* this ensures that each position line is using the correct spectrogram image.
* Searches for the class in the parent dom element, and if not found recurses up one level of dom and repeats.
* @param element; the current element in the recursion that is being searched
* @param depth; int, the current level of recursion, in order to limit the search
* @returns DOM element or NULL
* @TODO: deprecated. We don't want to be searching for DOM elements here. Better to bind to data.
*
*/
this.getImageElement = function (element, depth) {
if (depth > 3 || element.tagName === "BODY") {
return null;
}
var containingElement = element.parentElement;
var images = containingElement.getElementsByClassName(scope.imageClass);
if (images.length > 0) {
return images[0];
} else {
return this.getImageElement(containingElement, depth + 1);
self.getWidth = function () {
if (self.containerWidth < 2) {
self.updateContainerWidth();
}
return self.containerWidth;
};


/**
* converts the proportion of elapsed audio to a pixel value,
* based on the width of the spectrogram image.
* based on the width of the containing element of the position line, which should match the width of the spectrogram image.
* @param audioPositionSeconds number
* @returns number
* @TODO: remove this. Better to use the unit converter, and also better if we don't need to reference the dom element
* @TODO: can we use the unit converter for this?
*/
scope.secondsToPixels = function (audioPositionSeconds) {
var pixelPosition, imageWidth;

if (image.clientWidth > 0) {
imageWidth = image.clientWidth;
} else {
// use number of columns of spectrogram as image width
imageWidth = 1;
}

pixelPosition = imageWidth * (scope.secondsToRatio(audioPositionSeconds));

return pixelPosition;
self.secondsToPixels = function (audioPositionSeconds) {
var width = self.getWidth() * (self.secondsToRatio(audioPositionSeconds));
return Math.min(width, self.getWidth());
};

self.pixelsToSeconds = function (numPixels) {
return (numPixels / self.getWidth()) * self.audioDuration();
};

/**
* Converts a number of seconds of elapsed audio to the fraction of the audio that has elapsed
* by dividing by the duration of the audio.
* @param audioPositionSeconds number
* @returns {number} range [0,1]
*/
scope.secondsToRatio = function (audioPositionSeconds) {
if (scope.media && scope.media.endOffset) {
var positionRatio = audioPositionSeconds / (scope.media.endOffset - scope.media.startOffset);
return (positionRatio > 1) ? 1 : positionRatio;
}
return 0;
self.secondsToRatio = function (audioPositionSeconds) {
var positionRatio = audioPositionSeconds / self.audioDuration();
return Math.min(1, positionRatio);
};

self.ratioToSeconds = function (ratio) {
return self.audioDuration() * ratio;
};

self.audioDuration = function () {
if (scope.media && scope.media.endOffset) {
return scope.media.endOffset - scope.media.startOffset;
} else {
return 0.001;
}
};

/**
* gets the offset as either percent or pixel value.
* uses the ratio position of the audioData to the total duration (based on the media start and end offset)
* @param boolean usePercent
* @returns string if usePercent otherwise float
*/
scope.getOffset = function (usePercent) {

self.getOffset = function () {
if (typeof(this.audioData) === "object") {
if (usePercent) {

var percent = scope.secondsToRatio(this.audioData.position) * 100;
percent = percent > 100 ? 100 : percent;

return percent + "%";
} else {
return(scope.secondsToPixels(this.audioData.position));
}

return(self.secondsToPixels(this.audioData.position));
} else {
return 0;
}

};

if (scope.imageClass !== undefined) {
image = this.getImageElement(elements[0], 0);
} else {
image = null;
}
self.updateScope = _.throttle(function updateScope() {
if (scope.$parent.$parent.$$phase) {
return;
}
scope.$parent.$parent.$digest();
}, 250);

scope.getOffset = self.getOffset;

}],
link: {
pre: function (scope, elements, attributes, controller) {

scope.dragOptions = {
axis: "x",
containment: true,
useLeftTop: false,
dragEnd: function dragEndSetPosition (dragscope, draggie, event, pointer) {
scope.audioData.position = controller.pixelsToSeconds(draggie.position.x);
controller.updateScope();
},
dragMove: function dragMoveSetPosition(dragscope, draggie, event, pointer) {
scope.audioData.position = controller.pixelsToSeconds(draggie.position.x);
controller.updateScope();
}
};
},
post: function (scope, elements, attributes, controller) {

angular.element($window).on("resize", function () {
scope.$apply();
});
angular.element($window).on("resize", function () {
controller.updateContainerWidth();
scope.$apply();
});

}


}



}
};


Expand Down
5 changes: 3 additions & 2 deletions src/app/annotationViewer/positionLine.tpl.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<div class="positionLineContainer">
<div class="positionLine"
baw-translate-x="getOffset(true)"
baw-translate-x="getOffset()"
ng-class="{hidden: !audioData.canPlay}"
draggie drag-options="$scrl.dragOptions">
draggie drag-options="dragOptions">
<div class="grab-bottom-center grab-handle-tail grab-handle-angle-0"
></div>
</div>
</div>


2 changes: 1 addition & 1 deletion src/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function whenDefaults(resourceName, singularResourceName, id, controllerMany, co
return this
// list
.when(pathList, {templateUrl: assetList, controller: controllerMany})
// manage
// managenpm
//.fluidIf(addManageView, function () {
// this.when(listPath, {templateUrl: assetManage, controller: controllerMany})
//})
Expand Down
3 changes: 3 additions & 0 deletions src/app/citizenScience/bristlebird/about.tpl.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<div class="citizen-science ipswich">




<div class="cs-main-container">
<div class="main wrapper clearfix">

Expand Down
13 changes: 7 additions & 6 deletions src/components/directives/drag.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,13 @@ ngDragabilly.directive("draggie",
options: "=dragOptions"
},
link: function (scope, $element, attributes/*, controller, transcludeFunction*/) {

console.log("drag's positionline scope id (startlink)", scope.options.positionLineScopeId);

var element = $element[0];
const transformProperty = typeof element.style.transform === "string" ? "transform" : "WebkitTransform";

scope.options = angular.extend(defaultOptions, scope.options);
scope.options = angular.extend({}, defaultOptions, scope.options);

var draggie = new Draggabilly(element, scope.options);

Expand All @@ -60,26 +63,24 @@ ngDragabilly.directive("draggie",

draggie.on("dragMove", function (event, pointer) {
scope.options.dragMove(scope, draggie, event, pointer);

if (scope.options.raiseAngularEvents) {
scope.$emit("draggabilly:draggie:dragMove", scope, draggie, event, pointer);
}
});

var reposition = function useTransformPositioning(element, position) {
element.style.left = 0;
element.style.left = 0;
element.style.top = 0;
element.style[transformProperty] = "translate3d( " + position.x + "px, " + position.y + "px, 0)";
};

draggie.on("dragEnd", function (event, pointer) {
console.log("drag scope id", scope.$id);
console.log("drag's positionline scope id (end drag)", scope.options.positionLineScopeId);
if (!scope.options.useLeftTop) {
reposition(draggie.element, draggie.position);
}


scope.options.dragEnd(scope, draggie, event, pointer);

if (scope.options.raiseAngularEvents) {
scope.$emit("draggabilly:draggie:dragEnd", scope, draggie, event, pointer);
}
Expand Down

0 comments on commit 20a0344

Please sign in to comment.