Pinch to zoom with Hammer.js - javascript

I want a pinch to Zoom function for an image. I want it to zoom in the area where the fingers are.
My index is only
<div id="wrapper" style="-webkit-transform: translate3d(0,0,0);overflow: hidden;">
</div>
And my script for zooming and scrolling is similar with this example. I have made a few changes to fit with my project
My problem is in
case 'transform':
rotation = last_rotation + ev.gesture.rotation;
scale = Math.max(1, Math.min(last_scale * ev.gesture.scale, 10));
break;
How can I change it so that it doesn't zoom into the center of the picture but at place where the first finger have touch the display?
Sorry for my bad english :)

This is an example with hammer.js and tap. As you tap it will zoom in at the point where you tapped. The event data is common for all gestures so switching from tap to pinch should work. It is a good example to work on. You may need to increase the scale step as you pinch. It has been tested on chrome(v30) and firefox (v24).
It is based on the solution mentioned at the thread,
Zoom in on a point (using scale and translate)
as you will see an alternative could also be to use canvas.
HTML
<div style="-webkit-transform: translate3d(0,0,0);overflow: hidden;" class="zoomable">
<img src="http://i.telegraph.co.uk/multimedia/archive/01842/landscape-rainbow_1842437i.jpg" />
</div>
JS
(function ($) {
$(document).ready(function () {
var scale = 1; // scale of the image
var xLast = 0; // last x location on the screen
var yLast = 0; // last y location on the screen
var xImage = 0; // last x location on the image
var yImage = 0; // last y location on the image
Hammer($('.zoomable img').get(0)).on("tap", function (event) {
var posX = event.gesture.center.pageX;
var posY = event.gesture.center.pageY;
// find current location on screen
var xScreen = posX; //- $(this).offset().left;
var yScreen = posY; //- $(this).offset().top;
// find current location on the image at the current scale
xImage = xImage + ((xScreen - xLast) / scale);
yImage = yImage + ((yScreen - yLast) / scale);
scale++;
// determine the location on the screen at the new scale
var xNew = (xScreen - xImage) / scale;
var yNew = (yScreen - yImage) / scale;
// save the current screen location
xLast = xScreen;
yLast = yScreen;
// redraw
$(this).css('-webkit-transform', 'scale(' + scale + ')' + 'translate(' + xNew + 'px, ' + yNew + 'px' + ')')
.css('-webkit-transform-origin', xImage + 'px ' + yImage + 'px').css('-moz-transform', 'scale(' + scale + ') translate(' + xNew + 'px, ' + yNew + 'px)').css('-moz-transform-origin', xImage + 'px ' + yImage + 'px')
.css('-o-transform', 'scale(' + scale + ') translate(' + xNew + 'px, ' + yNew + 'px)').css('-o-transform-origin', xImage + 'px ' + yImage + 'px').css('transform', 'scale(' + scale + ') translate(' + xNew + 'px, ' + yNew + 'px)');
});
});
})(jQuery);
http://jsfiddle.net/SySZL/

