mirror of
https://github.com/igorski/bitmappery.git
synced 2026-06-16 19:25:38 +02:00
Added 'Fit to window' option to zoom tool
This commit is contained in:
@@ -109,9 +109,9 @@ export default {
|
||||
"activeTool",
|
||||
"activeToolOptions",
|
||||
"antiAlias",
|
||||
"canvasDimensions",
|
||||
"snapAlign",
|
||||
"zoomOptions",
|
||||
"zCanvasBaseDimensions",
|
||||
]),
|
||||
documentTitle() {
|
||||
const { name } = this.activeDocument;
|
||||
@@ -151,6 +151,7 @@ export default {
|
||||
renderState.reset();
|
||||
layerPool.clear();
|
||||
this.calcIdealDimensions();
|
||||
this.setToolOptionValue({ tool: ToolTypes.ZOOM, option: "level", value: 1 }); // reset zoom
|
||||
this.$nextTick( async () => {
|
||||
// previously active tool needs to update to new document ref
|
||||
const tool = this.activeTool;
|
||||
@@ -262,10 +263,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
...mapMutations([
|
||||
"setZCanvasBaseDimensions",
|
||||
"setCanvasDimensions",
|
||||
"setActiveTool",
|
||||
"setPanMode",
|
||||
"setSelectMode",
|
||||
"setToolOptionValue",
|
||||
]),
|
||||
...mapActions([
|
||||
"requestDocumentClose",
|
||||
@@ -309,20 +311,30 @@ export default {
|
||||
if ( calculateBestFit ) {
|
||||
const { width, height } = this.activeDocument;
|
||||
const scaledSize = scaleToRatio( width, height, containerSize.width, containerSize.height );
|
||||
this.setZCanvasBaseDimensions( scaledSize );
|
||||
xScale = scaledSize.width / this.activeDocument.width;
|
||||
yScale = scaledSize.height / this.activeDocument.height;
|
||||
const maxScaling = calculateMaxScaling( scaledSize.width, scaledSize.height, width, containerSize.width );
|
||||
|
||||
maxInScale = maxScaling.in;
|
||||
maxOutScale = maxScaling.out;
|
||||
|
||||
this.setCanvasDimensions({
|
||||
...scaledSize,
|
||||
visibleWidth : containerSize.width,
|
||||
visibleHeight : containerSize.height,
|
||||
maxInScale,
|
||||
maxOutScale
|
||||
});
|
||||
|
||||
xScale = scaledSize.width / this.activeDocument.width;
|
||||
yScale = scaledSize.height / this.activeDocument.height;
|
||||
|
||||
this.viewportWidth = containerSize.width;
|
||||
this.viewportHeight = containerSize.height;
|
||||
zCanvas.setViewport( this.viewportWidth, this.viewportHeight );
|
||||
}
|
||||
this.scaleWrapper();
|
||||
// replace below with updated zCanvas lib to not multiply by zoom
|
||||
this.cvsWidth = this.zCanvasBaseDimensions.width * zoom;
|
||||
this.cvsHeight = this.zCanvasBaseDimensions.height * zoom;
|
||||
this.cvsWidth = this.canvasDimensions.width * zoom;
|
||||
this.cvsHeight = this.canvasDimensions.height * zoom;
|
||||
zCanvas.setDocumentScale( this.cvsWidth, this.cvsHeight, xScale, zoom, this.activeDocument );
|
||||
this.centerCanvas = zCanvas.getWidth() < containerSize.width || zCanvas.getHeight() < containerSize.height ;
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Igor Zinken 2020-2021 - https://www.igorski.nl
|
||||
* Igor Zinken 2020-2022 - https://www.igorski.nl
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
@@ -22,15 +22,17 @@
|
||||
*/
|
||||
<template>
|
||||
<div class="form">
|
||||
<label v-t="'importLocalFile'"
|
||||
for="file"
|
||||
class="file-label button button--block"
|
||||
<label
|
||||
v-t="'importLocalFile'"
|
||||
for="file"
|
||||
class="file-label button button--block"
|
||||
></label>
|
||||
<input type="file"
|
||||
id="file"
|
||||
multiple
|
||||
:accept="acceptedImageTypes"
|
||||
@change="handleFileSelect"
|
||||
<input
|
||||
type="file"
|
||||
id="file"
|
||||
multiple
|
||||
:accept="acceptedFileTypes"
|
||||
@change="handleFileSelect"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"en-US": {
|
||||
"zoomLevel": "Zoom level",
|
||||
"bestFit": "Best fit",
|
||||
"fitWindow": "Fit window",
|
||||
"original": "Original"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Igor Zinken 2020-2021 - https://www.igorski.nl
|
||||
* Igor Zinken 2020-2022 - https://www.igorski.nl
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
@@ -38,6 +38,12 @@
|
||||
class="button button--small"
|
||||
@click="setBestFit()"
|
||||
></button>
|
||||
<button
|
||||
v-t="'fitWindow'"
|
||||
type="button"
|
||||
class="button button--small"
|
||||
@click="setFitWindow()"
|
||||
></button>
|
||||
<button
|
||||
v-t="'original'"
|
||||
type="button"
|
||||
@@ -51,8 +57,9 @@
|
||||
<script>
|
||||
import { mapGetters, mapMutations } from "vuex";
|
||||
import ToolTypes, { MIN_ZOOM, MAX_ZOOM } from "@/definitions/tool-types";
|
||||
import Slider from "@/components/ui/slider/slider";
|
||||
import messages from "./messages.json";
|
||||
import { scaleValue, isPortrait, isLandscape } from "@/math/image-math";
|
||||
import Slider from "@/components/ui/slider/slider";
|
||||
import messages from "./messages.json";
|
||||
|
||||
export default {
|
||||
i18n: { messages },
|
||||
@@ -67,7 +74,7 @@ export default {
|
||||
...mapGetters([
|
||||
"activeDocument",
|
||||
"zoomOptions",
|
||||
"zCanvasBaseDimensions",
|
||||
"canvasDimensions",
|
||||
]),
|
||||
zoomLevel: {
|
||||
get() {
|
||||
@@ -89,8 +96,38 @@ export default {
|
||||
setBestFit() {
|
||||
this.zoomLevel = 0;
|
||||
},
|
||||
setFitWindow() {
|
||||
const { width, height } = this.activeDocument;
|
||||
const { visibleWidth, visibleHeight, maxOutScale } = this.canvasDimensions;
|
||||
|
||||
const isWidthDominantSide = isLandscape( width, height );
|
||||
|
||||
if ( isWidthDominantSide ) {
|
||||
// width is dominant, meaning zoom level 0 has image occupying full visibleHeight
|
||||
const minZoomHeight = visibleHeight / maxOutScale;
|
||||
const minZoomWidth = minZoomHeight * ( width / height );
|
||||
const heightAtZeroZoom = visibleHeight;
|
||||
const widthAtZeroZoom = ( width / height ) * heightAtZeroZoom;
|
||||
const pixelsPerZoomUnit = ( widthAtZeroZoom - minZoomWidth ) / MIN_ZOOM;
|
||||
|
||||
this.setZoomLevel(( widthAtZeroZoom - visibleWidth ) / pixelsPerZoomUnit );
|
||||
}
|
||||
else {
|
||||
// height is dominant, meaning zoom level 0 has image occupying full visibleWidth
|
||||
const minZoomWidth = visibleWidth / maxOutScale;
|
||||
const minZoomHeight = minZoomWidth * ( height / width );
|
||||
const widthAtZeroZoom = visibleWidth;
|
||||
const heightAtZeroZoom = ( height / width ) * widthAtZeroZoom;
|
||||
const pixelsPerZoomUnit = ( widthAtZeroZoom - minZoomWidth ) / MIN_ZOOM;
|
||||
|
||||
this.setZoomLevel(( heightAtZeroZoom - visibleHeight ) / pixelsPerZoomUnit );
|
||||
}
|
||||
},
|
||||
setOriginalSize() {
|
||||
this.zoomLevel = ( this.activeDocument.width / this.zCanvasBaseDimensions.width ) * window.devicePixelRatio;
|
||||
this.zoomLevel = ( this.activeDocument.width / this.canvasDimensions.width ) * window.devicePixelRatio;
|
||||
},
|
||||
setZoomLevel( level ) {
|
||||
this.zoomLevel = Math.max( MIN_ZOOM, Math.min( MAX_ZOOM, level ));
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Igor Zinken 2020 - https://www.igorski.nl
|
||||
* Igor Zinken 2020-2022 - https://www.igorski.nl
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
@@ -24,20 +24,28 @@ import Vue from "vue";
|
||||
|
||||
export default {
|
||||
state: {
|
||||
// the base dimensions describe the "best fit" scale to represent
|
||||
// the currently active document at the current window size, this
|
||||
// is basically the base line used for the unzoomed document view
|
||||
zCanvasBaseDimensions: {
|
||||
width: 0,
|
||||
height: 0,
|
||||
canvasDimensions: {
|
||||
// the base dimensions describe the "best fit" scale to represent
|
||||
// the currently active document at the current window size, this
|
||||
// is basically the baseline used for the unzoomed document view
|
||||
width : 0,
|
||||
height : 0,
|
||||
// the visible area of the canvas (as it is positioned inside a container
|
||||
// that offers scrollable overflow)
|
||||
visibleWidth : 0,
|
||||
visibleHeight : 0,
|
||||
// the maximum in- and out zoom level supported for the currently
|
||||
// open document at the current available screen dimensions
|
||||
maxInScale : 1,
|
||||
maxOutScale : 1,
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
zCanvasBaseDimensions: state => state.zCanvasBaseDimensions,
|
||||
canvasDimensions: state => state.canvasDimensions,
|
||||
},
|
||||
mutations: {
|
||||
setZCanvasBaseDimensions( state, { width, height }) {
|
||||
Vue.set( state, "zCanvasBaseDimensions", { width, height });
|
||||
setCanvasDimensions( state, { width, height, visibleWidth, visibleHeight, maxInScale, maxOutScale }) {
|
||||
Vue.set( state, "canvasDimensions", { width, height, visibleWidth, visibleHeight, maxInScale, maxOutScale });
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -4,17 +4,29 @@ const { getters, mutations } = storeModule;
|
||||
|
||||
describe( "Vuex canvas module", () => {
|
||||
describe( "getters", () => {
|
||||
it( "should be able to retrieve the zCanvas instance base dimensions", () => {
|
||||
const state = { zCanvasBaseDimensions: { width: 10, height: 5 } };
|
||||
expect( getters.zCanvasBaseDimensions( state )).toEqual( state.zCanvasBaseDimensions );
|
||||
it( "should be able to retrieve the zCanvas instance dimensions", () => {
|
||||
const state = {
|
||||
canvasDimensions: {
|
||||
width: 10, height: 5, visibleWidth: 7, visibleHeight: 3, maxInScale: 1, maxOutScale: 1
|
||||
}
|
||||
};
|
||||
expect( getters.canvasDimensions( state )).toEqual( state.canvasDimensions );
|
||||
});
|
||||
});
|
||||
|
||||
describe( "mutations", () => {
|
||||
it( "should be able to set the zCanvas instance base dimensions", () => {
|
||||
const state = { zCanvasBaseDimensions: { width: 10, height: 5 } };
|
||||
mutations.setZCanvasBaseDimensions( state, { width: 50, height: 40 } );
|
||||
expect( state.zCanvasBaseDimensions ).toEqual({ width: 50, height: 40 });
|
||||
it( "should be able to set the zCanvas instance dimensions", () => {
|
||||
const state = {
|
||||
canvasDimensions: {
|
||||
width: 10, height: 5, visibleWidth: 7, visibleHeight: 3, maxInScale: 1, maxOutScale: 1
|
||||
}
|
||||
};
|
||||
mutations.setCanvasDimensions( state, {
|
||||
width: 50, height: 40, visibleWidth: 40, visibleHeight: 20, maxInScale: 5, maxOutScale: 10
|
||||
});
|
||||
expect( state.canvasDimensions ).toEqual({
|
||||
width: 50, height: 40, visibleWidth: 40, visibleHeight: 20, maxInScale: 5, maxOutScale: 10
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user