Annotation Player as rudimentary Web Component
This commit is contained in:
parent
55475451cf
commit
daf0e0dfd4
2 changed files with 186 additions and 50 deletions
|
@ -168,29 +168,16 @@
|
|||
padding: 10px;
|
||||
}
|
||||
|
||||
#annotations .svganim_player {
|
||||
#annotations .svganim_player,
|
||||
#annotations annotation-player {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 300px;
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
padding: 10px;
|
||||
|
||||
background: white;
|
||||
}
|
||||
|
||||
#annotations .svganim_player svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#annotations .svganim_player.play:not(.loading) .controls {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#annotations .svganim_player:hover .controls {
|
||||
visibility: visible !important;
|
||||
}
|
||||
</style>
|
||||
<script src="assets/nouislider-15.5.0.js"></script>
|
||||
<script src="assets/wNumb-1.2.0.min.js"></script>
|
||||
|
|
|
@ -1,3 +1,161 @@
|
|||
class AnnotationPlayer extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
// We don't use constructor() because an element's attributes
|
||||
// are unavailable until connected to the DOM.
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
// Create a shadow root
|
||||
this.attachShadow({ mode: "open" });
|
||||
|
||||
const imgEl = document.createElement('img');
|
||||
const playerEl = document.createElement('div');
|
||||
|
||||
|
||||
imgEl.src = `/annotation/${this.annotation.id}.svg`;
|
||||
imgEl.addEventListener('click', () => {
|
||||
imgEl.style.display = 'none';
|
||||
new Annotator(
|
||||
playerEl,
|
||||
"tags.json",
|
||||
this.annotation.url,
|
||||
{ is_player: true, crop_to_fit: true, autoplay: true }
|
||||
);
|
||||
})
|
||||
|
||||
playerEl.classList.add('play');
|
||||
|
||||
const styleEl = document.createElement('style');
|
||||
styleEl.textContent = `
|
||||
:host{
|
||||
overflow: hidden;
|
||||
padding: 10px;
|
||||
|
||||
background: white;
|
||||
}
|
||||
|
||||
svg, img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.play:not(.loading) .controls {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
:host(:hover) .controls {
|
||||
visibility: visible !important;
|
||||
}
|
||||
|
||||
.controls--playback {
|
||||
/* display:flex; */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.timecode {
|
||||
position: absolute;
|
||||
right: 100%;
|
||||
width: 5%;
|
||||
font-size: 8px;
|
||||
}
|
||||
|
||||
|
||||
.controls--playback input[type='range'] {
|
||||
/* position: absolute;
|
||||
z-index: 100;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0; */
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
.controls button.paused,
|
||||
.controls button.playing {
|
||||
position: absolute;
|
||||
left: 100%;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.controls button.paused::before {
|
||||
content: '⏵';
|
||||
}
|
||||
|
||||
.controls button.playing::before {
|
||||
content: '⏸';
|
||||
}
|
||||
|
||||
|
||||
.loading .controls button:is(.playing, .paused)::before {
|
||||
content: '↺';
|
||||
display: inline-block;
|
||||
animation: rotate 1s infinite;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
0% {
|
||||
transform: rotate(359deg)
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(0deg)
|
||||
}
|
||||
}
|
||||
|
||||
.controls {
|
||||
position: absolute !important;
|
||||
z-index: 100;
|
||||
bottom: 10px;
|
||||
left: 5%;
|
||||
right: 0;
|
||||
width: 90%;
|
||||
}
|
||||
svg .background {
|
||||
fill: white
|
||||
}
|
||||
|
||||
path {
|
||||
fill: none;
|
||||
stroke: gray;
|
||||
stroke-width: 1mm;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
|
||||
g.before path {
|
||||
opacity: 0.5;
|
||||
stroke: gray !important;
|
||||
}
|
||||
|
||||
g.after path,
|
||||
path.before_in {
|
||||
opacity: .1;
|
||||
stroke: gray !important;
|
||||
}
|
||||
|
||||
.gray {
|
||||
position: absolute;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
|
||||
`;
|
||||
|
||||
this.shadowRoot.appendChild(styleEl);
|
||||
this.shadowRoot.appendChild(imgEl);
|
||||
this.shadowRoot.appendChild(playerEl);
|
||||
|
||||
}
|
||||
|
||||
setAnnotation(annotation) {
|
||||
this.annotation = annotation;
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('annotation-player', AnnotationPlayer);
|
||||
|
||||
|
||||
class AnnotationManager {
|
||||
constructor(rootEl, tagsUrl) {
|
||||
this.rootEl = rootEl;
|
||||
|
@ -141,10 +299,8 @@ class AnnotationManager {
|
|||
const ulEl = document.createElement('ul');
|
||||
this.annotations.forEach((annotation, idx) => {
|
||||
const liEl = document.createElement('li');
|
||||
const imgEl = document.createElement('img');
|
||||
const playerEl = document.createElement('div');
|
||||
const infoEl = document.createElement('span');
|
||||
infoEl.classList.add('annotation-info');
|
||||
const playerEl = new AnnotationPlayer(); //document.createElement('annotation-player');
|
||||
playerEl.setAnnotation(annotation);
|
||||
|
||||
const selectEl = document.createElement('input');
|
||||
selectEl.type = 'checkbox';
|
||||
|
@ -157,25 +313,14 @@ class AnnotationManager {
|
|||
}
|
||||
})
|
||||
|
||||
|
||||
const tag = this.rootTag.find_by_id(annotation.tag);
|
||||
console.log(tag)
|
||||
|
||||
const infoEl = document.createElement('span');
|
||||
infoEl.classList.add('annotation-info');
|
||||
infoEl.innerText = `[${tag.get_name()}] ${annotation.comment}`;
|
||||
|
||||
imgEl.src = `/annotation/${annotation.id}.svg`;
|
||||
imgEl.addEventListener('click', () => {
|
||||
imgEl.style.display = 'none';
|
||||
new Annotator(
|
||||
playerEl,
|
||||
"tags.json",
|
||||
annotation.url,
|
||||
{ is_player: true, crop_to_fit: true, autoplay: true }
|
||||
);
|
||||
})
|
||||
|
||||
playerEl.classList.add('play');
|
||||
|
||||
liEl.appendChild(imgEl);
|
||||
liEl.appendChild(playerEl);
|
||||
liEl.appendChild(selectEl);
|
||||
liEl.appendChild(infoEl);
|
||||
|
@ -209,6 +354,10 @@ class AnnotationManager {
|
|||
this.buildAnnotationActions()
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the form items to select & move the annotations
|
||||
* @returns undefined
|
||||
*/
|
||||
buildAnnotationActions() {
|
||||
if (!this.actionsEl || !this.annotations.length) return
|
||||
this.actionsEl.innerHTML = "";
|
||||
|
|
Loading…
Reference in a new issue