Check out the Pinch Zoom and Pan with HammerJS demo. This example has been tested on Android, iOS and Windows Phone.
You can find the source code at Pinch Zoom and Pan with HammerJS.
For your convenience, here is the source code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport"
content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
<title>Pinch Zoom</title>
</head>
<body>
<div>
<div style="height:150px;background-color:#eeeeee">
Ignore this area. Space is needed to test on the iPhone simulator as pinch simulation on the
iPhone simulator requires the target to be near the middle of the screen and we only respect
touch events in the image area. This space is not needed in production.
</div>
<style>
.pinch-zoom-container {
overflow: hidden;
height: 300px;
}
.pinch-zoom-image {
width: 100%;
}
</style>
<script src="https://hammerjs.github.io/dist/hammer.js"></script>
<script>
var MIN_SCALE = 1; // 1=scaling when first loaded
var MAX_SCALE = 64;
// HammerJS fires "pinch" and "pan" events that are cumulative in nature and not
// deltas. Therefore, we need to store the "last" values of scale, x and y so that we can
// adjust the UI accordingly. It isn't until the "pinchend" and "panend" events are received
// that we can set the "last" values.
// Our "raw" coordinates are not scaled. This allows us to only have to modify our stored
// coordinates when the UI is updated. It also simplifies our calculations as these
// coordinates are without respect to the current scale.
var imgWidth = null;
var imgHeight = null;
var viewportWidth = null;
var viewportHeight = null;
var scale = null;
var lastScale = null;
var container = null;
var img = null;
var x = 0;
var lastX = 0;
var y = 0;
var lastY = 0;
var pinchCenter = null;
// We need to disable the following event handlers so that the browser doesn't try to
// automatically handle our image drag gestures.
var disableImgEventHandlers = function () {
var events = ['onclick', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover',
'onmouseup', 'ondblclick', 'onfocus', 'onblur'];
events.forEach(function (event) {
img[event] = function () {
return false;
};
});
};
// Traverse the DOM to calculate the absolute position of an element
var absolutePosition = function (el) {
var x = 0,
y = 0;
while (el !== null) {
x += el.offsetLeft;
y += el.offsetTop;
el = el.offsetParent;
}
return { x: x, y: y };
};
var restrictScale = function (scale) {
if (scale < MIN_SCALE) {
scale = MIN_SCALE;
} else if (scale > MAX_SCALE) {
scale = MAX_SCALE;
}
return scale;
};
var restrictRawPos = function (pos, viewportDim, imgDim) {
if (pos < viewportDim/scale - imgDim) { // too far left/up?
pos = viewportDim/scale - imgDim;
} else if (pos > 0) { // too far right/down?
pos = 0;
}
return pos;
};
var updateLastPos = function (deltaX, deltaY) {
lastX = x;
lastY = y;
};
var translate = function (deltaX, deltaY) {
// We restrict to the min of the viewport width/height or current width/height as the
// current width/height may be smaller than the viewport width/height
var newX = restrictRawPos(lastX + deltaX/scale,
Math.min(viewportWidth, curWidth), imgWidth);
x = newX;
img.style.marginLeft = Math.ceil(newX*scale) + 'px';
var newY = restrictRawPos(lastY + deltaY/scale,
Math.min(viewportHeight, curHeight), imgHeight);
y = newY;
img.style.marginTop = Math.ceil(newY*scale) + 'px';
};
var zoom = function (scaleBy) {
scale = restrictScale(lastScale*scaleBy);
curWidth = imgWidth*scale;
curHeight = imgHeight*scale;
img.style.width = Math.ceil(curWidth) + 'px';
img.style.height = Math.ceil(curHeight) + 'px';
// Adjust margins to make sure that we aren't out of bounds
translate(0, 0);
};
var rawCenter = function (e) {
var pos = absolutePosition(container);
// We need to account for the scroll position
var scrollLeft = window.pageXOffset ? window.pageXOffset : document.body.scrollLeft;
var scrollTop = window.pageYOffset ? window.pageYOffset : document.body.scrollTop;
var zoomX = -x + (e.center.x - pos.x + scrollLeft)/scale;
var zoomY = -y + (e.center.y - pos.y + scrollTop)/scale;
return { x: zoomX, y: zoomY };
};
var updateLastScale = function () {
lastScale = scale;
};
var zoomAround = function (scaleBy, rawZoomX, rawZoomY, doNotUpdateLast) {
// Zoom
zoom(scaleBy);
// New raw center of viewport
var rawCenterX = -x + Math.min(viewportWidth, curWidth)/2/scale;
var rawCenterY = -y + Math.min(viewportHeight, curHeight)/2/scale;
// Delta
var deltaX = (rawCenterX - rawZoomX)*scale;
var deltaY = (rawCenterY - rawZoomY)*scale;
// Translate back to zoom center
translate(deltaX, deltaY);
if (!doNotUpdateLast) {
updateLastScale();
updateLastPos();
}
};
var zoomCenter = function (scaleBy) {
// Center of viewport
var zoomX = -x + Math.min(viewportWidth, curWidth)/2/scale;
var zoomY = -y + Math.min(viewportHeight, curHeight)/2/scale;
zoomAround(scaleBy, zoomX, zoomY);
};
var zoomIn = function () {
zoomCenter(2);
};
var zoomOut = function () {
zoomCenter(1/2);
};
var onLoad = function () {
img = document.getElementById('pinch-zoom-image-id');
container = img.parentElement;
disableImgEventHandlers();
imgWidth = img.width;
imgHeight = img.height;
viewportWidth = img.offsetWidth;
scale = viewportWidth/imgWidth;
lastScale = scale;
viewportHeight = img.parentElement.offsetHeight;
curWidth = imgWidth*scale;
curHeight = imgHeight*scale;
var hammer = new Hammer(container, {
domEvents: true
});
hammer.get('pinch').set({
enable: true
});
hammer.on('pan', function (e) {
translate(e.deltaX, e.deltaY);
});
hammer.on('panend', function (e) {
updateLastPos();
});
hammer.on('pinch', function (e) {
// We only calculate the pinch center on the first pinch event as we want the center to
// stay consistent during the entire pinch
if (pinchCenter === null) {
pinchCenter = rawCenter(e);
var offsetX = pinchCenter.x*scale - (-x*scale + Math.min(viewportWidth, curWidth)/2);
var offsetY = pinchCenter.y*scale - (-y*scale + Math.min(viewportHeight, curHeight)/2);
pinchCenterOffset = { x: offsetX, y: offsetY };
}
// When the user pinch zooms, she/he expects the pinch center to remain in the same
// relative location of the screen. To achieve this, the raw zoom center is calculated by
// first storing the pinch center and the scaled offset to the current center of the
// image. The new scale is then used to calculate the zoom center. This has the effect of
// actually translating the zoom center on each pinch zoom event.
var newScale = restrictScale(scale*e.scale);
var zoomX = pinchCenter.x*newScale - pinchCenterOffset.x;
var zoomY = pinchCenter.y*newScale - pinchCenterOffset.y;
var zoomCenter = { x: zoomX/newScale, y: zoomY/newScale };
zoomAround(e.scale, zoomCenter.x, zoomCenter.y, true);
});
hammer.on('pinchend', function (e) {
updateLastScale();
updateLastPos();
pinchCenter = null;
});
hammer.on('doubletap', function (e) {
var c = rawCenter(e);
zoomAround(2, c.x, c.y);
});
};
</script>
<button onclick="zoomIn()">Zoom In</button>
<button onclick="zoomOut()">Zoom Out</button>
<div class="pinch-zoom-container">
<img id="pinch-zoom-image-id" class="pinch-zoom-image" onload="onLoad()"
src="https://hammerjs.github.io/assets/img/pano-1.jpg">
</div>
</div>
</body>
</html>

Related

JointJS: item added to incorrect position after panning paperScroller

I'm having trouble to get the correct position to items added to the graph after moving items to a new area on the left side of the paper.
Function called when the item is drop on the canvas.
function drop(ev) {
ev.preventDefault();
// CANVAS ELEMENT DROP
var data = ev.dataTransfer.getData("text");
console.log('ev.pageX: ' + ev.pageX);
console.log('$(paper-container).offset().left: ' + $('#paper-container').offset().left);
console.log('$(.joint-paper).position().left: ' + $('.joint-paper').position().left);
console.log('ev.pageY: ' + ev.pageY);
console.log('$(paper-container).offset().top: ' + $('#paper-container').offset().top);
console.log('$(.joint-paper).position().top: ' + $('.joint-paper').position().top);
var x = ev.pageX - $('#paper-container').offset().left - $('.joint-paper').position().left;
var y = ev.pageY - $('#paper-container').offset().top - $('.joint-paper').position().top;
addCanvasItem(x, y);
}
Then adding item to the canvas:
function addCanvasItem(x, y) {
//x and y are in the screen referential
var zoomRatio = vm.paperScroller.zoom();
var scrollX = vm.paperScroller.el.scrollLeft;
var scrollY = vm.paperScroller.el.scrollTop;
var posX = x / zoomRatio + scrollX / zoomRatio - 50;
var posY = y / zoomRatio + scrollY / zoomRatio - 30;
item.attributes.position = { x: posX, y: posY };
item.addTo(vm.graph);
var cellView = item.findView(vm.paper);
rappidJsConfig.resetSelection([cellView.model]);
vm.selectedView = cellView;
vm.initEditor();
if (vm.isVisibleType('qad.Question')) {
var selectedQuestion = document.getElementById("selected-question");
if (selectedQuestion) {
selectedQuestion.focus();
}
}
};
Any ideas ?

Zoom based on cursor using javascript

I've both tried to solve the problem as well as search StackOverflow for multiple solutions, none that seemed to work properly. I have what appears to be a close but not quite the end result I'm looking for. I'm trying to make it so when the user zooms using the mousewheel, the zoom being based on the cursor's position.
Could someone explain what I'm doing wrong here. Somewhere in my calculation for the image offset im doing something wrong which you'll see when you test it.
// offset image based on cursor position
var width = img_ele.getBoundingClientRect().width;
var height = img_ele.getBoundingClientRect().height;
var x_cursor = window.event.clientX;
var y_cursor = window.event.clientY;
var x = img_ele.offsetLeft;
var y = img_ele.offsetTop;
// Calculate displacement of zooming position.
var dx = x - ((x_cursor - x) * (factor - 1.0));
var dy = y - ((y_cursor - y) * (factor - 1.0));
img_ele.style.left = dx + 'px';
img_ele.style.top = dy + 'px';
Below is the full code. Just change the src image to one of your liking.
<!DOCTYPE html>
<html>
<body>
<div id="container">
<img ondragstart="return false" id="drag-img" src="map.jpg" />
</div>
<input type="button" id="zoomout" class="button" value="Zoom out">
<input type="button" id="zoomin" class="button" value="Zoom in">
<input type="button" id="zoomfit" class="button" value="Zoom fit">
</body>
</html>
<script>
var img_ele = null,
x_cursor = 0,
y_cursor = 0,
x_img_ele = 0,
y_img_ele = 0;
function zoom(factor) {
img_ele = document.getElementById('drag-img');
// Zoom into the image.
var width = img_ele.getBoundingClientRect().width;
var height = img_ele.getBoundingClientRect().height;
img_ele.style.width = (width * factor) + 'px';
img_ele.style.height = (height * factor) + 'px';
// offset image based on cursor position
var width = img_ele.getBoundingClientRect().width;
var height = img_ele.getBoundingClientRect().height;
var x_cursor = window.event.clientX;
var y_cursor = window.event.clientY;
var x = img_ele.offsetLeft;
var y = img_ele.offsetTop;
// Calculate displacement of zooming position.
var dx = x - ((x_cursor - x) * (factor - 1.0));
var dy = y - ((y_cursor - y) * (factor - 1.0));
img_ele.style.left = dx + 'px';
img_ele.style.top = dy + 'px';
console.log('MAP SIZE : ' + width, height);
console.log('MAP TOP/LEFT : ' + x, y, 'NEW:', dx, dy);
console.log('CURSOR : ' + x_cursor, y_cursor);
img_ele = null;
}
function zoom_fit() {
bb_el = document.getElementById('container')
img_el = document.getElementById('drag-img');
var width = bb_el.getBoundingClientRect().width;
var height = bb_el.getBoundingClientRect().height;
img_el.style.width = width + 'px';
img_el.style.height = height + 'px';
img_el.style.left = '0px';
img_el.style.top = '0px';
img_el = null;
}
document.getElementById('zoomout').addEventListener('click', function() {
zoom(0.9);
});
document.getElementById('zoomin').addEventListener('click', function() {
zoom(1.1);
});
document.getElementById('zoomfit').addEventListener('click', function() {
zoom_fit();
});
document.addEventListener('mousewheel', function(event) {
event.preventDefault();
x_cursor = window.event.clientX;
y_cursor = window.event.clientY;
// console.log('ZOOM : ' + 'X:', x_cursor, 'Y:', y_cursor);
if (event.deltaY < 0) {
// console.log('scrolling up');
zoom(1.1);
}
if (event.deltaY > 0) {
// console.log('scrolling down');
zoom(0.9);
}
});
function start_drag() {
img_ele = this;
// console.log('inside start_drag var img_ele set to : ' + this);
x_img_ele = window.event.clientX - document.getElementById('drag-img').offsetLeft;
y_img_ele = window.event.clientY - document.getElementById('drag-img').offsetTop;
// console.log('start_drag : ' + 'x_img_ele:', x_img_ele, 'y_img_ele:', y_img_ele);
}
function stop_drag() {
// console.log('stop drag');
img_ele = null;
}
function while_drag() {
// console.log('while_drag: ', window.event);
var x_cursor = window.event.clientX;
var y_cursor = window.event.clientY;
if (img_ele !== null) {
img_ele.style.left = (x_cursor - x_img_ele) + 'px';
img_ele.style.top = ( window.event.clientY - y_img_ele) + 'px';
// console.log('while_drag: ','x_cursor', x_cursor, 'x_img_ele', x_img_ele, 'y_cursor', y_cursor, 'y_img_ele', y_img_ele,'Image left and top', img_ele.style.left+' - '+img_ele.style.top);
}
}
document.getElementById('drag-img').addEventListener('mousedown', start_drag);
document.getElementById('container').addEventListener('mousemove', while_drag);
document.getElementById('container').addEventListener('mouseup', stop_drag);
function while_drag() {
var x_cursor = window.event.clientX;
var y_cursor = window.event.clientY;
if (img_ele !== null) {
img_ele.style.left = (x_cursor - x_img_ele) + 'px';
img_ele.style.top = ( window.event.clientY - y_img_ele) + 'px';
// console.log(img_ele.style.left+' - '+img_ele.style.top);
}
}
document.getElementById('drag-img').addEventListener('mousedown', start_drag);
document.getElementById('container').addEventListener('mousemove', while_drag);
document.getElementById('container').addEventListener('mouseup', stop_drag);
</script>
<style>
#drag-img {
cursor: move;
position: relative;
width: 400px;
height: 400px;
}
#container {
overflow: hidden;
background: red;
width: 400px;
height: 400px;
}
.button {
width: 80px;
height: 25px;
}
</style>

Pinch zoom on PDF.js using Hammer.js

I am trying to use Hammer.js to perform a pinch zoom with my PDF.js, however, it doesn't work, despite much tries. I didn't get any errors when I debug my codes on my mobile as well, but I just still can't pinch to zoom in and out. Please help if you know what went wrong, my codes are as shown below:
HTML:
<body>
<script type="text/javascript" src="reportviewer/hammer.js"></script>
<script>
var MIN_SCALE = 1; // 1=scaling when first loaded
var MAX_SCALE = 64;
// HammerJS fires "pinch" and "pan" events that are cumulative in nature and not
// deltas. Therefore, we need to store the "last" values of scale, x and y so that we can
// adjust the UI accordingly. It isn't until the "pinchend" and "panend" events are received
// that we can set the "last" values.
// Our "raw" coordinates are not scaled. This allows us to only have to modify our stored
// coordinates when the UI is updated. It also simplifies our calculations as these
// coordinates are without respect to the current scale.
var imgWidth = null;
var imgHeight = null;
var viewportWidth = null;
var viewportHeight = null;
var scale = null;
var lastScale = null;
var container = null;
var img = null;
var x = 0;
var lastX = 0;
var y = 0;
var lastY = 0;
var pinchCenter = null;
// We need to disable the following event handlers so that the browser doesn't try to
// automatically handle our image drag gestures.
var disableImgEventHandlers = function () {
var events = ['onclick', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover',
'onmouseup', 'ondblclick', 'onfocus', 'onblur'];
events.forEach(function (event) {
img[event] = function () {
return false;
};
});
};
// Traverse the DOM to calculate the absolute position of an element
var absolutePosition = function (el) {
var x = 0,
y = 0;
while (el !== null) {
x += el.offsetLeft;
y += el.offsetTop;
el = el.offsetParent;
}
return { x: x, y: y };
};
var restrictScale = function (scale) {
if (scale < MIN_SCALE) {
scale = MIN_SCALE;
} else if (scale > MAX_SCALE) {
scale = MAX_SCALE;
}
return scale;
};
var restrictRawPos = function (pos, viewportDim, imgDim) {
if (pos < viewportDim / scale - imgDim) { // too far left/up?
pos = viewportDim / scale - imgDim;
} else if (pos > 0) { // too far right/down?
pos = 0;
}
return pos;
};
var updateLastPos = function (deltaX, deltaY) {
lastX = x;
lastY = y;
};
var translate = function (deltaX, deltaY) {
// We restrict to the min of the viewport width/height or current width/height as the
// current width/height may be smaller than the viewport width/height
var newX = restrictRawPos(lastX + deltaX / scale,
Math.min(viewportWidth, curWidth), imgWidth);
x = newX;
img.style.marginLeft = Math.ceil(newX * scale) + 'px';
var newY = restrictRawPos(lastY + deltaY / scale,
Math.min(viewportHeight, curHeight), imgHeight);
y = newY;
img.style.marginTop = Math.ceil(newY * scale) + 'px';
};
var zoom = function (scaleBy) {
scale = restrictScale(lastScale * scaleBy);
curWidth = imgWidth * scale;
curHeight = imgHeight * scale;
img.style.width = Math.ceil(curWidth) + 'px';
img.style.height = Math.ceil(curHeight) + 'px';
// Adjust margins to make sure that we aren't out of bounds
translate(0, 0);
};
var rawCenter = function (e) {
var pos = absolutePosition(container);
// We need to account for the scroll position
var scrollLeft = window.pageXOffset ? window.pageXOffset : document.body.scrollLeft;
var scrollTop = window.pageYOffset ? window.pageYOffset : document.body.scrollTop;
var zoomX = -x + (e.center.x - pos.x + scrollLeft) / scale;
var zoomY = -y + (e.center.y - pos.y + scrollTop) / scale;
return { x: zoomX, y: zoomY };
};
var updateLastScale = function () {
lastScale = scale;
};
var zoomAround = function (scaleBy, rawZoomX, rawZoomY, doNotUpdateLast) {
// Zoom
zoom(scaleBy);
// New raw center of viewport
var rawCenterX = -x + Math.min(viewportWidth, curWidth) / 2 / scale;
var rawCenterY = -y + Math.min(viewportHeight, curHeight) / 2 / scale;
// Delta
var deltaX = (rawCenterX - rawZoomX) * scale;
var deltaY = (rawCenterY - rawZoomY) * scale;
// Translate back to zoom center
translate(deltaX, deltaY);
if (!doNotUpdateLast) {
updateLastScale();
updateLastPos();
}
};
var zoomCenter = function (scaleBy) {
// Center of viewport
var zoomX = -x + Math.min(viewportWidth, curWidth) / 2 / scale;
var zoomY = -y + Math.min(viewportHeight, curHeight) / 2 / scale;
zoomAround(scaleBy, zoomX, zoomY);
};
var zoomIn = function () {
zoomCenter(2);
};
var zoomOut = function () {
zoomCenter(1 / 2);
};
var onLoad = function () {
img = document.getElementById('pinchzoom');
container = img.parentElement;
disableImgEventHandlers();
imgWidth = img.width;
imgHeight = img.height;
viewportWidth = img.parentElement.offsetWidth;
scale = viewportWidth / imgWidth;
lastScale = scale;
viewportHeight = img.parentElement.offsetHeight;
curWidth = imgWidth * scale;
curHeight = imgHeight * scale;
var hammer = new Hammer(container, {
domEvents: true
});
hammer.get('pinch').set({
enable: true
});
hammer.on('pan', function (e) {
translate(e.deltaX, e.deltaY);
});
hammer.on('panend', function (e) {
updateLastPos();
});
hammer.on('pinch', function (e) {
// We only calculate the pinch center on the first pinch event as we want the center to
// stay consistent during the entire pinch
if (pinchCenter === null) {
pinchCenter = rawCenter(e);
var offsetX = pinchCenter.x * scale - (-x * scale + Math.min(viewportWidth, curWidth) / 2);
var offsetY = pinchCenter.y * scale - (-y * scale + Math.min(viewportHeight, curHeight) / 2);
pinchCenterOffset = { x: offsetX, y: offsetY };
}
// When the user pinch zooms, she/he expects the pinch center to remain in the same
// relative location of the screen. To achieve this, the raw zoom center is calculated by
// first storing the pinch center and the scaled offset to the current center of the
// image. The new scale is then used to calculate the zoom center. This has the effect of
// actually translating the zoom center on each pinch zoom event.
var newScale = restrictScale(scale * e.scale);
var zoomX = pinchCenter.x * newScale - pinchCenterOffset.x;
var zoomY = pinchCenter.y * newScale - pinchCenterOffset.y;
var zoomCenter = { x: zoomX / newScale, y: zoomY / newScale };
zoomAround(e.scale, zoomCenter.x, zoomCenter.y, true);
});
hammer.on('pinchend', function (e) {
updateLastScale();
updateLastPos();
pinchCenter = null;
});
hammer.on('doubletap', function (e) {
var c = rawCenter(e);
zoomAround(2, c.x, c.y);
});
};
</script>
</body>
View:
<div data-options="dxView : { name: 'myViewer', title: 'My Viewer', disableCache: true } ">
<div data-options="dxContent : { targetPlaceholder: 'content' } " class="dx-content-background">
<div>
<iframe onload="onLoad()" data-bind="attr: { src: EmbedPDFLink }" class="viewReport"/>
</div>
</div>
not for hammer.js... but you can use (not-ready-for-production) SVG backend to render stuff into DOM so you don't need to deal with repainting canvas all the time yourself. Based on https://github.com/mozilla/pdf.js/blob/master/examples/components/pageviewer.html :
var url = "https://cdn.mozilla.net/pdfjs/tracemonkey.pdf";
var PAGE_TO_VIEW = 1;
var SCALE = 1.0;
var container = document.getElementById('container');
// Load document
PDFJS.getDocument(url).then(function (doc) {
return doc.getPage(PAGE_TO_VIEW).then(function (pdfPage) {
// Add div with page view.
var pdfPageView = new PDFJS.PDFPageView({
container: container,
renderer: 'svg',
id: PAGE_TO_VIEW,
scale: SCALE,
defaultViewport: pdfPage.getViewport(SCALE),
// We can enable text/annotations layers, if needed
textLayerFactory: new PDFJS.DefaultTextLayerFactory(),
annotationLayerFactory: new PDFJS.DefaultAnnotationLayerFactory()
});
// Associates the actual page with the view, and drawing it
pdfPageView.setPdfPage(pdfPage);
return pdfPageView.draw();
});
});
<link href="https://npmcdn.com/pdfjs-dist/web/pdf_viewer.css" rel="stylesheet"/>
<script src="https://npmcdn.com/pdfjs-dist/web/compatibility.js"></script>
<script src="https://npmcdn.com/pdfjs-dist/build/pdf.js"></script>
<script src="https://npmcdn.com/pdfjs-dist/web/pdf_viewer.js"></script>
<div id="container" class="pdfViewer singlePageView"></div>

