Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions demo/bordered.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="Description" content="Pan and zoom DOM elements demo " />
<meta name="keywords" content="dom, pan, zoom" />
<meta name="author" content="Andrei Kashcha" />
<meta name="title" content="DOM panzoom demo" />
<title>Bordered panzoom demo</title>
<style type="text/css" media="screen">
.container {
border: 1px solid rgb(51, 50, 50);
width: 600px;
height: 600px;
overflow: hidden;
}

.container img {
width: 100%;
}
</style>
</head>
<body>
<div class="container">
<img
src="https://cdnpp.org/wp-content/uploads/2021/06/sample-image-Square.jpg"
alt="sample-image"
class="zoomable"
/>
</div>
<!-- <script src="../dist/panzoom.js"></script> -->
<script src="../dist/panzoom.js"></script>
<script>
var area = document.querySelector(".zoomable")
panzoom(area, {
smoothScroll: false,
minZoom: 1,
bordered: true,
filterKey: () => true,
})
</script>
<a
href="https://github.com/anvaka/panzoom"
style="position: absolute; top: 8px; right: 8px; border: 0"
>GitHub</a
>
</body>
</html>
82 changes: 64 additions & 18 deletions dist/panzoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ function createPanZoom(domElement, options) {
var maxZoom = typeof options.maxZoom === 'number' ? options.maxZoom : Number.POSITIVE_INFINITY;
var minZoom = typeof options.minZoom === 'number' ? options.minZoom : 0;

if (options.bordered && (!minZoom || minZoom < 1)) {
throw new Error('Cannot create bordered panzoom with minZoom less than 1');
}

var boundsPadding = typeof options.boundsPadding === 'number' ? options.boundsPadding : 0.05;
var zoomDoubleClickSpeed = typeof options.zoomDoubleClickSpeed === 'number' ? options.zoomDoubleClickSpeed : defaultDoubleTapZoomSpeed;
var beforeWheel = options.beforeWheel || noop;
Expand Down Expand Up @@ -178,6 +182,48 @@ function createPanZoom(domElement, options) {
return paused;
}

function resolveTransformScale(scale) {
if (minZoom) {
scale = Math.max(scale, minZoom)
}

return scale;
}

function setTransformScale(scale) {
transform.scale = resolveTransformScale(scale);
}

function setTransformX(x, scale = null) {
scale = scale || transform.scale;
scale = resolveTransformScale(scale);

if (options.bordered) {
if (x > 0) {
x = 0;
} else {
x = Math.max(x, -(domElement.clientWidth * scale - domElement.clientWidth))
}
}

transform.x = x;
}

function setTransformY(y, scale = null) {
scale = scale || transform.scale;
scale = resolveTransformScale(scale);

if (options.bordered) {
if (y > 0) {
y = 0;
} else {
y = Math.max(y, -(domElement.clientHeight * scale - domElement.clientHeight))
}
}

transform.y = y;
}

function showRectangle(rect) {
// TODO: this duplicates autocenter. I think autocenter should go.
var clientRect = owner.getBoundingClientRect();
Expand All @@ -192,9 +238,9 @@ function createPanZoom(domElement, options) {
var dw = size.x / rectWidth;
var dh = size.y / rectHeight;
var scale = Math.min(dw, dh);
transform.x = -(rect.left + rectWidth / 2) * scale + size.x / 2;
transform.y = -(rect.top + rectHeight / 2) * scale + size.y / 2;
transform.scale = scale;
setTransformX(-(rect.left + rectWidth / 2) * scale + size.x / 2);
setTransformY(-(rect.top + rectHeight / 2) * scale + size.y / 2);
setTransformScale(scale);
}

function transformToScreen(x, y) {
Expand Down Expand Up @@ -241,9 +287,9 @@ function createPanZoom(domElement, options) {
var dh = h / bbox.height;
var dw = w / bbox.width;
var scale = Math.min(dw, dh);
transform.x = -(bbox.left + bbox.width / 2) * scale + w / 2 + left;
transform.y = -(bbox.top + bbox.height / 2) * scale + h / 2 + top;
transform.scale = scale;
setTransformX(-(bbox.left + bbox.width / 2) * scale + w / 2 + left, scale);
setTransformY(-(bbox.top + bbox.height / 2) * scale + h / 2 + top, scale);
setTransformScale(scale);
}

function getTransformModel() {
Expand Down Expand Up @@ -294,8 +340,8 @@ function createPanZoom(domElement, options) {
}

function moveTo(x, y) {
transform.x = x;
transform.y = y;
setTransformX(x);
setTransformY(y);

keepTransformInsideBounds();

Expand Down Expand Up @@ -412,16 +458,16 @@ function createPanZoom(domElement, options) {

var size = transformToScreen(clientX, clientY);

transform.x = size.x - ratio * (size.x - transform.x);
transform.y = size.y - ratio * (size.y - transform.y);
setTransformX(size.x - ratio * (size.x - transform.x), newScale);
setTransformY(size.y - ratio * (size.y - transform.y), newScale);

// TODO: https://github.com/anvaka/panzoom/issues/112
if (bounds && boundsPadding === 1 && minZoom === 1) {
transform.scale *= ratio;
setTransformScale(transform.scale * ratio);
keepTransformInsideBounds();
} else {
var transformAdjusted = keepTransformInsideBounds();
if (!transformAdjusted) transform.scale *= ratio;
if (!transformAdjusted) setTransformScale(transform.scale * ratio);
}

triggerEvent('zoom');
Expand Down Expand Up @@ -1327,12 +1373,12 @@ function makeSvgController(svgElement, options) {
}

function getBBox() {
var bbox = svgElement.getBBox();
var boundingBox = svgElement.getBBox();
return {
left: bbox.x,
top: bbox.y,
width: bbox.width,
height: bbox.height,
left: boundingBox.x,
top: boundingBox.y,
width: boundingBox.width,
height: boundingBox.height,
};
}

Expand Down Expand Up @@ -1574,7 +1620,7 @@ function makeAggregateRaf() {

var t = backBuffer;
backBuffer = frontBuffer;
frontBuffer = t;
frontBuffer = t;

frontBuffer.forEach(function(callback) {
callback();
Expand Down
2 changes: 1 addition & 1 deletion dist/panzoom.min.js

Large diffs are not rendered by default.

70 changes: 58 additions & 12 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ function createPanZoom(domElement, options) {
var maxZoom = typeof options.maxZoom === 'number' ? options.maxZoom : Number.POSITIVE_INFINITY;
var minZoom = typeof options.minZoom === 'number' ? options.minZoom : 0;

if (options.bordered && (!minZoom || minZoom < 1)) {
throw new Error('Cannot create bordered panzoom with minZoom less than 1');
}

var boundsPadding = typeof options.boundsPadding === 'number' ? options.boundsPadding : 0.05;
var zoomDoubleClickSpeed = typeof options.zoomDoubleClickSpeed === 'number' ? options.zoomDoubleClickSpeed : defaultDoubleTapZoomSpeed;
var beforeWheel = options.beforeWheel || noop;
Expand Down Expand Up @@ -177,6 +181,48 @@ function createPanZoom(domElement, options) {
return paused;
}

function resolveTransformScale(scale) {
if (minZoom) {
scale = Math.max(scale, minZoom)
}

return scale;
}

function setTransformScale(scale) {
transform.scale = resolveTransformScale(scale);
}

function setTransformX(x, scale = null) {
scale = scale || transform.scale;
scale = resolveTransformScale(scale);

if (options.bordered) {
if (x > 0) {
x = 0;
} else {
x = Math.max(x, -(domElement.clientWidth * scale - domElement.clientWidth))
}
}

transform.x = x;
}

function setTransformY(y, scale = null) {
scale = scale || transform.scale;
scale = resolveTransformScale(scale);

if (options.bordered) {
if (y > 0) {
y = 0;
} else {
y = Math.max(y, -(domElement.clientHeight * scale - domElement.clientHeight))
}
}

transform.y = y;
}

function showRectangle(rect) {
// TODO: this duplicates autocenter. I think autocenter should go.
var clientRect = owner.getBoundingClientRect();
Expand All @@ -191,9 +237,9 @@ function createPanZoom(domElement, options) {
var dw = size.x / rectWidth;
var dh = size.y / rectHeight;
var scale = Math.min(dw, dh);
transform.x = -(rect.left + rectWidth / 2) * scale + size.x / 2;
transform.y = -(rect.top + rectHeight / 2) * scale + size.y / 2;
transform.scale = scale;
setTransformX(-(rect.left + rectWidth / 2) * scale + size.x / 2);
setTransformY(-(rect.top + rectHeight / 2) * scale + size.y / 2);
setTransformScale(scale);
}

function transformToScreen(x, y) {
Expand Down Expand Up @@ -240,9 +286,9 @@ function createPanZoom(domElement, options) {
var dh = h / bbox.height;
var dw = w / bbox.width;
var scale = Math.min(dw, dh);
transform.x = -(bbox.left + bbox.width / 2) * scale + w / 2 + left;
transform.y = -(bbox.top + bbox.height / 2) * scale + h / 2 + top;
transform.scale = scale;
setTransformX(-(bbox.left + bbox.width / 2) * scale + w / 2 + left, scale);
setTransformY(-(bbox.top + bbox.height / 2) * scale + h / 2 + top, scale);
setTransformScale(scale);
}

function getTransformModel() {
Expand Down Expand Up @@ -293,8 +339,8 @@ function createPanZoom(domElement, options) {
}

function moveTo(x, y) {
transform.x = x;
transform.y = y;
setTransformX(x);
setTransformY(y);

keepTransformInsideBounds();

Expand Down Expand Up @@ -411,16 +457,16 @@ function createPanZoom(domElement, options) {

var size = transformToScreen(clientX, clientY);

transform.x = size.x - ratio * (size.x - transform.x);
transform.y = size.y - ratio * (size.y - transform.y);
setTransformX(size.x - ratio * (size.x - transform.x), newScale);
setTransformY(size.y - ratio * (size.y - transform.y), newScale);

// TODO: https://github.com/anvaka/panzoom/issues/112
if (bounds && boundsPadding === 1 && minZoom === 1) {
transform.scale *= ratio;
setTransformScale(transform.scale * ratio);
keepTransformInsideBounds();
} else {
var transformAdjusted = keepTransformInsideBounds();
if (!transformAdjusted) transform.scale *= ratio;
if (!transformAdjusted) setTransformScale(transform.scale * ratio);
}

triggerEvent('zoom');
Expand Down