diff --git a/projects/ng-flowchart/src/lib/model/flow.model.ts b/projects/ng-flowchart/src/lib/model/flow.model.ts index caa61b9e..e7660513 100644 --- a/projects/ng-flowchart/src/lib/model/flow.model.ts +++ b/projects/ng-flowchart/src/lib/model/flow.model.ts @@ -87,11 +87,11 @@ export namespace NgFlowchart { /** Canvas zoom options. Defaults to mouse wheel zoom */ zoom?: { - mode: 'WHEEL' | 'NONE' - rescaleOnResize: boolean + mode: 'WHEEL' | 'MANUAL' | 'DISABLED' + defaultStep: number } = { mode: 'WHEEL', - rescaleOnResize: true + defaultStep: .1 } } @@ -178,6 +178,11 @@ export namespace NgFlowchart { * Called after the canvas completes a re-render */ afterRender?: () => void + + /** + * Called after the canvas has been scaled + */ + afterScale?: (newScale: number) => void }; } diff --git a/projects/ng-flowchart/src/lib/ng-flowchart-canvas.directive.ts b/projects/ng-flowchart/src/lib/ng-flowchart-canvas.directive.ts index ba5d15bd..b564c76a 100644 --- a/projects/ng-flowchart/src/lib/ng-flowchart-canvas.directive.ts +++ b/projects/ng-flowchart/src/lib/ng-flowchart-canvas.directive.ts @@ -54,15 +54,12 @@ export class NgFlowchartCanvasDirective implements OnInit, OnDestroy, AfterViewI if (this._options.centerOnResize) { this.canvas.reRender(true); } - if(this._options.zoom.rescaleOnResize) { - - } } @HostListener('wheel', ['$event']) protected onZoom(event) { if (this._options.zoom.mode === 'WHEEL') { - this.adjustScale(event) + this.adjustWheelScale(event) } } @@ -93,10 +90,8 @@ export class NgFlowchartCanvasDirective implements OnInit, OnDestroy, AfterViewI } private _disabled: boolean = false; - private _scaleVal: number = 1; private _id: string = null private canvasContent: HTMLElement; - private scaleDebounceTimer constructor( protected canvasEle: ElementRef, @@ -118,7 +113,6 @@ export class NgFlowchartCanvasDirective implements OnInit, OnDestroy, AfterViewI } this.canvas._disabled = this._disabled; - } ngAfterViewInit() { @@ -153,34 +147,33 @@ export class NgFlowchartCanvasDirective implements OnInit, OnDestroy, AfterViewI return new NgFlowchart.Flow(this.canvas); } - private adjustScale(event) { + public scaleDown() { + this.canvas.scaleDown() + } + + public scaleUp() { + this.canvas.scaleUp() + } + + public setScale(scaleValue: number) { + const scaleVal = Math.max(0, scaleValue) + this.canvas.setScale(scaleVal) + } + + private adjustWheelScale(event) { + if (this.canvas.flow.hasRoot()) { event.preventDefault(); // scale down / zoom out - - if(event.deltaY > 0) { - this._scaleVal -= this._scaleVal * .1 + if (event.deltaY > 0) { + this.scaleDown() } // scale up / zoom in - else if(event.deltaY < 0) { - this._scaleVal += this._scaleVal * .1 + else if (event.deltaY < 0) { + this.scaleUp() } - const minDimAdjust = `${1/this._scaleVal * 100}%` - - this.canvasContent.style.transform = `scale(${this._scaleVal})`; - this.canvasContent.style.minHeight = minDimAdjust - this.canvasContent.style.minWidth = minDimAdjust - this.canvasContent.style.transformOrigin = 'top left' - this.canvasContent.classList.add('scaling') - - this.canvas.setScale(this._scaleVal) - this.canvas.reRender(true) - - this.scaleDebounceTimer && clearTimeout(this.scaleDebounceTimer) - this.scaleDebounceTimer = setTimeout(() => { - this.canvasContent.classList.remove('scaling') - }, 300) + } }; } \ No newline at end of file diff --git a/projects/ng-flowchart/src/lib/ng-flowchart-canvas.service.ts b/projects/ng-flowchart/src/lib/ng-flowchart-canvas.service.ts index 4ba718b2..77a60acf 100644 --- a/projects/ng-flowchart/src/lib/ng-flowchart-canvas.service.ts +++ b/projects/ng-flowchart/src/lib/ng-flowchart-canvas.service.ts @@ -5,14 +5,14 @@ import { CanvasRendererService } from './services/canvas-renderer.service'; import { DropDataService as DragService } from './services/dropdata.service'; import { OptionsService } from './services/options.service'; import { StepManagerService } from './services/step-manager.service'; -import {first} from 'rxjs/operators' +import { first } from 'rxjs/operators' export class CanvasFlow { rootStep: NgFlowchartStepComponent; // steps from this canvas only private _steps: NgFlowchartStepComponent[] = []; - + hasRoot() { return !!this.rootStep; } @@ -22,7 +22,7 @@ export class CanvasFlow { } removeStep(step: NgFlowchartStepComponent) { - + let index = this._steps.findIndex(ele => ele.id == step.id); if (index >= 0) { this._steps.splice(index, 1); @@ -65,12 +65,8 @@ export class NgFlowchartCanvasService { private renderer: CanvasRendererService, private stepmanager: StepManagerService ) { - - } - public setScale(scale: number) { - this.renderer.setScale(scale) } public init(view: ViewContainerRef) { @@ -120,7 +116,7 @@ export class NgFlowchartCanvasService { } - + public async onDrop(drag: DragEvent) { this.renderer.clearAllSnapIndicators(this.flow.steps); @@ -180,7 +176,7 @@ export class NgFlowchartCanvasService { }) } - public createStep(pending: NgFlowchart.PendingStep): Promise> { + public createStep(pending: NgFlowchart.PendingStep): Promise> { let componentRef: ComponentRef; componentRef = this.stepmanager.create(pending, this); @@ -193,6 +189,37 @@ export class NgFlowchartCanvasService { }) } + public resetScale() { + if(this.options.options.zoom.mode === 'DISABLED') { + return + } + this.renderer.resetScale(this.flow) + } + + public scaleUp(step?: number) { + if(this.options.options.zoom.mode === 'DISABLED') { + return + } + this.renderer.scaleUp(this.flow, step); + + } + + public scaleDown(step?: number) { + if(this.options.options.zoom.mode === 'DISABLED') { + return + } + this.renderer.scaleDown(this.flow, step); + + } + + public setScale(scaleValue: number) { + if(this.options.options.zoom.mode === 'DISABLED') { + return + } + this.renderer.setScale(this.flow, scaleValue) + } + + addChildStep(componentRef: ComponentRef, dropTarget: NgFlowchart.DropTarget) { this.addToCanvas(componentRef); this.addStepToFlow(componentRef.instance, dropTarget); diff --git a/projects/ng-flowchart/src/lib/services/canvas-renderer.service.ts b/projects/ng-flowchart/src/lib/services/canvas-renderer.service.ts index 685d96e7..7cd96a43 100644 --- a/projects/ng-flowchart/src/lib/services/canvas-renderer.service.ts +++ b/projects/ng-flowchart/src/lib/services/canvas-renderer.service.ts @@ -16,6 +16,7 @@ export class CanvasRendererService { private viewContainer: ViewContainerRef; private scale: number = 1; + private scaleDebounceTimer = null constructor( private options: OptionsService @@ -23,10 +24,6 @@ export class CanvasRendererService { } - public setScale(scale: number) { - this.scale = scale; - } - public init(viewContainer: ViewContainerRef) { this.viewContainer = viewContainer; } @@ -346,31 +343,45 @@ export class CanvasRendererService { return canvasContent as HTMLElement; } - // public scaleUp() { - // const minDimAdjust = `${1/this._scaleVal * 100}%` - - // this.canvasContent.style.transform = `scale(${this._scaleVal})`; - // this.canvasContent.style.minHeight = minDimAdjust - // this.canvasContent.style.minWidth = minDimAdjust - // this.canvasContent.style.transformOrigin = 'top left' - // this.canvasContent.classList.add('scaling') - - // this.canvas.setScale(this._scaleVal) - // this.canvas.reRender(true) - - // this.scaleDebounceTimer && clearTimeout(this.scaleDebounceTimer) - // this.scaleDebounceTimer = setTimeout(() => { - // this.canvasContent.classList.remove('scaling') - // }, 300) - // } + public resetScale(flow: CanvasFlow) { + this.setScale(flow, 1) + } + + public scaleUp(flow: CanvasFlow, step? : number) { + const newScale = this.scale + (this.scale * step || this.options.options.zoom.defaultStep) + this.setScale(flow, newScale) + + } - // public scaleDown() { + public scaleDown(flow: CanvasFlow, step? : number) { + const newScale = this.scale - (this.scale * step || this.options.options.zoom.defaultStep) + this.setScale(flow, newScale) + } + + public setScale(flow: CanvasFlow, scaleValue: number) { + const minDimAdjust = `${1/scaleValue * 100}%` + + const canvasContent = this.getCanvasContentElement() + + canvasContent.style.transform = `scale(${scaleValue})`; + canvasContent.style.minHeight = minDimAdjust + canvasContent.style.minWidth = minDimAdjust + canvasContent.style.transformOrigin = 'top left' + canvasContent.classList.add('scaling') - // } + this.scale = scaleValue + this.render(flow, true) - // private scale() { + if(this.options.callbacks?.afterScale) { + this.options.callbacks.afterScale(this.scale) + } - // } + this.scaleDebounceTimer && clearTimeout(this.scaleDebounceTimer) + this.scaleDebounceTimer = setTimeout(() => { + canvasContent.classList.remove('scaling') + }, 300) + + } } \ No newline at end of file diff --git a/projects/workspace/src/styles.scss b/projects/workspace/src/styles.scss index bd9a1d57..757e3016 100644 --- a/projects/workspace/src/styles.scss +++ b/projects/workspace/src/styles.scss @@ -37,6 +37,7 @@ body { min-height: 100px; } +// TODO move this to the library .ngflowchart-canvas-content.scaling .ngflowchart-step-wrapper, .ngflowchart-canvas-content.scaling svg { transition: none !important;