Konva events mis-positioned after screen resize

In my code I am resizing the Konva canvas and the konvajs-content elements to maintain a full screen appearance.
resizeCanvas()
window.onresize = function() { resizeCanvas(); }
function resizeCanvas() {
var w = window,
d = document,
e = d.documentElement,
g = d.getElementsByTagName('body')[0],
x = w.innerWidth || e.clientWidth || g.clientWidth,
y = w.innerHeight || e.clientHeight || g.clientHeight;
var ratio = x / y;
var should = 1920 / 1080;
var cv = document.getElementsByTagName("canvas")[0];
var cc = document.getElementsByClassName("konvajs-content")[0];
var cx, cy;
var cleft=0;
if(ratio > should) {
cx = (y * 1920/1080);
cy = y;
cleft = (x - cx) / 2;
} else {
cx = x;
cy = (x * 1080/1920);
cv.setAttribute("style", "width:" + x + "px;height:"+ (x*1080/1920) + "px;");
}
cc.setAttribute("style", "width:" + x + "px;height: " + y + "px;");
cv.setAttribute("style", "width:" + cx + "px;heigth: " + cy + "px; position: relative; left: " + cleft + "px");
}
This all works great until I try to capture any event input. As you can see in the JSFiddle, when trying to click on the 'Test' text you will not cause an event to fire.
But if you click ~40px to the left and 20px above the text you will fire the events.
https://jsfiddle.net/3qc3wtr3/2/
Is there a way to keep the resize behavior and to ensure that events are being fired based on the actual location of the elements?
You should use stage.width() and stage.height() to fit a page. You can add scale into stage if you need.

