Skip to content
Snippets Groups Projects
Commit 641b5f85 authored by fsdavid's avatar fsdavid
Browse files

Screenshot taking functionality

parent 15ecb2f3
No related branches found
No related tags found
No related merge requests found
...@@ -86,7 +86,9 @@ ...@@ -86,7 +86,9 @@
</div> </div>
<div class="d-flex flex-row justify-content-end z-index-10 position-absolute pe-none w-100 h-100"> <div class="d-flex flex-row justify-content-end z-index-10 position-absolute pe-none w-100 h-100">
<signin-banner signinWrapper> <signin-banner
signinWrapper
[parcellationIsSelected]="selectedParcellation? true : false">
</signin-banner> </signin-banner>
</div> </div>
......
...@@ -155,6 +155,8 @@ export class NehubaContainer implements OnInit, OnChanges, OnDestroy{ ...@@ -155,6 +155,8 @@ export class NehubaContainer implements OnInit, OnChanges, OnDestroy{
private ngPanelTouchMove$: Observable<any> private ngPanelTouchMove$: Observable<any>
takingScreenshot = true
constructor( constructor(
private constantService : AtlasViewerConstantsServices, private constantService : AtlasViewerConstantsServices,
private apiService :AtlasViewerAPIServices, private apiService :AtlasViewerAPIServices,
...@@ -766,6 +768,15 @@ export class NehubaContainer implements OnInit, OnChanges, OnDestroy{ ...@@ -766,6 +768,15 @@ export class NehubaContainer implements OnInit, OnChanges, OnDestroy{
} }
}) })
) )
// To get WebGL content when taking screenshot
HTMLCanvasElement.prototype.getContext = function(origFn) {
return function(type, attribs) {
attribs = attribs || {}
attribs.preserveDrawingBuffer = true
return origFn.call(this, type, attribs)
}
}(HTMLCanvasElement.prototype.getContext)
} }
// datasetViewerRegistry : Set<string> = new Set() // datasetViewerRegistry : Set<string> = new Set()
......
...@@ -20,6 +20,7 @@ import { Store, select } from "@ngrx/store"; ...@@ -20,6 +20,7 @@ import { Store, select } from "@ngrx/store";
export class SigninBanner{ export class SigninBanner{
@Input() darktheme: boolean @Input() darktheme: boolean
@Input() parcellationIsSelected: boolean
public user$: Observable<User> public user$: Observable<User>
public userBtnTooltip$: Observable<string> public userBtnTooltip$: Observable<string>
......
...@@ -2,6 +2,19 @@ ...@@ -2,6 +2,19 @@
[iav-key-listener]="keyListenerConfig" [iav-key-listener]="keyListenerConfig"
(iav-key-event)="openTmplWithDialog(helpComponent)"> (iav-key-event)="openTmplWithDialog(helpComponent)">
<!-- Take screenshot -->
<div class="btnWrapper" *ngIf="parcellationIsSelected">
<button mat-icon-button
(click)="takeScreenshotElement.takingScreenshot = true;
takeScreenshotElement.previewingScreenshot = false;
takeScreenshotElement.croppedCanvas = null;
takeScreenshotElement.loadingScreenshot = null;"
matTooltip="Take screenshot"
color="primary">
<i class="fas fa-camera"></i>
</button>
</div>
<!-- pinned datasets --> <!-- pinned datasets -->
<div class="btnWrapper"> <div class="btnWrapper">
...@@ -145,3 +158,4 @@ ...@@ -145,3 +158,4 @@
</mat-list-item> </mat-list-item>
</mat-list> </mat-list>
</ng-template> </ng-template>
<take-screenshot #takeScreenshotElement style="z-index: 1509;" class="position-fixed fixed-top"></take-screenshot>
import {Component, ElementRef, HostListener, Inject, Input, OnInit, Renderer2, ViewChild} from "@angular/core";
import html2canvas from "html2canvas";
import {DOCUMENT} from "@angular/common";
import {ESCAPE} from "@angular/cdk/keycodes";
@Component({
selector: 'take-screenshot',
templateUrl: './takeScreenshot.template.html',
styleUrls: ['./takeScreenshot.style.css']
})
export class TakeScreenshotComponent implements OnInit {
@ViewChild('downloadLink', {read: ElementRef}) downloadLink: ElementRef;
@ViewChild('helpBody', {read: ElementRef}) helpBody: ElementRef
@ViewChild('screenshotPreviewCard', {read: ElementRef}) screenshotPreviewCard: ElementRef
takingScreenshot = false
previewingScreenshot = false
loadingScreenshot = false
croppedCanvas = null
mouseIsDown = false
isDragging = false
tookScreenShot = false // After the mouse is released
// Used to calculate where to start showing the dragging area
startX = 0
startY = 0
endX = 0
endY = 0
borderWidth = ''
// The box that contains the border and all required numbers.
boxTop = 0
boxLeft = 0
boxEndWidth = 0
boxEndHeight = 0
windowHeight = 0
windowWidth = 0
screenshotStartX = 0
screenshotStartY = 0
imageUrl
constructor(private renderer: Renderer2, @Inject(DOCUMENT) private document: any) {
}
ngOnInit(): void {
this.windowWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
this.windowHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
}
@HostListener('window:resize', ['$event'])
onResize(event) {
this.windowWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
this.windowHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
}
@HostListener('window:keyup', ['$event'])
keyEvent(event: KeyboardEvent) {
if (this.takingScreenshot && event.key === 'Escape') {
this.cancelTakingScreenshot()
}
}
move = (e) => {
if (this.mouseIsDown) {
this.isDragging = true
this.endY = e.clientY
this.endX = e.clientX
if (this.endX >= this.startX && this.endY >= this.startY) {
// III quadrant
this.borderWidth = this.startY + 'px '
+ (this.windowWidth - this.endX) + 'px '
+ (this.windowHeight - this.endY) + 'px '
+ this.startX + 'px'
this.boxTop = this.startY
this.boxLeft = this.startX
this.boxEndWidth = this.endX - this.startX
this.boxEndHeight = this.endY - this.startY
this.screenshotStartX = this.startX
this.screenshotStartY = this.startY
} else if (this.endX <= this.startX && this.endY >= this.startY) {
// IV quadrant
this.borderWidth = this.startY + 'px '
+ (this.windowWidth - this.startX) + 'px '
+ (this.windowHeight - this.endY) + 'px '
+ this.endX + 'px'
this.boxLeft = this.endX
this.boxTop = this.startY
this.boxEndWidth = this.startX - this.endX
this.boxEndHeight = this.endY - this.startY
this.screenshotStartX = this.endX
this.screenshotStartY = this.startY
} else if (this.endX >= this.startX && this.endY <= this.startY) {
// II quadrant
this.borderWidth = this.endY + 'px '
+ (this.windowWidth - this.endX) + 'px '
+ (this.windowHeight - this.startY) + 'px '
+ this.startX + 'px'
this.boxLeft = this.startX
this.boxTop = this.endY
this.boxEndWidth = this.endX - this.startX
this.boxEndHeight = this.startY - this.endY
this.screenshotStartX = this.startX
this.screenshotStartY = this.endY
} else if (this.endX <= this.startX && this.endY <= this.startY) {
// I quadrant
this.boxLeft = this.endX
this.boxTop = this.endY
this.boxEndWidth = this.startX - this.endX
this.boxEndHeight = this.startY - this.endY
this.borderWidth = this.endY + 'px '
+ (this.windowWidth - this.startX) + 'px '
+ (this.windowHeight - this.startY) + 'px '
+ this.endX + 'px'
this.screenshotStartX = this.endX
this.screenshotStartY = this.endY
} else {
this.isDragging = false
}
}
}
mouseDown = (e) => {
this.borderWidth = this.windowWidth + 'px ' + this.windowHeight + 'px'
this.startX = e.clientX
this.startY = e.clientY
this.mouseIsDown = true
this.tookScreenShot = false
}
mouseUp = (e) => {
this.borderWidth = '0'
if (this.isDragging) {
// Don't take the screenshot unless the mouse moved somehow.
this.tookScreenShot = true
}
this.isDragging = false
this.mouseIsDown = false
this.loadingScreenshot = true
this.takingScreenshot = false
this.takeScreenshot()
}
takeScreenshot() {
html2canvas(this.document.querySelector('#neuroglancer-container canvas')).then(canvas => {
this.croppedCanvas = null
this.croppedCanvas = this.renderer.createElement('canvas')
this.croppedCanvas.width = this.boxEndWidth * window.devicePixelRatio
this.croppedCanvas.height = this.boxEndHeight * window.devicePixelRatio
this.croppedCanvas.getContext('2d')
.drawImage(canvas,
this.screenshotStartX * window.devicePixelRatio, this.screenshotStartY * window.devicePixelRatio,
this.boxEndWidth * window.devicePixelRatio, this.boxEndHeight * window.devicePixelRatio,
0, 0,
this.boxEndWidth * window.devicePixelRatio, this.boxEndHeight * window.devicePixelRatio)
}).then(() => {
this.screenshotPreviewCard.nativeElement.click()
this.loadingScreenshot = false
this.imageUrl = this.croppedCanvas.toDataURL()
this.previewingScreenshot = true
})
}
saveImage() {
this.downloadLink.nativeElement.href = this.croppedCanvas.toDataURL('image/png')
this.downloadLink.nativeElement.download = 'marble-diagram.png'
this.downloadLink.nativeElement.click()
}
cancelTakingScreenshot() {
this.takingScreenshot = false;
this.previewingScreenshot = false;
this.loadingScreenshot = false;
this.croppedCanvas = null;
}
}
\ No newline at end of file
.overlay,
.tooltip,
.borderedBox {
user-select: none;
}
.overlay {
background-color: rgba(0, 0, 0, 0.5);
}
.overlay.highlighting {
background: none;
border-color: rgba(0, 0, 0, 0.5);
border-style: solid;
}
.screenshotContainer {
clear: both;
background-repeat: no-repeat;
background-size: cover;
}
.smallSizeWindow {
width: 160px;
height: 40px;
}
.cancelTimesPosition {
top: 5px;
right: 5px;
}
.previewScreenshot {
max-width: 400px !important;
max-height: 400px !important;
}
.previewImage {
max-width:350px !important;
max-height:350px !important;
}
.screenshotPreviewCard {
bottom: 50px !important;
right: 150px !important;
z-index: 10520 !important;
}
<div id="screenshot"
class="screenshotContainer overflow-hidden w-100 h-100"
(mousemove)="move($event)"
(mousedown)="mouseDown($event)"
(mouseup)="mouseUp($event)"
*ngIf="takingScreenshot"
[ngStyle]="{'cursor':takingScreenshot? 'crosshair' : 'auto'}">
<div class="overlay position-fixed fixed-top w-100 h-100" [ngClass]="{ 'highlighting' : mouseIsDown }" [ngStyle]="{ borderWidth: borderWidth }"></div>
<div class="position-absolute border border-light" *ngIf="isDragging" [ngStyle]="{ left: boxLeft + 'px', top: boxTop + 'px', width: boxEndWidth + 'px', height: boxEndHeight + 'px' }"></div>
</div>
<mat-card #screenshotPreviewCard
class="position-fixed screenshotPreviewCard"
(click)="$event.stopPropagation()"
*ngIf="previewingScreenshot || takingScreenshot || loadingScreenshot">
<i class="fas fa-times cursorPointer position-absolute cancelTimesPosition"
(click)="cancelTakingScreenshot()">
</i>
<div *ngIf="takingScreenshot || loadingScreenshot" class="smallSizeWindow">
<div class="d-flex flex-column w-100 h-100" *ngIf="takingScreenshot">
<span>Size: {{boxEndWidth}} x {{boxEndHeight}}px</span>
</div>
<div class="d-flex w-100 h-100 justify-content-center align-items-center" *ngIf="loadingScreenshot">
<i class="fas fa-spinner fa-pulse"></i>
</div>
</div>
<div *ngIf="previewingScreenshot" class="d-flex flex-column align-items-center previewScreenshot">
<img [src]="imageUrl" class="previewImage">
<div class="d-flex w-100 justify-content-end mt-2">
<button mat-stroked-button color="primary" class="mr-1 ml-1" (click)="saveImage(); previewingScreenshot = false; takingScreenshot = false; croppedCanvas = null;">
<i class="fas fa-save"></i> Save
</button>
<button mat-stroked-button color="primary" class="mr-1 ml-1" (click)="previewingScreenshot = false; takingScreenshot = true; croppedCanvas = null;">
<i class="fas fa-camera"></i> Try again
</button>
<button mat-stroked-button color="primary" class="mr-1 ml-1" (click)="cancelTakingScreenshot()">
<i class="fas fa-times"></i> Cancel
</button>
</div>
</div>
<div id="download" class="d-none">
<a #downloadLink></a>
</div>
</mat-card>
\ No newline at end of file
...@@ -71,6 +71,7 @@ import { RegionHierarchy } from './viewerStateController/regionHierachy/regionHi ...@@ -71,6 +71,7 @@ import { RegionHierarchy } from './viewerStateController/regionHierachy/regionHi
import { CurrentlySelectedRegions } from './viewerStateController/regionsListView/currentlySelectedRegions/currentlySelectedRegions.component' import { CurrentlySelectedRegions } from './viewerStateController/regionsListView/currentlySelectedRegions/currentlySelectedRegions.component'
import { RegionTextSearchAutocomplete } from "./viewerStateController/regionSearch/regionSearch.component"; import { RegionTextSearchAutocomplete } from "./viewerStateController/regionSearch/regionSearch.component";
import { RegionsListView } from "./viewerStateController/regionsListView/simpleRegionsListView/regionListView.component"; import { RegionsListView } from "./viewerStateController/regionsListView/simpleRegionsListView/regionListView.component";
import {TakeScreenshotComponent} from "src/ui/takeScreenshot/takeScreenshot.component";
@NgModule({ @NgModule({
imports : [ imports : [
...@@ -117,6 +118,7 @@ import { RegionsListView } from "./viewerStateController/regionsListView/simpleR ...@@ -117,6 +118,7 @@ import { RegionsListView } from "./viewerStateController/regionsListView/simpleR
SearchSideNav, SearchSideNav,
RegionTextSearchAutocomplete, RegionTextSearchAutocomplete,
RegionsListView, RegionsListView,
TakeScreenshotComponent,
/* pipes */ /* pipes */
GroupDatasetByRegion, GroupDatasetByRegion,
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment