Skip to content

Commit

Permalink
feature: align cover svg to viewer (#167)
Browse files Browse the repository at this point in the history
* feature: align cover svg to viewer

* fix: removed package lock

* fix: documentation dont add blank lines

* fix: align cover unit tests

* adds cover option on storybook

Co-authored-by: Christian <[email protected]>
  • Loading branch information
wolasss and chrvadala committed Jan 5, 2020
1 parent 871021a commit 69b5b19
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 10 deletions.
3 changes: 2 additions & 1 deletion docs/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ import {
ALIGN_RIGHT,
ALIGN_TOP,
ALIGN_BOTTOM,

ALIGN_COVER,

INITIAL_VALUE
} from 'react-svg-pan-zoom'
```
Expand Down
1 change: 1 addition & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ export const ALIGN_LEFT = 'left';
export const ALIGN_RIGHT = 'right';
export const ALIGN_TOP = 'top';
export const ALIGN_BOTTOM = 'bottom';
export const ALIGN_COVER = 'cover';

export const INITIAL_VALUE = {}
29 changes: 23 additions & 6 deletions src/features/zoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {fromObject, scale, transform, translate} from 'transformation-matrix';

import {
ACTION_ZOOM, MODE_IDLE, MODE_ZOOMING,
ALIGN_CENTER, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_TOP, ALIGN_BOTTOM
ALIGN_CENTER, ALIGN_LEFT, ALIGN_RIGHT, ALIGN_TOP, ALIGN_BOTTOM, ALIGN_COVER
} from '../constants';
import {decompose, getSVGPoint, set} from './common';
import calculateBox from '../utils/calculateBox';
Expand Down Expand Up @@ -101,15 +101,16 @@ export function fitToViewer(value, SVGAlignX=ALIGN_LEFT, SVGAlignY=ALIGN_TOP) {
let scaleY = viewerHeight / SVGHeight;
let scaleLevel = Math.min(scaleX, scaleY);

const scaleMatrix = scale(scaleLevel, scaleLevel);
let scaleMatrix = scale(scaleLevel, scaleLevel);

let translateX = -SVGMinX * scaleX;
let translateY = -SVGMinY * scaleY;

// after fitting, SVG and the viewer will match in width (1) or in height (2)
if (scaleX < scaleY) {
//(1) match in width, meaning scaled SVGHeight <= viewerHeight
// after fitting, SVG and the viewer will match in width (1) or in height (2) or SVG will cover the container with preserving aspect ratio (0)
if (scaleX < scaleY) {
let remainderY = viewerHeight - scaleX * SVGHeight;

//(1) match in width, meaning scaled SVGHeight <= viewerHeight
switch(SVGAlignY) {
case ALIGN_TOP:
translateY = -SVGMinY * scaleLevel;
Expand All @@ -123,12 +124,20 @@ export function fitToViewer(value, SVGAlignX=ALIGN_LEFT, SVGAlignY=ALIGN_TOP) {
translateY = remainderY - SVGMinY * scaleLevel;
break;

case ALIGN_COVER:
scaleMatrix = scale(scaleY, scaleY); // (0) we must now match to short edge, in this case - height
let remainderX = viewerWidth - scaleY * SVGWidth; // calculate remainder in the other scale

translateX = SVGMinX + Math.round(remainderX / 2); // center by the long edge
break;

default:
//no op
}
} else {
//(2) match in height, meaning scaled SVGWidth <= viewerWidth
let remainderX = viewerWidth - scaleY * SVGWidth;

//(2) match in height, meaning scaled SVGWidth <= viewerWidth
switch(SVGAlignX) {
case ALIGN_LEFT:
translateX = -SVGMinX * scaleLevel;
Expand All @@ -142,12 +151,20 @@ export function fitToViewer(value, SVGAlignX=ALIGN_LEFT, SVGAlignY=ALIGN_TOP) {
translateX = remainderX - SVGMinX * scaleLevel;
break;

case ALIGN_COVER:
scaleMatrix = scale(scaleX, scaleX); // (0) we must now match to short edge, in this case - width
let remainderY = viewerHeight - scaleX * SVGHeight; // calculate remainder in the other scale

translateY = SVGMinY + Math.round(remainderY / 2); // center by the long edge
break;

default:
//no op
}
}

const translationMatrix = translate(translateX, translateY);

const matrix = transform(
translationMatrix, //2
scaleMatrix //1
Expand Down
7 changes: 5 additions & 2 deletions storybook/stories/DifferentSizesStory.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
ALIGN_LEFT,
ALIGN_RIGHT,
ALIGN_TOP,
ALIGN_COVER,
UncontrolledReactSVGPanZoom
} from '../../src/index';

Expand Down Expand Up @@ -34,12 +35,14 @@ export default class DifferentSizesStory extends Component {
SVGAlignX: select('toolbarProps.SVGAlignX', {
[ALIGN_LEFT]: ALIGN_LEFT,
[ALIGN_CENTER]: ALIGN_CENTER,
[ALIGN_RIGHT]: ALIGN_RIGHT
[ALIGN_RIGHT]: ALIGN_RIGHT,
[ALIGN_COVER]: ALIGN_COVER,
}, ALIGN_LEFT),
SVGAlignY: select('toolbarProps.SVGAlignY', {
[ALIGN_TOP]: ALIGN_TOP,
[ALIGN_CENTER]: ALIGN_CENTER,
[ALIGN_BOTTOM]: ALIGN_BOTTOM
[ALIGN_BOTTOM]: ALIGN_BOTTOM,
[ALIGN_COVER]: ALIGN_COVER,
}, ALIGN_TOP),
}

Expand Down
31 changes: 30 additions & 1 deletion test/features/zoom.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ALIGN_LEFT,
ALIGN_RIGHT,
ALIGN_TOP,
ALIGN_COVER,
fitSelection,
fitToViewer,
MODE_IDLE,
Expand Down Expand Up @@ -105,7 +106,29 @@ describe("fitSelection", () => {
test.todo('h<w')
})

describe("fitToViewer", () => {
describe("fitToViewer rect > viewer", () => {
test("rect with w>h", () => {
const value = getDefaultValue(
200, 100, //viewer 200x100
0, 0, 400, 400, //svg 400x400
)

const value1 = fitToViewer(value, ALIGN_COVER, ALIGN_COVER)
expect(testSVGBBox(value1)).toEqual([0, -50, 200, 150])
})

test("rect with w<h", () => {
const value = getDefaultValue(
100, 200, //viewer 200x100
0, 0, 400, 400, //svg 400x400
)

const value1 = fitToViewer(value, ALIGN_COVER, ALIGN_COVER)
expect(testSVGBBox(value1)).toEqual([-50, 0, 150, 200])
})
})

describe("fitToViewer rect < viewer", () => {
test("rect with w>h", () => {
const value = getDefaultValue(
200, 100, //viewer 200x100
Expand All @@ -120,6 +143,9 @@ describe("fitToViewer", () => {

const value3 = fitToViewer(value, ALIGN_RIGHT, ALIGN_TOP)
expect(testSVGBBox(value3)).toEqual([100, 0, 200, 100])

const value4 = fitToViewer(value, ALIGN_COVER, ALIGN_COVER)
expect(testSVGBBox(value4)).toEqual([0, -50, 200, 150])
})

test("rect with w<h", () => {
Expand All @@ -136,6 +162,9 @@ describe("fitToViewer", () => {

const value3 = fitToViewer(value, ALIGN_LEFT, ALIGN_BOTTOM)
expect(testSVGBBox(value3)).toEqual([0, 100, 100, 200])

const value4 = fitToViewer(value, ALIGN_COVER, ALIGN_COVER)
expect(testSVGBBox(value4)).toEqual([-50, 0, 150, 200])
})
})

Expand Down

0 comments on commit 69b5b19

Please sign in to comment.