JQuery Listener on Canvas Child doesn't work

i have a problem i'm implementing a crop custom rectangle on a canvas i made a function in Javascript that when the crop function is called the create on existing canvas a child and then with the JQuery listener i draw the rectangle.The childNode is create correctly while the listener don't work they don't get the events. This is my code:
var dragging = false;
var xstart = 0;
var ystart = 0;
var width = 0;
var height = 0;
var ctxotmp = null;
var ctxtmp = null;
var canvastmp = null;
var mycanvas = null;
function draw() {
ctxtmp.fillRect(xstart, ystart, width, height);
}
function init() {
mycanvas = $('#mycanvas')[0];
// create temp canvas
canvastmp = document.createElement('canvas');
canvastmp.id = "mycanvastmp";
canvastmp.width = mycanvas.width;
canvastmp.height = mycanvas.height;
mycanvas.parentNode.appendChild(canvastmp);
$("#mycanvastmp").css({position:"absolute",top:$("#mycanvas").css("top"),left:$("#mycanvas").css("left")});
canvastmp = $('#mycanvastmp')[0];
ctxtmp = canvastmp.getContext('2d');
ctxtmp.lineWidth = 1;
ctxtmp.fillStyle = "rgba(0, 0, 0, 0.5)";
}
//listener
$('#mycanvastmp').mousedown(function(e) {
var xoffs = $(this).offset().left;
var yoffs = $(this).offset().top;
xstart = e.pageX - xoffs;
ystart = e.pageY - yoffs;
dragging = true;
});
$('#mycanvastmp').mousemove(function(e) {
if(dragging) {
var xoffs = $(this).offset().left;
var yoffs = $(this).offset().top;
width = e.pageX - xoffs - xstart;
height = e.pageY - yoffs - ystart;
ctxtmp.clearRect(0, 0, $(this).width(), $(this).height());
draw();
}
});
$('#mycanvastmp').mouseup(function() {
dragging=false;
alert('The rectangle for crop (x, y, width, height): ' + xstart + ', ' + ystart + ', ' + width + ', ' + height);
});
Someone can help me?
Looks like you're attaching the events before the temp canvas is created.
Either attach the events in the init() function after adding the temp canvas to the DOM or use .delegate() or .on()
$("#mycanvas").on("mouseup", "#mycanvastmp", function() {
//...
});
You need to use .on on method in order to bind events to dynamically created objects. When your page initially loads and the dom fires, it doesn't see tempCanvas so it doesn't attach them initially.
//listener
$('body').on('mousedown' ,'#mycanvastmp', function(e) {
var xoffs = $(this).offset().left;
var yoffs = $(this).offset().top;
xstart = e.pageX - xoffs;
ystart = e.pageY - yoffs;
dragging = true;
});
$('body').on('mousemove' ,'#mycanvastmp', function(e) {
if(dragging) {
var xoffs = $(this).offset().left;
var yoffs = $(this).offset().top;
width = e.pageX - xoffs - xstart;
height = e.pageY - yoffs - ystart;
ctxtmp.clearRect(0, 0, $(this).width(), $(this).height());
draw();
}
});
$('body').on('mouseup' ,'#mycanvastmp', function(e) {
dragging=false;
alert('The rectangle for crop (x, y, width, height): ' + xstart + ', ' + ystart + ', ' + width + ', ' + height);
});
init();
Live Demo

Categories

Resources